From 069c2ceddf886135e7f86edff3673535c16f6dd9 Mon Sep 17 00:00:00 2001 From: Gavriil Sitnikov Date: Tue, 24 Jan 2017 20:32:01 +0300 Subject: [PATCH 01/11] validation initial logic added --- .../BooleanValidationController.java | 51 +++++++ .../validation/ConversionException.java | 27 ++++ .../EditTextValidationController.java | 78 +++++++++++ .../validation/EditTextValidator.java | 126 ++++++++++++++++++ .../validation/SameTypeValidator.java | 17 +++ .../SimpleValidationController.java | 28 ++++ .../TwoWayValidationController.java | 70 ++++++++++ .../validation/ValidationController.java | 42 ++++++ .../templates/validation/ValidationState.java | 50 +++++++ .../templates/validation/Validator.java | 63 +++++++++ .../templates/validation/ViewWithError.java | 34 +++++ 11 files changed, 586 insertions(+) create mode 100644 src/main/java/ru/touchin/templates/validation/BooleanValidationController.java create mode 100644 src/main/java/ru/touchin/templates/validation/ConversionException.java create mode 100644 src/main/java/ru/touchin/templates/validation/EditTextValidationController.java create mode 100644 src/main/java/ru/touchin/templates/validation/EditTextValidator.java create mode 100644 src/main/java/ru/touchin/templates/validation/SameTypeValidator.java create mode 100644 src/main/java/ru/touchin/templates/validation/SimpleValidationController.java create mode 100644 src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java create mode 100644 src/main/java/ru/touchin/templates/validation/ValidationController.java create mode 100644 src/main/java/ru/touchin/templates/validation/ValidationState.java create mode 100644 src/main/java/ru/touchin/templates/validation/Validator.java create mode 100644 src/main/java/ru/touchin/templates/validation/ViewWithError.java diff --git a/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java b/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java new file mode 100644 index 0000000..903484c --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; + +import rx.Observable; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public class BooleanValidationController extends TwoWayValidationController> { + + public BooleanValidationController(@NonNull final SameTypeValidator validationWrapper) { + super(validationWrapper); + } + + @NonNull + public Observable validation(@NonNull final Observable activatedObservable) { + return Observable.combineLatest(activatedObservable, getValidationWrapper().getWrapperModel().observe(), + (activated, flag) -> { + final boolean selected = flag == null ? false : flag; + if (activated && !selected) { + return ValidationState.ERROR_NO_DESCRIPTION; + } else if (!activated && !selected) { + return ValidationState.INITIAL; + } + return ValidationState.VALID; + }) + .doOnNext(validationState -> getValidationWrapper().getValidationState().set(validationState)); + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ConversionException.java b/src/main/java/ru/touchin/templates/validation/ConversionException.java new file mode 100644 index 0000000..e705851 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/ConversionException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public class ConversionException extends Exception { +} diff --git a/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java b/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java new file mode 100644 index 0000000..62ea68b --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import java.io.Serializable; + +import ru.touchin.roboswag.core.utils.pairs.NonNullPair; +import rx.Observable; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public class EditTextValidationController + extends TwoWayValidationController> { + + public EditTextValidationController(@NonNull final EditTextValidator validationWrapper) { + super(validationWrapper); + } + + @NonNull + public Observable validation(@NonNull final Observable focusOutObservable, @NonNull final Observable activatedObservable) { + return Observable + .>>combineLatest(activatedObservable, + getValidationWrapper().getWrapperModel().observe(), + focusOutObservable, + getValidationWrapper().getShowFullCheck().observe(), + (activated, text, focusIn, showError) -> { + if (focusIn == null && TextUtils.isEmpty(text) && !activated && !showError) { + return null; + } + final boolean focus = focusIn == null ? false : focusIn; + if (TextUtils.isEmpty(text)) { + return new NonNullPair<>(focus, (activated || showError) + ? getValidationWrapper().getValidationStateWhenEmpty().observe() + .map(state -> state != null ? state : ValidationState.ERROR_NO_DESCRIPTION) + : Observable.just(ValidationState.INITIAL)); + } + if (!showError && focus) { + return new NonNullPair<>(true, getValidationWrapper().primaryValidate(text)); + } + return new NonNullPair<>(focus, getValidationWrapper().fullValidate(text)); + }) + .switchMap(validationPair -> { + if (validationPair == null) { + return Observable.empty(); + } + return validationPair.getSecond() + .doOnNext(validationState -> { + if (!validationPair.getFirst()) { + getValidationWrapper().getShowFullCheck().set(validationState != ValidationState.VALID); + } + getValidationWrapper().getValidationState().set(validationState); + }); + }); + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/EditTextValidator.java new file mode 100644 index 0000000..20425a8 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/EditTextValidator.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.io.Serializable; + +import ru.touchin.roboswag.core.log.Lc; +import ru.touchin.roboswag.core.observables.Changeable; +import ru.touchin.roboswag.core.observables.NonNullChangeable; +import ru.touchin.roboswag.core.utils.pairs.HalfNullablePair; +import rx.Observable; +import rx.exceptions.OnErrorThrowable; +import rx.functions.Func1; +import rx.schedulers.Schedulers; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public abstract class EditTextValidator extends Validator { + + @NonNull + private final NonNullChangeable showFullCheck = new NonNullChangeable<>(false); + @NonNull + private final Changeable>> finalCheck = new Changeable<>(null); + @NonNull + private final Changeable>> primaryCheck = new Changeable<>(null); + + @NonNull + public NonNullChangeable getShowFullCheck() { + return showFullCheck; + } + + @Nullable + public Changeable>> getFinalCheck() { + return finalCheck; + } + + @Nullable + public Changeable>> getPrimaryCheck() { + return primaryCheck; + } + + @NonNull + private HalfNullablePair validateText( + @Nullable final Func1> finalCheck, + @Nullable final Func1> primaryCheck, + @NonNull final String text, final boolean fullCheck) + throws ConversionException { + if (primaryCheck == null && finalCheck == null) { + return new HalfNullablePair<>(ValidationState.VALID, convertWrapperModelToModel(text)); + } + + if (primaryCheck != null) { + final HalfNullablePair primaryPair = primaryCheck.call(text); + if (finalCheck == null || primaryPair.getFirst() != ValidationState.VALID || primaryPair.getSecond() == null || !fullCheck) { + return primaryPair; + } + return finalCheck.call(primaryPair.getSecond()); + } + return finalCheck.call(convertWrapperModelToModel(text)); + } + + @NonNull + private Observable> createValidationObservable(@NonNull final String text, final boolean fullCheck) { + return Observable + .combineLatest(finalCheck.observe().observeOn(Schedulers.computation()), + primaryCheck.observe().observeOn(Schedulers.computation()), + (finalCheck, primaryCheck) -> { + try { + return validateText(finalCheck, primaryCheck, text, fullCheck); + } catch (final ConversionException exception) { + throw OnErrorThrowable.from(exception); + } + }); + } + + @NonNull + private Observable processChecks(@NonNull final String text, final boolean fullCheck) { + return createValidationObservable(text, fullCheck) + .map(HalfNullablePair::getFirst) + .onErrorResumeNext(throwable -> { + if (throwable instanceof ConversionException || throwable.getCause() instanceof ConversionException) { + Lc.assertion(throwable); + return Observable.just(ValidationState.ERROR_CONVERSION); + } + return Observable.error(throwable); + }); + } + + @NonNull + public Observable primaryValidate(@NonNull final String text) { + return processChecks(text, false); + } + + @NonNull + public Observable fullValidate(@NonNull final String text) { + return processChecks(text, true); + } + + @NonNull + public Observable> fullValidateAndGetModel(@NonNull final String text) { + return createValidationObservable(text, true); + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/SameTypeValidator.java b/src/main/java/ru/touchin/templates/validation/SameTypeValidator.java new file mode 100644 index 0000000..f2af062 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/SameTypeValidator.java @@ -0,0 +1,17 @@ +package ru.touchin.templates.validation; + + +import android.support.annotation.NonNull; + +import java.io.Serializable; + +public class SameTypeValidator extends Validator { + + @NonNull + @Override + protected TModel convertWrapperModelToModel(@NonNull final TModel wrapperModel) + throws ConversionException { + return wrapperModel; + } + +} diff --git a/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java b/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java new file mode 100644 index 0000000..9262e11 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java @@ -0,0 +1,28 @@ +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; + +import java.io.Serializable; + +import rx.Observable; + +public class SimpleValidationController> + extends TwoWayValidationController { + + public SimpleValidationController(@NonNull final TValidationWrapper validationWrapper) { + super(validationWrapper); + } + + @NonNull + public Observable validation(@NonNull final Observable activatedObservable) { + return Observable.combineLatest(activatedObservable, + getValidationWrapper().getWrapperModel().observe(), (activated, model) -> { + if (model == null) { + return activated ? ValidationState.ERROR_NO_DESCRIPTION : ValidationState.INITIAL; + } + return ValidationState.VALID; + }) + .doOnNext(validationState -> getValidationWrapper().getValidationState().set(validationState)); + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java b/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java new file mode 100644 index 0000000..cc5a735 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.io.Serializable; + +import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public abstract class TwoWayValidationController + > + extends ValidationController { + + public TwoWayValidationController(@NonNull final TValidationWrapper validationWrapper) { + super(validationWrapper); + } + + @NonNull + public Observable modelAndViewUpdating(@Nullable final Observable viewStateObservable, + @NonNull final Action1 updateViewAction, + @NonNull final ViewWithError viewWithError) { + final Observable stateObservable = viewStateObservable != null + ? viewStateObservable.doOnNext(flag -> getValidationWrapper().getWrapperModel().set(flag)) + : Observable.empty(); + return Observable + .merge(getValidationWrapper().getWrapperModel().observe() + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(updateViewAction), + getValidationWrapper().getValidationState().observe() + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(validationState -> { + if (!showError(validationState)) { + viewWithError.hideError(); + } else { + viewWithError.showError(validationState); + } + }), + stateObservable); + } + + protected boolean showError(@NonNull final ValidationState validationState) { + return validationState != ValidationState.VALID && validationState != ValidationState.INITIAL; + } + +} diff --git a/src/main/java/ru/touchin/templates/validation/ValidationController.java b/src/main/java/ru/touchin/templates/validation/ValidationController.java new file mode 100644 index 0000000..c543813 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/ValidationController.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public abstract class ValidationController { + + @NonNull + private final TWrapper validationWrapper; + + public ValidationController(@NonNull final TWrapper validationWrapper) { + this.validationWrapper = validationWrapper; + } + + @NonNull + public TWrapper getValidationWrapper() { + return validationWrapper; + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ValidationState.java b/src/main/java/ru/touchin/templates/validation/ValidationState.java new file mode 100644 index 0000000..6cb01a9 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/ValidationState.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + + +import java.io.Serializable; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public class ValidationState implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Initial state of validation. It indicates that no validation rules applied yet. + */ + public static final ValidationState INITIAL = new ValidationState(); + /** + * Valid state. + */ + public static final ValidationState VALID = new ValidationState(); + /** + * Error shows when model (e.g. DateTime) is failing on conversion from raw data (e.g. from String) for validation. + */ + public static final ValidationState ERROR_CONVERSION = new ValidationState(); + /** + * Error shows when we don't need to show any description of error (e.g. just highlight input field with red color). + */ + public static final ValidationState ERROR_NO_DESCRIPTION = new ValidationState(); + +} diff --git a/src/main/java/ru/touchin/templates/validation/Validator.java b/src/main/java/ru/touchin/templates/validation/Validator.java new file mode 100644 index 0000000..59e7f4d --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/Validator.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; + +import java.io.Serializable; + +import ru.touchin.roboswag.core.observables.Changeable; +import ru.touchin.roboswag.core.observables.NonNullChangeable; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public abstract class Validator + implements Serializable { + + private static final long serialVersionUID = 1L; + + @NonNull + private final NonNullChangeable validationState = new NonNullChangeable<>(ValidationState.INITIAL); + @NonNull + private final Changeable wrapperModel = new Changeable<>(null); + @NonNull + private final Changeable validationStateWhenEmpty = new Changeable<>(null); + + @NonNull + protected abstract TModel convertWrapperModelToModel(@NonNull final TWrapperModel wrapperModel) throws ConversionException; + + @NonNull + public Changeable getWrapperModel() { + return wrapperModel; + } + + @NonNull + public NonNullChangeable getValidationState() { + return validationState; + } + + @NonNull + public Changeable getValidationStateWhenEmpty() { + return validationStateWhenEmpty; + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ViewWithError.java b/src/main/java/ru/touchin/templates/validation/ViewWithError.java new file mode 100644 index 0000000..937e6a6 --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/ViewWithError.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016 Touch Instinct + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; + +/** + * Created by Ilia Kurtov on 24/01/2017. + * TODO: fill + */ +public interface ViewWithError { + + void hideError(); + + void showError(@NonNull ValidationState validationState); + +} From ba033c2814ec52455db6a7c5cb9678c7384ec9d3 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Tue, 24 Jan 2017 21:07:05 +0300 Subject: [PATCH 02/11] small refactor --- .../validation/BooleanValidationController.java | 4 ++-- .../validation/EditTextValidationController.java | 15 +++++++-------- .../validation/SimpleValidationController.java | 12 ++++++------ .../validation/TwoWayValidationController.java | 14 +++++++------- .../validation/ValidationController.java | 12 ++++++------ .../touchin/templates/validation/Validator.java | 4 ++-- .../templates/validation/ViewWithError.java | 2 +- 7 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java b/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java index 903484c..361ea12 100644 --- a/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java @@ -35,7 +35,7 @@ public class BooleanValidationController extends TwoWayValidationController validation(@NonNull final Observable activatedObservable) { - return Observable.combineLatest(activatedObservable, getValidationWrapper().getWrapperModel().observe(), + return Observable.combineLatest(activatedObservable, getValidator().getWrapperModel().observe(), (activated, flag) -> { final boolean selected = flag == null ? false : flag; if (activated && !selected) { @@ -45,7 +45,7 @@ public class BooleanValidationController extends TwoWayValidationController getValidationWrapper().getValidationState().set(validationState)); + .doOnNext(validationState -> getValidator().getValidationState().set(validationState)); } } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java b/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java index 62ea68b..9dd6703 100644 --- a/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java @@ -42,9 +42,9 @@ public class EditTextValidationController public Observable validation(@NonNull final Observable focusOutObservable, @NonNull final Observable activatedObservable) { return Observable .>>combineLatest(activatedObservable, - getValidationWrapper().getWrapperModel().observe(), + getValidator().getWrapperModel().observe(), focusOutObservable, - getValidationWrapper().getShowFullCheck().observe(), + getValidator().getShowFullCheck().observe(), (activated, text, focusIn, showError) -> { if (focusIn == null && TextUtils.isEmpty(text) && !activated && !showError) { return null; @@ -52,14 +52,13 @@ public class EditTextValidationController final boolean focus = focusIn == null ? false : focusIn; if (TextUtils.isEmpty(text)) { return new NonNullPair<>(focus, (activated || showError) - ? getValidationWrapper().getValidationStateWhenEmpty().observe() - .map(state -> state != null ? state : ValidationState.ERROR_NO_DESCRIPTION) + ? getValidator().getValidationStateWhenEmpty().observe() : Observable.just(ValidationState.INITIAL)); } if (!showError && focus) { - return new NonNullPair<>(true, getValidationWrapper().primaryValidate(text)); + return new NonNullPair<>(true, getValidator().primaryValidate(text)); } - return new NonNullPair<>(focus, getValidationWrapper().fullValidate(text)); + return new NonNullPair<>(focus, getValidator().fullValidate(text)); }) .switchMap(validationPair -> { if (validationPair == null) { @@ -68,9 +67,9 @@ public class EditTextValidationController return validationPair.getSecond() .doOnNext(validationState -> { if (!validationPair.getFirst()) { - getValidationWrapper().getShowFullCheck().set(validationState != ValidationState.VALID); + getValidator().getShowFullCheck().set(validationState != ValidationState.VALID); } - getValidationWrapper().getValidationState().set(validationState); + getValidator().getValidationState().set(validationState); }); }); } diff --git a/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java b/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java index 9262e11..1739c4a 100644 --- a/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java @@ -6,23 +6,23 @@ import java.io.Serializable; import rx.Observable; -public class SimpleValidationController> - extends TwoWayValidationController { +public class SimpleValidationController> + extends TwoWayValidationController { - public SimpleValidationController(@NonNull final TValidationWrapper validationWrapper) { - super(validationWrapper); + public SimpleValidationController(@NonNull final TValidator validator) { + super(validator); } @NonNull public Observable validation(@NonNull final Observable activatedObservable) { return Observable.combineLatest(activatedObservable, - getValidationWrapper().getWrapperModel().observe(), (activated, model) -> { + getValidator().getWrapperModel().observe(), (activated, model) -> { if (model == null) { return activated ? ValidationState.ERROR_NO_DESCRIPTION : ValidationState.INITIAL; } return ValidationState.VALID; }) - .doOnNext(validationState -> getValidationWrapper().getValidationState().set(validationState)); + .doOnNext(validationState -> getValidator().getValidationState().set(validationState)); } } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java b/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java index cc5a735..577c939 100644 --- a/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java @@ -33,11 +33,11 @@ import rx.functions.Action1; * TODO: fill */ public abstract class TwoWayValidationController - > - extends ValidationController { + > + extends ValidationController { - public TwoWayValidationController(@NonNull final TValidationWrapper validationWrapper) { - super(validationWrapper); + public TwoWayValidationController(@NonNull final TValidator validator) { + super(validator); } @NonNull @@ -45,13 +45,13 @@ public abstract class TwoWayValidationController @NonNull final Action1 updateViewAction, @NonNull final ViewWithError viewWithError) { final Observable stateObservable = viewStateObservable != null - ? viewStateObservable.doOnNext(flag -> getValidationWrapper().getWrapperModel().set(flag)) + ? viewStateObservable.doOnNext(flag -> getValidator().getWrapperModel().set(flag)) : Observable.empty(); return Observable - .merge(getValidationWrapper().getWrapperModel().observe() + .merge(getValidator().getWrapperModel().observe() .observeOn(AndroidSchedulers.mainThread()) .doOnNext(updateViewAction), - getValidationWrapper().getValidationState().observe() + getValidator().getValidationState().observe() .observeOn(AndroidSchedulers.mainThread()) .doOnNext(validationState -> { if (!showError(validationState)) { diff --git a/src/main/java/ru/touchin/templates/validation/ValidationController.java b/src/main/java/ru/touchin/templates/validation/ValidationController.java index c543813..01438a6 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationController.java @@ -25,18 +25,18 @@ import android.support.annotation.NonNull; * Created by Ilia Kurtov on 24/01/2017. * TODO: fill */ -public abstract class ValidationController { +public abstract class ValidationController { @NonNull - private final TWrapper validationWrapper; + private final TValidator validator; - public ValidationController(@NonNull final TWrapper validationWrapper) { - this.validationWrapper = validationWrapper; + public ValidationController(@NonNull final TValidator validator) { + this.validator = validator; } @NonNull - public TWrapper getValidationWrapper() { - return validationWrapper; + public TValidator getValidator() { + return validator; } } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/Validator.java b/src/main/java/ru/touchin/templates/validation/Validator.java index 59e7f4d..795d1f9 100644 --- a/src/main/java/ru/touchin/templates/validation/Validator.java +++ b/src/main/java/ru/touchin/templates/validation/Validator.java @@ -40,7 +40,7 @@ public abstract class Validator wrapperModel = new Changeable<>(null); @NonNull - private final Changeable validationStateWhenEmpty = new Changeable<>(null); + private final NonNullChangeable validationStateWhenEmpty = new NonNullChangeable<>(ValidationState.ERROR_NO_DESCRIPTION); @NonNull protected abstract TModel convertWrapperModelToModel(@NonNull final TWrapperModel wrapperModel) throws ConversionException; @@ -56,7 +56,7 @@ public abstract class Validator getValidationStateWhenEmpty() { + public NonNullChangeable getValidationStateWhenEmpty() { return validationStateWhenEmpty; } diff --git a/src/main/java/ru/touchin/templates/validation/ViewWithError.java b/src/main/java/ru/touchin/templates/validation/ViewWithError.java index 937e6a6..7cc71d4 100644 --- a/src/main/java/ru/touchin/templates/validation/ViewWithError.java +++ b/src/main/java/ru/touchin/templates/validation/ViewWithError.java @@ -29,6 +29,6 @@ public interface ViewWithError { void hideError(); - void showError(@NonNull ValidationState validationState); + void showError(@NonNull final ValidationState validationState); } From b0de8da96ceda2bedbef59f1cd8a150fa01cfb36 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Fri, 27 Jan 2017 18:20:05 +0300 Subject: [PATCH 03/11] refactor --- .../templates/validation/ValidationState.java | 32 ++++++++++++++++--- .../templates/validation/ViewWithError.java | 4 +-- .../BooleanValidationController.java | 8 +++-- .../EditTextValidationController.java | 4 ++- .../SimpleValidationController.java | 4 ++- .../TwoWayValidationController.java | 5 ++- .../ValidationController.java | 4 ++- .../{ => validators}/EditTextValidator.java | 8 +++-- .../{ => validators}/SameTypeValidator.java | 4 ++- .../{ => validators}/Validator.java | 4 ++- 10 files changed, 57 insertions(+), 20 deletions(-) rename src/main/java/ru/touchin/templates/validation/{ => validationcontrollers}/BooleanValidationController.java (87%) rename src/main/java/ru/touchin/templates/validation/{ => validationcontrollers}/EditTextValidationController.java (94%) rename src/main/java/ru/touchin/templates/validation/{ => validationcontrollers}/SimpleValidationController.java (84%) rename src/main/java/ru/touchin/templates/validation/{ => validationcontrollers}/TwoWayValidationController.java (92%) rename src/main/java/ru/touchin/templates/validation/{ => validationcontrollers}/ValidationController.java (89%) rename src/main/java/ru/touchin/templates/validation/{ => validators}/EditTextValidator.java (96%) rename src/main/java/ru/touchin/templates/validation/{ => validators}/SameTypeValidator.java (76%) rename src/main/java/ru/touchin/templates/validation/{ => validators}/Validator.java (92%) diff --git a/src/main/java/ru/touchin/templates/validation/ValidationState.java b/src/main/java/ru/touchin/templates/validation/ValidationState.java index 6cb01a9..eda8260 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationState.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationState.java @@ -33,18 +33,40 @@ public class ValidationState implements Serializable { /** * Initial state of validation. It indicates that no validation rules applied yet. */ - public static final ValidationState INITIAL = new ValidationState(); + public static final ValidationState INITIAL = new ValidationState(-1); /** * Valid state. */ - public static final ValidationState VALID = new ValidationState(); + public static final ValidationState VALID = new ValidationState(-2); /** * Error shows when model (e.g. DateTime) is failing on conversion from raw data (e.g. from String) for validation. */ - public static final ValidationState ERROR_CONVERSION = new ValidationState(); + public static final ValidationState ERROR_CONVERSION = new ValidationState(-3); /** * Error shows when we don't need to show any description of error (e.g. just highlight input field with red color). */ - public static final ValidationState ERROR_NO_DESCRIPTION = new ValidationState(); + public static final ValidationState ERROR_NO_DESCRIPTION = new ValidationState(-4); -} + private final int code; + + public ValidationState(final int code) { + this.code = code; + } + + public int getCode() { + return code; + } + + @Override + public boolean equals(final Object object) { + return this == object + || !(object == null || getClass() != object.getClass()) && code == ((ValidationState) object).code; + } + + @Override + public int hashCode() { + //TODO + return super.hashCode(); + } + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ViewWithError.java b/src/main/java/ru/touchin/templates/validation/ViewWithError.java index 7cc71d4..fffc1c7 100644 --- a/src/main/java/ru/touchin/templates/validation/ViewWithError.java +++ b/src/main/java/ru/touchin/templates/validation/ViewWithError.java @@ -19,8 +19,6 @@ package ru.touchin.templates.validation; -import android.support.annotation.NonNull; - /** * Created by Ilia Kurtov on 24/01/2017. * TODO: fill @@ -29,6 +27,6 @@ public interface ViewWithError { void hideError(); - void showError(@NonNull final ValidationState validationState); + void showError(); } diff --git a/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java similarity index 87% rename from src/main/java/ru/touchin/templates/validation/BooleanValidationController.java rename to src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java index 361ea12..6b9e955 100644 --- a/src/main/java/ru/touchin/templates/validation/BooleanValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java @@ -17,10 +17,12 @@ * */ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; +import ru.touchin.templates.validation.ValidationState; +import ru.touchin.templates.validation.validators.SameTypeValidator; import rx.Observable; /** @@ -29,8 +31,8 @@ import rx.Observable; */ public class BooleanValidationController extends TwoWayValidationController> { - public BooleanValidationController(@NonNull final SameTypeValidator validationWrapper) { - super(validationWrapper); + public BooleanValidationController(@NonNull final SameTypeValidator validator) { + super(validator); } @NonNull diff --git a/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java similarity index 94% rename from src/main/java/ru/touchin/templates/validation/EditTextValidationController.java rename to src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java index 9dd6703..93e0650 100644 --- a/src/main/java/ru/touchin/templates/validation/EditTextValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java @@ -17,7 +17,7 @@ * */ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; import android.text.TextUtils; @@ -25,6 +25,8 @@ import android.text.TextUtils; import java.io.Serializable; import ru.touchin.roboswag.core.utils.pairs.NonNullPair; +import ru.touchin.templates.validation.ValidationState; +import ru.touchin.templates.validation.validators.EditTextValidator; import rx.Observable; /** diff --git a/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java similarity index 84% rename from src/main/java/ru/touchin/templates/validation/SimpleValidationController.java rename to src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java index 1739c4a..824117e 100644 --- a/src/main/java/ru/touchin/templates/validation/SimpleValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java @@ -1,9 +1,11 @@ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; import java.io.Serializable; +import ru.touchin.templates.validation.ValidationState; +import ru.touchin.templates.validation.validators.Validator; import rx.Observable; public class SimpleValidationController> diff --git a/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java similarity index 92% rename from src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java rename to src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java index 577c939..b7c17c7 100644 --- a/src/main/java/ru/touchin/templates/validation/TwoWayValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java @@ -17,13 +17,16 @@ * */ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.io.Serializable; +import ru.touchin.templates.validation.ValidationState; +import ru.touchin.templates.validation.ViewWithError; +import ru.touchin.templates.validation.validators.Validator; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; diff --git a/src/main/java/ru/touchin/templates/validation/ValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java similarity index 89% rename from src/main/java/ru/touchin/templates/validation/ValidationController.java rename to src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java index 01438a6..307a119 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java @@ -17,10 +17,12 @@ * */ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; +import ru.touchin.templates.validation.validators.Validator; + /** * Created by Ilia Kurtov on 24/01/2017. * TODO: fill diff --git a/src/main/java/ru/touchin/templates/validation/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java similarity index 96% rename from src/main/java/ru/touchin/templates/validation/EditTextValidator.java rename to src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java index 20425a8..7406077 100644 --- a/src/main/java/ru/touchin/templates/validation/EditTextValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java @@ -17,7 +17,7 @@ * */ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validators; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -28,6 +28,8 @@ import ru.touchin.roboswag.core.log.Lc; import ru.touchin.roboswag.core.observables.Changeable; import ru.touchin.roboswag.core.observables.NonNullChangeable; import ru.touchin.roboswag.core.utils.pairs.HalfNullablePair; +import ru.touchin.templates.validation.ConversionException; +import ru.touchin.templates.validation.ValidationState; import rx.Observable; import rx.exceptions.OnErrorThrowable; import rx.functions.Func1; @@ -51,12 +53,12 @@ public abstract class EditTextValidator extends Val return showFullCheck; } - @Nullable + @NonNull public Changeable>> getFinalCheck() { return finalCheck; } - @Nullable + @NonNull public Changeable>> getPrimaryCheck() { return primaryCheck; } diff --git a/src/main/java/ru/touchin/templates/validation/SameTypeValidator.java b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java similarity index 76% rename from src/main/java/ru/touchin/templates/validation/SameTypeValidator.java rename to src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java index f2af062..bf41b0a 100644 --- a/src/main/java/ru/touchin/templates/validation/SameTypeValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java @@ -1,10 +1,12 @@ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validators; import android.support.annotation.NonNull; import java.io.Serializable; +import ru.touchin.templates.validation.ConversionException; + public class SameTypeValidator extends Validator { @NonNull diff --git a/src/main/java/ru/touchin/templates/validation/Validator.java b/src/main/java/ru/touchin/templates/validation/validators/Validator.java similarity index 92% rename from src/main/java/ru/touchin/templates/validation/Validator.java rename to src/main/java/ru/touchin/templates/validation/validators/Validator.java index 795d1f9..348dd44 100644 --- a/src/main/java/ru/touchin/templates/validation/Validator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/Validator.java @@ -17,7 +17,7 @@ * */ -package ru.touchin.templates.validation; +package ru.touchin.templates.validation.validators; import android.support.annotation.NonNull; @@ -25,6 +25,8 @@ import java.io.Serializable; import ru.touchin.roboswag.core.observables.Changeable; import ru.touchin.roboswag.core.observables.NonNullChangeable; +import ru.touchin.templates.validation.ConversionException; +import ru.touchin.templates.validation.ValidationState; /** * Created by Ilia Kurtov on 24/01/2017. From c1849585be90033654060b43fd33ae4efc2e68c1 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Mon, 30 Jan 2017 14:12:58 +0300 Subject: [PATCH 04/11] updated validation --- .../templates/validation/ValidationFunc.java | 12 ++++++++++++ .../templates/validation/ValidationState.java | 3 +-- .../templates/validation/ViewWithError.java | 4 +++- .../TwoWayValidationController.java | 2 +- .../validation/validators/EditTextValidator.java | 16 +++++++++------- 5 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 src/main/java/ru/touchin/templates/validation/ValidationFunc.java diff --git a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java new file mode 100644 index 0000000..23356dd --- /dev/null +++ b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java @@ -0,0 +1,12 @@ +package ru.touchin.templates.validation; + +import android.support.annotation.NonNull; + +import java.io.Serializable; + +public interface ValidationFunc extends Serializable { + + @NonNull + TReturn call(@NonNull final TInput input); + +} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ValidationState.java b/src/main/java/ru/touchin/templates/validation/ValidationState.java index eda8260..5a8c022 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationState.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationState.java @@ -65,8 +65,7 @@ public class ValidationState implements Serializable { @Override public int hashCode() { - //TODO - return super.hashCode(); + return 31 * code; } } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ViewWithError.java b/src/main/java/ru/touchin/templates/validation/ViewWithError.java index fffc1c7..7cc71d4 100644 --- a/src/main/java/ru/touchin/templates/validation/ViewWithError.java +++ b/src/main/java/ru/touchin/templates/validation/ViewWithError.java @@ -19,6 +19,8 @@ package ru.touchin.templates.validation; +import android.support.annotation.NonNull; + /** * Created by Ilia Kurtov on 24/01/2017. * TODO: fill @@ -27,6 +29,6 @@ public interface ViewWithError { void hideError(); - void showError(); + void showError(@NonNull final ValidationState validationState); } diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java index b7c17c7..8ba8b53 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java @@ -67,7 +67,7 @@ public abstract class TwoWayValidationController } protected boolean showError(@NonNull final ValidationState validationState) { - return validationState != ValidationState.VALID && validationState != ValidationState.INITIAL; + return !validationState.equals(ValidationState.VALID) && !validationState.equals(ValidationState.INITIAL); } } diff --git a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java index 7406077..406beaf 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java @@ -29,6 +29,7 @@ import ru.touchin.roboswag.core.observables.Changeable; import ru.touchin.roboswag.core.observables.NonNullChangeable; import ru.touchin.roboswag.core.utils.pairs.HalfNullablePair; import ru.touchin.templates.validation.ConversionException; +import ru.touchin.templates.validation.ValidationFunc; import ru.touchin.templates.validation.ValidationState; import rx.Observable; import rx.exceptions.OnErrorThrowable; @@ -44,9 +45,9 @@ public abstract class EditTextValidator extends Val @NonNull private final NonNullChangeable showFullCheck = new NonNullChangeable<>(false); @NonNull - private final Changeable>> finalCheck = new Changeable<>(null); + private final Changeable>> finalCheck = new Changeable<>(null); @NonNull - private final Changeable>> primaryCheck = new Changeable<>(null); + private final Changeable>> primaryCheck = new Changeable<>(null); @NonNull public NonNullChangeable getShowFullCheck() { @@ -54,19 +55,19 @@ public abstract class EditTextValidator extends Val } @NonNull - public Changeable>> getFinalCheck() { + public Changeable>> getFinalCheck() { return finalCheck; } @NonNull - public Changeable>> getPrimaryCheck() { + public Changeable>> getPrimaryCheck() { return primaryCheck; } @NonNull private HalfNullablePair validateText( - @Nullable final Func1> finalCheck, - @Nullable final Func1> primaryCheck, + @Nullable final ValidationFunc> finalCheck, + @Nullable final ValidationFunc> primaryCheck, @NonNull final String text, final boolean fullCheck) throws ConversionException { if (primaryCheck == null && finalCheck == null) { @@ -122,7 +123,8 @@ public abstract class EditTextValidator extends Val @NonNull public Observable> fullValidateAndGetModel(@NonNull final String text) { - return createValidationObservable(text, true); + return createValidationObservable(text, true) + .first(); } } \ No newline at end of file From 4833c12364cc0baae58fe9022d8e25aec50d99f3 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Mon, 30 Jan 2017 14:24:25 +0300 Subject: [PATCH 05/11] static --- .../validation/ConversionException.java | 5 ++ .../EditTextValidationController.java | 47 +++++++++++-------- .../ValidationController.java | 2 +- .../validators/EditTextValidator.java | 1 - 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/main/java/ru/touchin/templates/validation/ConversionException.java b/src/main/java/ru/touchin/templates/validation/ConversionException.java index e705851..110a228 100644 --- a/src/main/java/ru/touchin/templates/validation/ConversionException.java +++ b/src/main/java/ru/touchin/templates/validation/ConversionException.java @@ -24,4 +24,9 @@ package ru.touchin.templates.validation; * TODO: fill */ public class ConversionException extends Exception { + + public ConversionException(final Throwable cause) { + super(cause); + } + } diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java index 93e0650..abf5e90 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java @@ -20,6 +20,7 @@ package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.TextUtils; import java.io.Serializable; @@ -42,26 +43,11 @@ public class EditTextValidationController @NonNull public Observable validation(@NonNull final Observable focusOutObservable, @NonNull final Observable activatedObservable) { - return Observable - .>>combineLatest(activatedObservable, - getValidator().getWrapperModel().observe(), - focusOutObservable, - getValidator().getShowFullCheck().observe(), - (activated, text, focusIn, showError) -> { - if (focusIn == null && TextUtils.isEmpty(text) && !activated && !showError) { - return null; - } - final boolean focus = focusIn == null ? false : focusIn; - if (TextUtils.isEmpty(text)) { - return new NonNullPair<>(focus, (activated || showError) - ? getValidator().getValidationStateWhenEmpty().observe() - : Observable.just(ValidationState.INITIAL)); - } - if (!showError && focus) { - return new NonNullPair<>(true, getValidator().primaryValidate(text)); - } - return new NonNullPair<>(focus, getValidator().fullValidate(text)); - }) + return Observable.combineLatest(activatedObservable, + getValidator().getWrapperModel().observe(), + focusOutObservable, + getValidator().getShowFullCheck().observe(), + this::getValidationPair) .switchMap(validationPair -> { if (validationPair == null) { return Observable.empty(); @@ -76,4 +62,25 @@ public class EditTextValidationController }); } + @Nullable + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) + private NonNullPair> getValidationPair(final boolean activated, + @Nullable final String text, + @Nullable final Boolean focusIn, + final boolean showError) { + if (focusIn == null && TextUtils.isEmpty(text) && !activated && !showError) { + return null; + } + final boolean focus = focusIn == null ? false : focusIn; + if (TextUtils.isEmpty(text)) { + return new NonNullPair<>(focus, (activated || showError) + ? getValidator().getValidationStateWhenEmpty().observe() + : Observable.just(ValidationState.INITIAL)); + } + if (!showError && focus) { + return new NonNullPair<>(true, getValidator().primaryValidate(text)); + } + return new NonNullPair<>(focus, getValidator().fullValidate(text)); + } + } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java index 307a119..37dc600 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java @@ -27,7 +27,7 @@ import ru.touchin.templates.validation.validators.Validator; * Created by Ilia Kurtov on 24/01/2017. * TODO: fill */ -public abstract class ValidationController { +public class ValidationController { @NonNull private final TValidator validator; diff --git a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java index 406beaf..f0f8336 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java @@ -33,7 +33,6 @@ import ru.touchin.templates.validation.ValidationFunc; import ru.touchin.templates.validation.ValidationState; import rx.Observable; import rx.exceptions.OnErrorThrowable; -import rx.functions.Func1; import rx.schedulers.Schedulers; /** From 346531231547dc18cde1698ed6a655a2933ecbe5 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Mon, 30 Jan 2017 14:26:33 +0300 Subject: [PATCH 06/11] add annotation --- .../touchin/templates/validation/ConversionException.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/touchin/templates/validation/ConversionException.java b/src/main/java/ru/touchin/templates/validation/ConversionException.java index 110a228..4392940 100644 --- a/src/main/java/ru/touchin/templates/validation/ConversionException.java +++ b/src/main/java/ru/touchin/templates/validation/ConversionException.java @@ -19,14 +19,16 @@ package ru.touchin.templates.validation; +import android.support.annotation.Nullable; + /** * Created by Ilia Kurtov on 24/01/2017. * TODO: fill */ public class ConversionException extends Exception { - public ConversionException(final Throwable cause) { + public ConversionException(@Nullable final Throwable cause) { super(cause); } -} +} \ No newline at end of file From 88b4c43d5295c4a7ad06d86d155474b26f8d0897 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Mon, 30 Jan 2017 17:33:11 +0300 Subject: [PATCH 07/11] newest updates --- .../templates/validation/ValidationFunc.java | 4 ++-- .../validation/validators/EditTextValidator.java | 16 ++++------------ .../validation/validators/SameTypeValidator.java | 2 +- .../validation/validators/Validator.java | 2 +- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java index 23356dd..38c5d9f 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java @@ -4,9 +4,9 @@ import android.support.annotation.NonNull; import java.io.Serializable; -public interface ValidationFunc extends Serializable { +public interface ValidationFunc extends Serializable { @NonNull - TReturn call(@NonNull final TInput input); + TReturn call(@NonNull final TInput input) throws Throwable; } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java index f0f8336..9a5c67e 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java @@ -68,11 +68,10 @@ public abstract class EditTextValidator extends Val @Nullable final ValidationFunc> finalCheck, @Nullable final ValidationFunc> primaryCheck, @NonNull final String text, final boolean fullCheck) - throws ConversionException { + throws Throwable { if (primaryCheck == null && finalCheck == null) { return new HalfNullablePair<>(ValidationState.VALID, convertWrapperModelToModel(text)); } - if (primaryCheck != null) { final HalfNullablePair primaryPair = primaryCheck.call(text); if (finalCheck == null || primaryPair.getFirst() != ValidationState.VALID || primaryPair.getSecond() == null || !fullCheck) { @@ -91,8 +90,8 @@ public abstract class EditTextValidator extends Val (finalCheck, primaryCheck) -> { try { return validateText(finalCheck, primaryCheck, text, fullCheck); - } catch (final ConversionException exception) { - throw OnErrorThrowable.from(exception); + } catch (final Throwable exception) { + return new HalfNullablePair<>(ValidationState.ERROR_CONVERSION, null); } }); } @@ -100,14 +99,7 @@ public abstract class EditTextValidator extends Val @NonNull private Observable processChecks(@NonNull final String text, final boolean fullCheck) { return createValidationObservable(text, fullCheck) - .map(HalfNullablePair::getFirst) - .onErrorResumeNext(throwable -> { - if (throwable instanceof ConversionException || throwable.getCause() instanceof ConversionException) { - Lc.assertion(throwable); - return Observable.just(ValidationState.ERROR_CONVERSION); - } - return Observable.error(throwable); - }); + .map(HalfNullablePair::getFirst); } @NonNull diff --git a/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java index bf41b0a..ab2e66a 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java @@ -12,7 +12,7 @@ public class SameTypeValidator extends Validator validationStateWhenEmpty = new NonNullChangeable<>(ValidationState.ERROR_NO_DESCRIPTION); @NonNull - protected abstract TModel convertWrapperModelToModel(@NonNull final TWrapperModel wrapperModel) throws ConversionException; + protected abstract TModel convertWrapperModelToModel(@NonNull final TWrapperModel wrapperModel) throws Throwable; @NonNull public Changeable getWrapperModel() { From 91322f3087c44016a61e37712f40fda26a744d27 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Mon, 30 Jan 2017 17:44:56 +0300 Subject: [PATCH 08/11] static --- .../templates/validation/validators/EditTextValidator.java | 5 ++--- .../templates/validation/validators/SameTypeValidator.java | 2 -- .../touchin/templates/validation/validators/Validator.java | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java index 9a5c67e..75185e3 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java @@ -24,15 +24,12 @@ import android.support.annotation.Nullable; import java.io.Serializable; -import ru.touchin.roboswag.core.log.Lc; import ru.touchin.roboswag.core.observables.Changeable; import ru.touchin.roboswag.core.observables.NonNullChangeable; import ru.touchin.roboswag.core.utils.pairs.HalfNullablePair; -import ru.touchin.templates.validation.ConversionException; import ru.touchin.templates.validation.ValidationFunc; import ru.touchin.templates.validation.ValidationState; import rx.Observable; -import rx.exceptions.OnErrorThrowable; import rx.schedulers.Schedulers; /** @@ -83,6 +80,8 @@ public abstract class EditTextValidator extends Val } @NonNull + @SuppressWarnings("PMD.AvoidCatchingThrowable") + // It's intended private Observable> createValidationObservable(@NonNull final String text, final boolean fullCheck) { return Observable .combineLatest(finalCheck.observe().observeOn(Schedulers.computation()), diff --git a/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java index ab2e66a..50b7e38 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java @@ -5,8 +5,6 @@ import android.support.annotation.NonNull; import java.io.Serializable; -import ru.touchin.templates.validation.ConversionException; - public class SameTypeValidator extends Validator { @NonNull diff --git a/src/main/java/ru/touchin/templates/validation/validators/Validator.java b/src/main/java/ru/touchin/templates/validation/validators/Validator.java index e3790ba..9abcdac 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/Validator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/Validator.java @@ -25,7 +25,6 @@ import java.io.Serializable; import ru.touchin.roboswag.core.observables.Changeable; import ru.touchin.roboswag.core.observables.NonNullChangeable; -import ru.touchin.templates.validation.ConversionException; import ru.touchin.templates.validation.ValidationState; /** From e2d742bbe5bd5120ef74ed51a17b691c96bce65d Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Thu, 2 Feb 2017 10:48:54 +0300 Subject: [PATCH 09/11] starts to comment --- .../templates/validation/ValidationFunc.java | 14 ++++++++++++++ .../templates/validation/ValidationState.java | 4 +++- .../templates/validation/ViewWithError.java | 13 ++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java index 38c5d9f..8632db9 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java @@ -4,8 +4,22 @@ import android.support.annotation.NonNull; import java.io.Serializable; +/** + * Created by Ilia Kurtov on 30/01/2017. + * Simple interface that gets one parameter {@link TInput} as input and returns other type {@link TReturn}. + * Interface extends {@link Serializable} to survive after {@link ru.touchin.roboswag.components.navigation.AbstractState} recreation. + * Created as a replace for {@link rx.functions.Func1} because it needed to be {@link Serializable} + * @param input type. + * @param return type. + */ public interface ValidationFunc extends Serializable { + /** + * + * @param input + * @return + * @throws Throwable + */ @NonNull TReturn call(@NonNull final TInput input) throws Throwable; diff --git a/src/main/java/ru/touchin/templates/validation/ValidationState.java b/src/main/java/ru/touchin/templates/validation/ValidationState.java index 5a8c022..7236981 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationState.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationState.java @@ -24,7 +24,9 @@ import java.io.Serializable; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * Basic class for validation states. If you need to have more states with more data in it - + * create class that extends this class and don't forget to redefine {@link #equals(Object)} and {@link #hashCode()} methods. + * Don't use same {@link #code} for different states. */ public class ValidationState implements Serializable { diff --git a/src/main/java/ru/touchin/templates/validation/ViewWithError.java b/src/main/java/ru/touchin/templates/validation/ViewWithError.java index 7cc71d4..a4bc14a 100644 --- a/src/main/java/ru/touchin/templates/validation/ViewWithError.java +++ b/src/main/java/ru/touchin/templates/validation/ViewWithError.java @@ -23,12 +23,23 @@ import android.support.annotation.NonNull; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * Interface for views that must be validated. Have two states - show error or hide error. + * You can provide your own Validation State to provide, eg string resource. + * In this case use instanceOf to define what state do you have. */ public interface ViewWithError { + /** + * Hides the error when validation passes successful. + */ void hideError(); + /** + * Shows error + * Pass here error state. + * It is not correct to pass here {@link ValidationState#VALID} or {@link ValidationState#INITIAL} + * @param validationState error state. Can be other than {@link ValidationState} if you have successor of base {@link ValidationState}. + */ void showError(@NonNull final ValidationState validationState); } From 045f4d650441bd2a8231ccc45352177a0b22430b Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Fri, 3 Feb 2017 19:50:29 +0300 Subject: [PATCH 10/11] small comments --- .../validation/ConversionException.java | 34 ------------------- .../templates/validation/ValidationFunc.java | 10 +++--- .../validation/validators/Validator.java | 5 ++- 3 files changed, 9 insertions(+), 40 deletions(-) delete mode 100644 src/main/java/ru/touchin/templates/validation/ConversionException.java diff --git a/src/main/java/ru/touchin/templates/validation/ConversionException.java b/src/main/java/ru/touchin/templates/validation/ConversionException.java deleted file mode 100644 index 4392940..0000000 --- a/src/main/java/ru/touchin/templates/validation/ConversionException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2016 Touch Instinct - * - * This file is part of RoboSwag library. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package ru.touchin.templates.validation; - -import android.support.annotation.Nullable; - -/** - * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill - */ -public class ConversionException extends Exception { - - public ConversionException(@Nullable final Throwable cause) { - super(cause); - } - -} \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java index 8632db9..02a1e82 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationFunc.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationFunc.java @@ -6,7 +6,7 @@ import java.io.Serializable; /** * Created by Ilia Kurtov on 30/01/2017. - * Simple interface that gets one parameter {@link TInput} as input and returns other type {@link TReturn}. + * Simple interface that gets one parameter with {@link TInput} type as input and returns other type {@link TReturn} as a result. * Interface extends {@link Serializable} to survive after {@link ru.touchin.roboswag.components.navigation.AbstractState} recreation. * Created as a replace for {@link rx.functions.Func1} because it needed to be {@link Serializable} * @param input type. @@ -15,10 +15,10 @@ import java.io.Serializable; public interface ValidationFunc extends Serializable { /** - * - * @param input - * @return - * @throws Throwable + * The method maps some {@link TInput} type argument into a {@link TReturn} type. + * @param input data; + * @return mapped data into a {@link TReturn} type. + * @throws Throwable for catching conversion errors. */ @NonNull TReturn call(@NonNull final TInput input) throws Throwable; diff --git a/src/main/java/ru/touchin/templates/validation/validators/Validator.java b/src/main/java/ru/touchin/templates/validation/validators/Validator.java index 9abcdac..9ab45f3 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/Validator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/Validator.java @@ -29,7 +29,10 @@ import ru.touchin.templates.validation.ValidationState; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * This class holds information about current state of the object - {@link #getWrapperModel()}(that should be connected to some view), + * current error state {@link #getValidationState()}. Also you need to provide a {@link ValidationState} or class that extends it + * as an empty state. Eg, if you need to show some text in your view to show user that this view shouldn't be empty - pass needed state + * to the {@link #getValidationStateWhenEmpty()} */ public abstract class Validator implements Serializable { From e8d65bd71a26be740b75f9d06e3ef6cdf7a1ac31 Mon Sep 17 00:00:00 2001 From: Ilia Kurtov Date: Mon, 6 Feb 2017 14:05:10 +0300 Subject: [PATCH 11/11] commented finally --- .../templates/validation/ValidationState.java | 9 +++ .../BooleanValidationController.java | 10 ++- .../EditTextValidationController.java | 14 +++- .../SimpleValidationController.java | 15 +++- .../TwoWayValidationController.java | 73 ------------------- .../ValidationController.java | 62 ++++++++++++++-- .../validators/EditTextValidator.java | 39 +++++++++- .../validators/SameTypeValidator.java | 11 +++ .../validation/validators/Validator.java | 23 ++++++ 9 files changed, 169 insertions(+), 87 deletions(-) delete mode 100644 src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java diff --git a/src/main/java/ru/touchin/templates/validation/ValidationState.java b/src/main/java/ru/touchin/templates/validation/ValidationState.java index 7236981..2adb29e 100644 --- a/src/main/java/ru/touchin/templates/validation/ValidationState.java +++ b/src/main/java/ru/touchin/templates/validation/ValidationState.java @@ -55,10 +55,19 @@ public class ValidationState implements Serializable { this.code = code; } + /** + * Returns unique code of the {@link ValidationState}. + * @return code or the ValidationState. + */ public int getCode() { return code; } + /** + * Don't forget to override this method! + * @param object that you want to compare. + * @return true if objects equals and false otherwise. + */ @Override public boolean equals(final Object object) { return this == object diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java index 6b9e955..5d27370 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/BooleanValidationController.java @@ -27,14 +27,20 @@ import rx.Observable; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * {@link ValidationController} for {@link Boolean} models. Eg if you have some flag that should be bounded to checkbox. */ -public class BooleanValidationController extends TwoWayValidationController> { +public class BooleanValidationController extends ValidationController> { public BooleanValidationController(@NonNull final SameTypeValidator validator) { super(validator); } + /** + * This method validates bounded view. + * @param activatedObservable emits true when we need to show error on empty fields. Eg when user clicks on Done button but he missed some + * necessary fields to fill. + * @return observable without any concrete type. Simply subscribe to this method to make it works. + */ @NonNull public Observable validation(@NonNull final Observable activatedObservable) { return Observable.combineLatest(activatedObservable, getValidator().getWrapperModel().observe(), diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java index abf5e90..c8da94b 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/EditTextValidationController.java @@ -32,15 +32,25 @@ import rx.Observable; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * ValidationController for {@link android.widget.EditText} views. It has method {@link #validation} that response + * for validating view. To use this class properly, you need to subscribe to the {@link #modelAndViewUpdating} + * and to the {@link #validation} methods. */ public class EditTextValidationController - extends TwoWayValidationController> { + extends ValidationController> { public EditTextValidationController(@NonNull final EditTextValidator validationWrapper) { super(validationWrapper); } + /** + * This method validates bounded view. + * + * @param focusOutObservable that emits items when bounded view get focus in or out. + * @param activatedObservable emits true when we need to show error on empty fields. Eg when user clicks on Done button but he missed some + * necessary fields to fill. + * @return observable without any concrete type. Simply subscribe to this method to make it works. + */ @NonNull public Observable validation(@NonNull final Observable focusOutObservable, @NonNull final Observable activatedObservable) { return Observable.combineLatest(activatedObservable, diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java index 824117e..d8e9da9 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/SimpleValidationController.java @@ -8,13 +8,26 @@ import ru.touchin.templates.validation.ValidationState; import ru.touchin.templates.validation.validators.Validator; import rx.Observable; +/** + * Created by Ilia Kurtov on 24/01/2017. + * {@link ValidationController} for models that have the same modal as wrapper model. You can use it when you simply need to be sure + * that user have selected some item and it is not null. + * @param type of the model. + * @param corresponding {@link Validator} + */ public class SimpleValidationController> - extends TwoWayValidationController { + extends ValidationController { public SimpleValidationController(@NonNull final TValidator validator) { super(validator); } + /** + * This method validates bounded view. + * @param activatedObservable emits true when we need to show error on empty fields. Eg when user clicks on Done button but he missed some + * necessary fields to fill. + * @return observable without any concrete type. Simply subscribe to this method to make it works. + */ @NonNull public Observable validation(@NonNull final Observable activatedObservable) { return Observable.combineLatest(activatedObservable, diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java deleted file mode 100644 index 8ba8b53..0000000 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/TwoWayValidationController.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2016 Touch Instinct - * - * This file is part of RoboSwag library. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package ru.touchin.templates.validation.validationcontrollers; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import java.io.Serializable; - -import ru.touchin.templates.validation.ValidationState; -import ru.touchin.templates.validation.ViewWithError; -import ru.touchin.templates.validation.validators.Validator; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action1; - -/** - * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill - */ -public abstract class TwoWayValidationController - > - extends ValidationController { - - public TwoWayValidationController(@NonNull final TValidator validator) { - super(validator); - } - - @NonNull - public Observable modelAndViewUpdating(@Nullable final Observable viewStateObservable, - @NonNull final Action1 updateViewAction, - @NonNull final ViewWithError viewWithError) { - final Observable stateObservable = viewStateObservable != null - ? viewStateObservable.doOnNext(flag -> getValidator().getWrapperModel().set(flag)) - : Observable.empty(); - return Observable - .merge(getValidator().getWrapperModel().observe() - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext(updateViewAction), - getValidator().getValidationState().observe() - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext(validationState -> { - if (!showError(validationState)) { - viewWithError.hideError(); - } else { - viewWithError.showError(validationState); - } - }), - stateObservable); - } - - protected boolean showError(@NonNull final ValidationState validationState) { - return !validationState.equals(ValidationState.VALID) && !validationState.equals(ValidationState.INITIAL); - } - -} diff --git a/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java b/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java index 37dc600..7f209fb 100644 --- a/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java +++ b/src/main/java/ru/touchin/templates/validation/validationcontrollers/ValidationController.java @@ -20,25 +20,75 @@ package ru.touchin.templates.validation.validationcontrollers; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import java.io.Serializable; + +import ru.touchin.templates.validation.ValidationState; +import ru.touchin.templates.validation.ViewWithError; import ru.touchin.templates.validation.validators.Validator; +import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * This class holds information about related {@link Validator} class and how to connect model with view. */ -public class ValidationController { +public class ValidationController + > { @NonNull private final TValidator validator; - public ValidationController(@NonNull final TValidator validator) { - this.validator = validator; - } - @NonNull public TValidator getValidator() { return validator; } + public ValidationController(@NonNull final TValidator validator) { + this.validator = validator; + } + + /** + * Bind to this observable to connect view and model. If you provide first argument (viewStateObservable) - the connection would be two-way. + * If not - one-way. This method changes updates view with current {@link ValidationState}. + * @param viewStateObservable input view state {@link Observable}. + * Eg it can be observable with input text from the {@link android.widget.EditText} + * @param updateViewAction action that updates current state of the bounded view. + * @param viewWithError view that implements {@link ViewWithError} interface and could reacts to the validation errors. + * @return observable without any concrete type. Simply subscribe to this method to make it works. + */ + @NonNull + public Observable modelAndViewUpdating(@Nullable final Observable viewStateObservable, + @NonNull final Action1 updateViewAction, + @NonNull final ViewWithError viewWithError) { + final Observable stateObservable = viewStateObservable != null + ? viewStateObservable.doOnNext(flag -> getValidator().getWrapperModel().set(flag)) + : Observable.empty(); + return Observable + .merge(getValidator().getWrapperModel().observe() + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(updateViewAction), + getValidator().getValidationState().observe() + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(validationState -> { + if (!showError(validationState)) { + viewWithError.hideError(); + } else { + viewWithError.showError(validationState); + } + }), + stateObservable); + } + + /** + * Helper function to check if validation state in error state ot not + * @param validationState the state you want to check for the errors. + * @return true if validation state is in error and false otherwise. + */ + protected boolean showError(@NonNull final ValidationState validationState) { + return !validationState.equals(ValidationState.VALID) && !validationState.equals(ValidationState.INITIAL); + } + } \ No newline at end of file diff --git a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java index 75185e3..46fc435 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/EditTextValidator.java @@ -34,7 +34,9 @@ import rx.schedulers.Schedulers; /** * Created by Ilia Kurtov on 24/01/2017. - * TODO: fill + * Special class for {@link android.widget.EditText} validation. It holds information about how primary check on typing should be + * ({@link #getPrimaryCheck()} - get and set check here) and how final check should be processed too ({@link #getFinalCheck()} - get and set check + * here). */ public abstract class EditTextValidator extends Validator { @@ -45,18 +47,32 @@ public abstract class EditTextValidator extends Val @NonNull private final Changeable>> primaryCheck = new Changeable<>(null); + /** + * This flag needed to force showing errors. You don't want to show final error when you start to enter data in some field at first time. + * But if user leaves this view and final check not passed - you need to force to show an error till user not enters correct data and leaves + * the view. + * @return {@link NonNullChangeable} with current state of the flag - do we need to show errors from final checks while user types. + */ @NonNull public NonNullChangeable getShowFullCheck() { return showFullCheck; } + /** + * Use this method to get or set final check. + * @return final check. + */ @NonNull - public Changeable>> getFinalCheck() { + protected Changeable>> getFinalCheck() { return finalCheck; } + /** + * Use this method to get or set primary check. + * @return primary check. + */ @NonNull - public Changeable>> getPrimaryCheck() { + protected Changeable>> getPrimaryCheck() { return primaryCheck; } @@ -101,16 +117,33 @@ public abstract class EditTextValidator extends Val .map(HalfNullablePair::getFirst); } + /** + * Validates text with primary check. + * @param text - input text. + * @return {@link Observable} with the result of the primary check. + */ @NonNull public Observable primaryValidate(@NonNull final String text) { return processChecks(text, false); } + /** + * Validates text with final check. + * @param text - input text. + * @return {@link Observable} with the result of the final check. + */ @NonNull public Observable fullValidate(@NonNull final String text) { return processChecks(text, true); } + /** + * Validates text with primary and final check consequentially and returns {@link Observable} with {@link HalfNullablePair} of final state + * and resulting model. + * @param text - input text. + * @return pair with final {@link ValidationState} that is always not null and a model that we get after converting the text. + * Model can be null if validation fails on primary or final checks. + */ @NonNull public Observable> fullValidateAndGetModel(@NonNull final String text) { return createValidationObservable(text, true) diff --git a/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java index 50b7e38..6921c07 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/SameTypeValidator.java @@ -5,8 +5,19 @@ import android.support.annotation.NonNull; import java.io.Serializable; +/** + * Created by Ilia Kurtov on 24/01/2017. + * Class that simplifies work with {@link Validator}'s that have the same wrapper model and model type. + * @param model that should be bounded with a view. + */ public class SameTypeValidator extends Validator { + /** + * Simply returns the same model without any converting. + * @param wrapperModel input model. + * @return the same model as input parameter. + * @throws Throwable - in this case no throwable would be thrown. + */ @NonNull @Override protected TModel convertWrapperModelToModel(@NonNull final TModel wrapperModel) diff --git a/src/main/java/ru/touchin/templates/validation/validators/Validator.java b/src/main/java/ru/touchin/templates/validation/validators/Validator.java index 9ab45f3..f255f36 100644 --- a/src/main/java/ru/touchin/templates/validation/validators/Validator.java +++ b/src/main/java/ru/touchin/templates/validation/validators/Validator.java @@ -33,6 +33,10 @@ import ru.touchin.templates.validation.ValidationState; * current error state {@link #getValidationState()}. Also you need to provide a {@link ValidationState} or class that extends it * as an empty state. Eg, if you need to show some text in your view to show user that this view shouldn't be empty - pass needed state * to the {@link #getValidationStateWhenEmpty()} + * {@link TWrapperModel} is type of class that should be connected to its bounded view. {@link TModel} is type of class + * that represent object that we need at the end. Eg, if we want to enter some digits to {@link android.widget.EditText} + * and get {@link java.util.Date} as a result - {@link CharSequence} or {@link String} should be the {@link TWrapperModel} + * and {@link java.util.Date} would be the {@link TModel} type. */ public abstract class Validator implements Serializable { @@ -46,19 +50,38 @@ public abstract class Validator validationStateWhenEmpty = new NonNullChangeable<>(ValidationState.ERROR_NO_DESCRIPTION); + /** + * This method converts {@link TWrapperModel} into a {@link TModel}. + * @param wrapperModel - not null value that should be converted into a {@link TModel} object. + * @return converted wrapperModel into a {@link TModel}. + * @throws Throwable for the cases when converting cannot be processed. + */ @NonNull protected abstract TModel convertWrapperModelToModel(@NonNull final TWrapperModel wrapperModel) throws Throwable; + /** + * Call this method to get {@link Changeable} with {@link TWrapperModel} inside it that should be connected to its bounded view. + * @return {@link Changeable} with {@link TWrapperModel}. + */ @NonNull public Changeable getWrapperModel() { return wrapperModel; } + /** + * Returns current {@link ValidationState} or its successor. Needed to connect with bounded view and react to this state changes. + * @return current validation state. + */ @NonNull public NonNullChangeable getValidationState() { return validationState; } + /** + * This method needed to get {@link ValidationState} that needed to be shown when bounded view is empty and you need to show to user reminder, + * that he or she needs to fill this view. + * @return {@link ValidationState} that should be shown for an empty field. + */ @NonNull public NonNullChangeable getValidationStateWhenEmpty() { return validationStateWhenEmpty;