diff --git a/examples/books-example/pom.xml b/examples/books-example/pom.xml index f9414f32e..1f75bfdbe 100644 --- a/examples/books-example/pom.xml +++ b/examples/books-example/pom.xml @@ -5,7 +5,7 @@ de.saxsys.mvvmfx examples - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/contacts-example/pom.xml b/examples/contacts-example/pom.xml index bab2c11ea..d2b339661 100644 --- a/examples/contacts-example/pom.xml +++ b/examples/contacts-example/pom.xml @@ -6,7 +6,7 @@ de.saxsys.mvvmfx examples - 1.5.1 + 1.5.2-SNAPSHOT contacts-example diff --git a/examples/mini-examples/fx-root-example/pom.xml b/examples/mini-examples/fx-root-example/pom.xml index 35496f570..c327c7584 100644 --- a/examples/mini-examples/fx-root-example/pom.xml +++ b/examples/mini-examples/fx-root-example/pom.xml @@ -5,7 +5,7 @@ mini-examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/mini-examples/helloworld-without-fxml/pom.xml b/examples/mini-examples/helloworld-without-fxml/pom.xml index 43f11ff55..4002b7644 100644 --- a/examples/mini-examples/helloworld-without-fxml/pom.xml +++ b/examples/mini-examples/helloworld-without-fxml/pom.xml @@ -5,7 +5,7 @@ mini-examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/mini-examples/helloworld/pom.xml b/examples/mini-examples/helloworld/pom.xml index 96718839c..afae78070 100644 --- a/examples/mini-examples/helloworld/pom.xml +++ b/examples/mini-examples/helloworld/pom.xml @@ -5,7 +5,7 @@ mini-examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/mini-examples/pom.xml b/examples/mini-examples/pom.xml index 26d898a40..105edc14d 100644 --- a/examples/mini-examples/pom.xml +++ b/examples/mini-examples/pom.xml @@ -5,7 +5,7 @@ examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 pom diff --git a/examples/mini-examples/scopes-example/pom.xml b/examples/mini-examples/scopes-example/pom.xml index 333f5c562..aed7bbc21 100644 --- a/examples/mini-examples/scopes-example/pom.xml +++ b/examples/mini-examples/scopes-example/pom.xml @@ -5,7 +5,7 @@ mini-examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/mini-examples/synchronizefx-example/pom.xml b/examples/mini-examples/synchronizefx-example/pom.xml index edd09b538..8bec3c691 100644 --- a/examples/mini-examples/synchronizefx-example/pom.xml +++ b/examples/mini-examples/synchronizefx-example/pom.xml @@ -5,7 +5,7 @@ mini-examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/mini-examples/welcome-example/pom.xml b/examples/mini-examples/welcome-example/pom.xml index 4ee51c3ea..c3657f17b 100644 --- a/examples/mini-examples/welcome-example/pom.xml +++ b/examples/mini-examples/welcome-example/pom.xml @@ -5,7 +5,7 @@ mini-examples de.saxsys.mvvmfx - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/examples/pom.xml b/examples/pom.xml index 4d2d246eb..77d8b4401 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ de.saxsys mvvmfx-parent - 1.5.1 + 1.5.2-SNAPSHOT de.saxsys.mvvmfx diff --git a/examples/todomvc-example/pom.xml b/examples/todomvc-example/pom.xml index d28e0d0eb..dddd8388a 100644 --- a/examples/todomvc-example/pom.xml +++ b/examples/todomvc-example/pom.xml @@ -5,7 +5,7 @@ de.saxsys.mvvmfx examples - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/mvvmfx-archetype/pom.xml b/mvvmfx-archetype/pom.xml index 4c425a103..a34bdc68d 100644 --- a/mvvmfx-archetype/pom.xml +++ b/mvvmfx-archetype/pom.xml @@ -5,7 +5,7 @@ de.saxsys mvvmfx-parent - 1.5.1 + 1.5.2-SNAPSHOT diff --git a/mvvmfx-archetype/src/main/resources/archetype-resources/pom.xml b/mvvmfx-archetype/src/main/resources/archetype-resources/pom.xml index 46b637a8a..330696fd9 100644 --- a/mvvmfx-archetype/src/main/resources/archetype-resources/pom.xml +++ b/mvvmfx-archetype/src/main/resources/archetype-resources/pom.xml @@ -16,7 +16,7 @@ de.saxsys mvvmfx-parent - 1.5.1 + 1.5.2-SNAPSHOT pom import diff --git a/mvvmfx-cdi/pom.xml b/mvvmfx-cdi/pom.xml index a682d1a49..137712e53 100644 --- a/mvvmfx-cdi/pom.xml +++ b/mvvmfx-cdi/pom.xml @@ -20,7 +20,7 @@ de.saxsys mvvmfx-parent - 1.5.1 + 1.5.2-SNAPSHOT mvvmfx-cdi diff --git a/mvvmfx-guice/pom.xml b/mvvmfx-guice/pom.xml index 9bf6c36bd..4c7327717 100644 --- a/mvvmfx-guice/pom.xml +++ b/mvvmfx-guice/pom.xml @@ -20,7 +20,7 @@ de.saxsys mvvmfx-parent - 1.5.1 + 1.5.2-SNAPSHOT mvvmfx-guice diff --git a/mvvmfx-testing-utils/pom.xml b/mvvmfx-testing-utils/pom.xml index f109ccb95..6aee314d5 100644 --- a/mvvmfx-testing-utils/pom.xml +++ b/mvvmfx-testing-utils/pom.xml @@ -5,7 +5,7 @@ mvvmfx-parent de.saxsys - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/mvvmfx-utils/pom.xml b/mvvmfx-utils/pom.xml index b331a1cf1..ccd149eea 100644 --- a/mvvmfx-utils/pom.xml +++ b/mvvmfx-utils/pom.xml @@ -5,7 +5,7 @@ mvvmfx-parent de.saxsys - 1.5.1 + 1.5.2-SNAPSHOT 4.0.0 diff --git a/mvvmfx/pom.xml b/mvvmfx/pom.xml index 204c9a6ae..43666f493 100644 --- a/mvvmfx/pom.xml +++ b/mvvmfx/pom.xml @@ -20,7 +20,7 @@ de.saxsys mvvmfx-parent - 1.5.1 + 1.5.2-SNAPSHOT mvvmfx diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidationStatus.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidationStatus.java index 7a8133623..42cc27754 100644 --- a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidationStatus.java +++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidationStatus.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2015 Alexander Casall, Manuel Mauky - * + *

