diff options
-rw-r--r-- | server/src/main/java/com/vaadin/data/Binder.java | 52 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/validator/NotNullValidator.java | 50 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/BinderTest.java | 68 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/validator/BeanValidatorTest.java | 6 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/validator/NotEmptyValidator.java (renamed from server/src/main/java/com/vaadin/data/validator/NotEmptyValidator.java) | 26 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/validator/NotNullValidatorTest.java | 42 |
6 files changed, 132 insertions, 112 deletions
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index f8ddace8a6..7912a55d72 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -422,6 +422,47 @@ public class Binder<BEAN> implements Serializable { */ public ValidationStatus<TARGET> validate(); + /** + * Sets the field to be required. This means two things: + * <ol> + * <li>the required indicator is visible</li> + * <li>the field value is validated for not being empty*</li> + * </ol> + * For localizing the error message, use + * {@link #setRequired(SerializableFunction)}. + * <p> + * *Value not being the equal to what {@link HasValue#getEmptyValue()} + * returns. + * + * @see #setRequired(SerializableFunction) + * @see HasValue#setRequiredIndicatorVisible(boolean) + * @see HasValue#isEmpty() + * @param errorMessage + * the error message to show for the invalid value + * @return this binding, for chaining + */ + public default Binding<BEAN, FIELDVALUE, TARGET> setRequired( + String errorMessage) { + return setRequired(context -> errorMessage); + } + + /** + * Sets the field to be required. This means two things: + * <ol> + * <li>the required indicator is visible</li> + * <li>the field value is validated for not being empty*</li> + * </ol> + * *Value not being the equal to what {@link HasValue#getEmptyValue()} + * returns. + * + * @see HasValue#setRequiredIndicatorVisible(boolean) + * @see HasValue#isEmpty() + * @param errorMessageProvider + * the provider for localized validation error message + * @return this binding, for chaining + */ + public Binding<BEAN, FIELDVALUE, TARGET> setRequired( + ErrorMessageProvider errorMessageProvider); } /** @@ -522,6 +563,17 @@ public class Binder<BEAN> implements Serializable { } @Override + public Binding<BEAN, FIELDVALUE, TARGET> setRequired( + ErrorMessageProvider errorMessageProvider) { + checkUnbound(); + + getField().setRequiredIndicatorVisible(true); + return withValidator( + value -> !Objects.equals(value, getField().getEmptyValue()), + errorMessageProvider); + } + + @Override public HasValue<FIELDVALUE> getField() { return field; } diff --git a/server/src/main/java/com/vaadin/data/validator/NotNullValidator.java b/server/src/main/java/com/vaadin/data/validator/NotNullValidator.java deleted file mode 100644 index c92aefac3b..0000000000 --- a/server/src/main/java/com/vaadin/data/validator/NotNullValidator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2000-2016 Vaadin Ltd. - * - * 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 com.vaadin.data.validator; - -import java.util.Objects; - -import com.vaadin.data.ValidationResult; -import com.vaadin.data.util.converter.ValueContext; - -/** - * This validator is used for validating properties that do not allow null - * values. - * - * @author Vaadin Ltd. - * @since 8.0 - */ -@SuppressWarnings("serial") -public class NotNullValidator extends AbstractValidator<String> { - - /** - * Creates a new NullValidator. - * - * @param errorMessage - * the error message to display on invalidation. - */ - public NotNullValidator(String errorMessage) { - super(errorMessage); - } - - @Override - public ValidationResult apply(String value, ValueContext context) { - return Objects.isNull(value) ? ValidationResult.error(getMessage(value)) - : ValidationResult.ok(); - } - -} diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index 6d33ab437b..22af7d2272 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -5,14 +5,18 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.util.Locale; import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.vaadin.data.Binder.Binding; import com.vaadin.data.util.converter.StringToIntegerConverter; -import com.vaadin.data.validator.NotNullValidator; +import com.vaadin.data.validator.NotEmptyValidator; +import com.vaadin.server.ErrorMessage; import com.vaadin.tests.data.bean.Person; import com.vaadin.tests.data.bean.Sex; import com.vaadin.ui.TextField; @@ -310,7 +314,7 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { public void withValidator_doesNotDisablesDefaulNullRepresentation() { String nullRepresentation = "foo"; binder.forField(nameField).withNullRepresentation(nullRepresentation) - .withValidator(new NotNullValidator("")) + .withValidator(new NotEmptyValidator<>("")) .bind(Person::getFirstName, Person::setFirstName); item.setFirstName(null); binder.setBean(item); @@ -321,4 +325,64 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { nameField.setValue(newValue); Assert.assertEquals(newValue, item.getFirstName()); } + + @Test + public void setRequired_withErrorMessage_fieldGetsRequiredIndicatorAndValidator() { + TextField textField = new TextField(); + Assert.assertFalse(textField.isRequiredIndicatorVisible()); + + Binding<Person, String, String> binding = binder.forField(textField); + Assert.assertFalse(textField.isRequiredIndicatorVisible()); + + binding.setRequired("foobar"); + Assert.assertTrue(textField.isRequiredIndicatorVisible()); + + binding.bind(Person::getFirstName, Person::setFirstName); + binder.setBean(item); + Assert.assertNull(textField.getErrorMessage()); + + textField.setValue(textField.getEmptyValue()); + ErrorMessage errorMessage = textField.getErrorMessage(); + Assert.assertNotNull(errorMessage); + Assert.assertEquals("foobar", errorMessage.getFormattedHtmlMessage()); + + textField.setValue("value"); + Assert.assertNull(textField.getErrorMessage()); + Assert.assertTrue(textField.isRequiredIndicatorVisible()); + } + + @Test + public void setRequired_withErrorMessageProvider_fieldGetsRequiredIndicatorAndValidator() { + TextField textField = new TextField(); + textField.setLocale(Locale.CANADA); + Assert.assertFalse(textField.isRequiredIndicatorVisible()); + + Binding<Person, String, String> binding = binder.forField(textField); + Assert.assertFalse(textField.isRequiredIndicatorVisible()); + AtomicInteger invokes = new AtomicInteger(); + + binding.setRequired(context -> { + invokes.incrementAndGet(); + Assert.assertSame(Locale.CANADA, context.getLocale().get()); + return "foobar"; + }); + Assert.assertTrue(textField.isRequiredIndicatorVisible()); + + binding.bind(Person::getFirstName, Person::setFirstName); + binder.setBean(item); + Assert.assertNull(textField.getErrorMessage()); + Assert.assertEquals(0, invokes.get()); + + textField.setValue(textField.getEmptyValue()); + ErrorMessage errorMessage = textField.getErrorMessage(); + Assert.assertNotNull(errorMessage); + Assert.assertEquals("foobar", errorMessage.getFormattedHtmlMessage()); + // validation is run twice, once for the field, then for all the fields + // for cross field validation... + Assert.assertEquals(2, invokes.get()); + + textField.setValue("value"); + Assert.assertNull(textField.getErrorMessage()); + Assert.assertTrue(textField.isRequiredIndicatorVisible()); + } }
\ No newline at end of file diff --git a/server/src/test/java/com/vaadin/data/validator/BeanValidatorTest.java b/server/src/test/java/com/vaadin/data/validator/BeanValidatorTest.java index fb504eea65..97f767bbc7 100644 --- a/server/src/test/java/com/vaadin/data/validator/BeanValidatorTest.java +++ b/server/src/test/java/com/vaadin/data/validator/BeanValidatorTest.java @@ -3,6 +3,7 @@ package com.vaadin.data.validator; import java.util.Calendar; import java.util.Locale; +import org.junit.After; import org.junit.Test; import com.vaadin.tests.data.bean.Address; @@ -77,6 +78,11 @@ public class BeanValidatorTest extends ValidatorTestBase { assertPasses(null, validator("nickname")); } + @After + public void tearDown() { + UI.setCurrent(null); + } + private BeanValidator validator(String propertyName) { return new BeanValidator(BeanToValidate.class, propertyName); } diff --git a/server/src/main/java/com/vaadin/data/validator/NotEmptyValidator.java b/server/src/test/java/com/vaadin/data/validator/NotEmptyValidator.java index 2223c333cb..61cacf8b51 100644 --- a/server/src/main/java/com/vaadin/data/validator/NotEmptyValidator.java +++ b/server/src/test/java/com/vaadin/data/validator/NotEmptyValidator.java @@ -17,6 +17,7 @@ package com.vaadin.data.validator; import java.util.Objects; +import com.vaadin.data.Binder.Binding; import com.vaadin.data.HasValue; import com.vaadin.data.ValidationResult; import com.vaadin.data.Validator; @@ -29,27 +30,16 @@ import com.vaadin.data.util.converter.ValueContext; * This validator works similar to {@link NotNullValidator} but in addition it * also check whether the value is not an empty String. * <p> - * The main purpose of this validator is its usage with {@link HasRequired} - * field instances. + * This validator can be suitable for fields that have been marked as required + * with {@link HasValue#setRequiredIndicatorVisible(boolean)}. * <p> - * If the field is required, it is visually indicated in the user interface. - * Furthermore, required fields requires "non-empty" validator. So in addition - * to call {@link HasRequired#setRequiredIndicatorVisible(boolean)} method one - * should add an instance of this validator explicitly so the code looks like - * this: - * - * <pre> - * <code> - * Binder<Bean,String, String> binder = new Binder<>(); - * TextField name = new TextField(); - * name.setRequiredIndicatorVisible(true); - * binder.forField(name).withValidator( - * new NonEmptyValidator("Name cannot be empty")) - * .bind(Bean::getName, Bean::setName); - * </code> - * </pre> + * Note that {@link Binding#setRequired(com.vaadin.data.ErrorMessageProvider)} + * does almost the same thing, but verifies against the value NOT being equal to + * what {@link HasValue#getEmptyValue()} returns and sets the required indicator + * visible with {@link HasValue#setRequiredIndicatorVisible(boolean)}. * * @see HasValue#setRequiredIndicatorVisible(boolean) + * @see Binding#setRequired(com.vaadin.data.ErrorMessageProvider) * @author Vaadin Ltd * @since 8.0 * diff --git a/server/src/test/java/com/vaadin/data/validator/NotNullValidatorTest.java b/server/src/test/java/com/vaadin/data/validator/NotNullValidatorTest.java deleted file mode 100644 index 24b95bf58a..0000000000 --- a/server/src/test/java/com/vaadin/data/validator/NotNullValidatorTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2000-2016 Vaadin Ltd. - * - * 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 com.vaadin.data.validator; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.data.ValidationResult; -import com.vaadin.data.util.converter.ValueContext; - -public class NotNullValidatorTest { - - @Test - public void nullValueIsDisallowed() { - NotNullValidator validator = new NotNullValidator("foo"); - ValidationResult result = validator.apply(null, new ValueContext()); - Assert.assertTrue(result.isError()); - Assert.assertEquals("foo", result.getErrorMessage()); - } - - @Test - public void nonNullValueIsAllowed() { - NotNullValidator validator = new NotNullValidator("foo"); - ValidationResult result = validator.apply("bar", new ValueContext()); - Assert.assertFalse(result.isError()); - Assert.assertFalse(result.isError()); - } - -} |