* 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 - * + *

+ * 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. @@ -15,14 +15,8 @@ ******************************************************************************/ package de.saxsys.mvvmfx.utils.validation; -import javafx.beans.property.ListProperty; -import javafx.beans.property.SimpleListProperty; -import javafx.collections.FXCollections; -import javafx.collections.ListChangeListener; - -import java.util.*; +import java.util.List; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * This class is used as {@link ValidationStatus} for {@link CompositeValidator}. @@ -66,32 +60,41 @@ void addMessage(Validator validator, List messages) getMessagesInternal().addAll( messages.stream() // ... we wrap them to keep track of the used validator. - .map(message -> new CompositeValidationMessageWrapper(message, validator)) - .collect(Collectors.toList())); + .map(message -> new CompositeValidationMessageWrapper(message, validator)) + .collect(Collectors.toList())); } /* Remove all given messages for the given validator. */ - void removeMessage(Validator validator, List messages) { - List messagesToRemove = + void removeMessage(final Validator validator, final List messages) { + final List messagesToRemove = getMessagesInternal().stream() - .filter(messages::contains) // only the given messages - .filter(message -> (message instanceof CompositeValidationMessageWrapper)) - .map(message -> (CompositeValidationMessageWrapper) message) - .filter(message -> message.getValidatorCode().equals(System.identityHashCode(validator))) - .collect(Collectors.toList()); + .filter(messages::contains) // only the given messages + .filter(message -> (message instanceof CompositeValidationMessageWrapper)) + .map(message -> (CompositeValidationMessageWrapper) message) + .filter(message -> message.getValidatorCode().equals(System.identityHashCode(validator))) + .collect(Collectors.toList()); - getMessagesInternal().removeAll(messagesToRemove); + getMessagesInternal().removeIf(validationMessage -> { + if (validationMessage instanceof CompositeValidationMessageWrapper) { + final CompositeValidationMessageWrapper wrapper = (CompositeValidationMessageWrapper) validationMessage; + return messagesToRemove.stream() + .filter(m -> m.getValidatorCode().equals(wrapper.getValidatorCode())) + .anyMatch(wrapper::equals); + } + + return false; + }); } /* * Remove all messages for this particular validator. */ - void removeMessage(Validator validator) { + void removeMessage(final Validator validator) { getMessagesInternal().removeIf(validationMessage -> { - if(validationMessage instanceof CompositeValidationMessageWrapper) { - CompositeValidationMessageWrapper wrapper = (CompositeValidationMessageWrapper) validationMessage; + if (validationMessage instanceof CompositeValidationMessageWrapper) { + final CompositeValidationMessageWrapper wrapper = (CompositeValidationMessageWrapper) validationMessage; return wrapper.getValidatorCode().equals(System.identityHashCode(validator)); } diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidator.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidator.java index 8c41c33f4..7cb1fb1d3 100644 --- a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidator.java +++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/validation/CompositeValidator.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2015 Alexander Casall, Manuel Mauky - * + *

* 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 - * + *

+ * 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. @@ -15,21 +15,20 @@ ******************************************************************************/ package de.saxsys.mvvmfx.utils.validation; +import java.util.HashMap; +import java.util.Map; + import javafx.beans.property.ListProperty; import javafx.beans.property.SimpleListProperty; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; -import java.util.HashMap; -import java.util.Map; - /** * This {@link Validator} implementation is used to compose multiple other validators. *

* The {@link ValidationStatus} of this validator will contain all messages of all registered validators. * - * * @author manuel.mauky */ public class CompositeValidator implements Validator { @@ -45,7 +44,7 @@ public CompositeValidator() { validators.addListener(new ListChangeListener() { @Override public void onChanged(Change c) { - while(c.next()) { + while (c.next()) { // When validators are added... c.getAddedSubList().forEach(validator -> { @@ -55,7 +54,7 @@ public void onChanged(Change c) { status.addMessage(validator, messages); final ListChangeListener changeListener = change -> { - while(change.next()) { + while (change.next()) { // add/remove messages for this particular validator status.addMessage(validator, change.getAddedSubList()); status.removeMessage(validator, change.getRemoved()); @@ -73,7 +72,7 @@ public void onChanged(Change c) { c.getRemoved().forEach(validator -> { status.removeMessage(validator); - if(listenerMap.containsKey(validator)){ + if (listenerMap.containsKey(validator)) { ListChangeListener changeListener = listenerMap.get(validator); validator.getValidationStatus().getMessages().removeListener(changeListener); @@ -85,21 +84,21 @@ public void onChanged(Change c) { }); } - + public CompositeValidator(Validator... validators) { this(); // before adding the validators we need to setup the listeners in the default constructor addValidators(validators); } - - + + public void addValidators(Validator... validators) { this.validators.addAll(validators); } - + public void removeValidators(Validator... validators) { this.validators.removeAll(validators); } - + @Override public ValidationStatus getValidationStatus() { return status; diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/validation/CompositeValidatorTest.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/validation/CompositeValidatorTest.java index 0bca51a22..d35d58495 100644 --- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/validation/CompositeValidatorTest.java +++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/validation/CompositeValidatorTest.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2015 Alexander Casall, Manuel Mauky - * + *

* 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 - * + *

+ * 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. @@ -15,39 +15,43 @@ ******************************************************************************/ package de.saxsys.mvvmfx.utils.validation; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleStringProperty; +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.common.base.Strings; + import org.junit.Before; import org.junit.Test; import java.util.List; import java.util.stream.Collectors; -import static org.assertj.core.api.Assertions.assertThat; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; /** * @author manuel.mauky */ public class CompositeValidatorTest { - + private ValidationStatus status; - + private BooleanProperty valid1 = new SimpleBooleanProperty(); private BooleanProperty valid2 = new SimpleBooleanProperty(); private CompositeValidator compositeValidator; private ObservableRuleBasedValidator validator1; private ObservableRuleBasedValidator validator2; - + @Before public void setup() { validator1 = new ObservableRuleBasedValidator(); validator1.addRule(valid1, ValidationMessage.error("error1")); - + validator2 = new ObservableRuleBasedValidator(); validator2.addRule(valid2, ValidationMessage.warning("warning2")); - - + + compositeValidator = new CompositeValidator(); status = compositeValidator.getValidationStatus(); } @@ -64,56 +68,56 @@ public void testValidatorConstructor() { assertThat(newValidator.getValidationStatus().isValid()).isFalse(); assertThat(newValidator.getValidationStatus().getMessages()).hasSize(2); } - + @Test public void testValidation() { compositeValidator.addValidators(validator1, validator2); - + valid1.set(true); valid2.set(true); - + assertThat(status.isValid()).isTrue(); - + valid1.setValue(false); - + assertThat(status.isValid()).isFalse(); assertThat(asStrings(status.getErrorMessages())).containsOnly("error1"); assertThat(asStrings(status.getWarningMessages())).isEmpty(); assertThat(asStrings(status.getMessages())).containsOnly("error1"); - + valid2.setValue(false); assertThat(status.isValid()).isFalse(); assertThat(asStrings(status.getErrorMessages())).containsOnly("error1"); assertThat(asStrings(status.getWarningMessages())).containsOnly("warning2"); assertThat(asStrings(status.getMessages())).containsOnly("error1", "warning2"); - + valid1.setValue(true); assertThat(status.isValid()).isFalse(); assertThat(asStrings(status.getErrorMessages())).isEmpty(); assertThat(asStrings(status.getWarningMessages())).containsOnly("warning2"); assertThat(asStrings(status.getMessages())).containsOnly("warning2"); - + valid2.setValue(true); assertThat(status.isValid()).isTrue(); assertThat(asStrings(status.getErrorMessages())).isEmpty(); assertThat(asStrings(status.getWarningMessages())).isEmpty(); assertThat(asStrings(status.getMessages())).isEmpty(); - + } - + @Test public void testLazyRegistration() { valid1.set(false); valid2.set(true); - + assertThat(status.isValid()).isTrue(); // no validator is registered at the moment - + compositeValidator.addValidators(validator2); assertThat(status.isValid()).isTrue(); // validator2 is valid - + compositeValidator.addValidators(validator1); assertThat(status.isValid()).isFalse(); - + compositeValidator.removeValidators(validator1); assertThat(status.isValid()).isTrue(); } @@ -207,6 +211,34 @@ public void testTestability() { } + /** + * Issue #413 + */ + @Test + public void validatorsMayNotDeleteEachOthersValidationMessages() { + final StringProperty prop1 = new SimpleStringProperty(); + final StringProperty prop2 = new SimpleStringProperty(); + final Validator notEmpty1 = new FunctionBasedValidator<>(prop1, v -> { + if (Strings.isNullOrEmpty(v)) { + return ValidationMessage.error("msg"); + } + return null; + }); + final Validator notEmpty2 = new FunctionBasedValidator<>(prop2, v -> { + if (Strings.isNullOrEmpty(v)) { + return ValidationMessage.error("msg"); + } + return null; + }); + final CompositeValidator compositeValidator = new CompositeValidator(notEmpty1, notEmpty2); + prop1.set(""); + prop2.set(""); + prop1.set("a"); + assertThat(notEmpty1.getValidationStatus().isValid()).isTrue(); + assertThat(notEmpty2.getValidationStatus().isValid()).isFalse(); + assertThat(compositeValidator.getValidationStatus().isValid()).isFalse(); + } + private List asStrings(List messages) { return messages diff --git a/pom.xml b/pom.xml index 828a287fd..a007a7181 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ de.saxsys mvvmfx-parent pom - 1.5.1 + 1.5.2-SNAPSHOT mvvmFX parent Application Framework for MVVM with JavaFX. http://www.saxsys.de