diff options
author | Tatu Lund <tatu@vaadin.com> | 2020-04-21 11:38:19 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-21 11:38:19 +0300 |
commit | d35bd4cde4ae0074d68c7e1f10f2be8757403cc7 (patch) | |
tree | 3b9765e462e939150715b9c037d4297a9ed911f2 /server/src | |
parent | 565eeb5b5a85e6ce6310e0098977f853869f01ba (diff) | |
download | vaadin-framework-d35bd4cde4ae0074d68c7e1f10f2be8757403cc7.tar.gz vaadin-framework-d35bd4cde4ae0074d68c7e1f10f2be8757403cc7.zip |
Add methods to control validation (#11945)
- Enable / disable all validators on Binder level
- Enable / disable validators on Binding level
- add writeBeanAsDraft(bean,boolean) for writing draft bean with validators disabled
Fixes https://github.com/vaadin/framework/issues/10709
Co-authored-by: Zhe Sun <31067185+ZheSun88@users.noreply.github.com>
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/main/java/com/vaadin/data/Binder.java | 122 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/BinderTest.java | 79 |
2 files changed, 191 insertions, 10 deletions
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 07dbf20ce4..c64602edae 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -254,6 +254,25 @@ public class Binder<BEAN> implements Serializable { * @since 8.10 */ public boolean isAsRequiredEnabled(); + + /** + * Define whether validators are disabled or enabled for this + * specific binding. + * + * @param validatorsDisabled A boolean value + * + * @since + */ + public void setValidatorsDisabled(boolean validatorsDisabled); + + /** + * Returns if validators are currently disabled or not + * + * @return A boolean value + * + * @since + */ + public boolean isValidatorsDisabled(); } /** @@ -800,6 +819,7 @@ public class Binder<BEAN> implements Serializable { private final HasValue<FIELDVALUE> field; private BindingValidationStatusHandler statusHandler; private boolean isStatusHandlerChanged; + private Binding<BEAN, TARGET> binding; private boolean bound; @@ -855,6 +875,7 @@ public class Binder<BEAN> implements Serializable { bound = true; getBinder().incompleteBindings.remove(getField()); + this.binding = binding; return binding; } @@ -889,6 +910,7 @@ public class Binder<BEAN> implements Serializable { Binding binding = ((BindingBuilder) finalBinding).bind(getter, setter); getBinder().boundProperties.put(propertyName, binding); + this.binding = binding; return binding; } finally { getBinder().incompleteMemberFieldBindings.remove(getField()); @@ -909,8 +931,17 @@ public class Binder<BEAN> implements Serializable { checkUnbound(); Objects.requireNonNull(validator, "validator cannot be null"); + Validator<? super TARGET> wrappedValidator = ((value, context) -> { + if (getBinder().isValidatorsDisabled() || + (binding != null && binding.isValidatorsDisabled())) { + return ValidationResult.ok(); + } else { + return validator.apply(value, context); + } + }); + converterValidatorChain = ((Converter<FIELDVALUE, TARGET>) converterValidatorChain) - .chain(new ValidatorAsConverter<>(validator)); + .chain(new ValidatorAsConverter<>(wrappedValidator)); return this; } @@ -1059,6 +1090,8 @@ public class Binder<BEAN> implements Serializable { private boolean asRequiredSet; + private boolean validatorsDisabled = false; + public BindingImpl(BindingBuilderImpl<BEAN, FIELDVALUE, TARGET> builder, ValueProvider<BEAN, TARGET> getter, Setter<BEAN, TARGET> setter) { @@ -1341,6 +1374,16 @@ public class Binder<BEAN> implements Serializable { public boolean isAsRequiredEnabled() { return field.isRequiredIndicatorVisible(); } + + @Override + public void setValidatorsDisabled(boolean validatorsDisabled) { + this.validatorsDisabled = validatorsDisabled; + } + + @Override + public boolean isValidatorsDisabled() { + return validatorsDisabled; + } } /** @@ -1446,6 +1489,8 @@ public class Binder<BEAN> implements Serializable { private Set<Binding<BEAN, ?>> changedBindings = new LinkedHashSet<>(); + private boolean validatorsDisabled = false; + /** * Creates a binder using a custom {@link PropertySet} implementation for * finding and resolving property names for @@ -1862,7 +1907,28 @@ public class Binder<BEAN> implements Serializable { * @since 8.10 */ public void writeBeanAsDraft(BEAN bean) { - doWriteDraft(bean, new ArrayList<>(bindings)); + doWriteDraft(bean, new ArrayList<>(bindings),false); + } + + /** + * Writes successfully converted changes from the bound fields bypassing + * all the Validation, or all fields passing conversion if forced = true. + * If the conversion fails, the value written to the bean will be null. + * + * @see #writeBean(Object) + * @see #writeBeanIfValid(Object) + * @see #readBean(Object) + * @see #setBean(Object) + * + * @param bean + * the object to which to write the field values, not + * {@code null} + * @param forced + * disable all Validators during write + * @since + */ + public void writeBeanAsDraft(BEAN bean, boolean forced) { + doWriteDraft(bean, new ArrayList<>(bindings),forced); } /** @@ -1960,14 +2026,23 @@ public class Binder<BEAN> implements Serializable { * the bean to write field values into * @param bindings * the set of bindings to write to the bean + * @param forced + * disable validators during write if true */ - @SuppressWarnings({ "unchecked" }) - private void doWriteDraft(BEAN bean, - Collection<Binding<BEAN, ?>> bindings) { + private void doWriteDraft(BEAN bean, + Collection<Binding<BEAN, ?>> bindings, boolean forced) { Objects.requireNonNull(bean, "bean cannot be null"); - bindings.forEach(binding -> ((BindingImpl<BEAN, ?, ?>) binding) - .writeFieldValue(bean)); + if (!forced) { + bindings.forEach(binding -> ((BindingImpl<BEAN, ?, ?>) binding) + .writeFieldValue(bean)); + } else { + boolean isDisabled = isValidatorsDisabled(); + setValidatorsDisabled(true); + bindings.forEach(binding -> ((BindingImpl<BEAN, ?, ?>) binding) + .writeFieldValue(bean)); + setValidatorsDisabled(isDisabled); + } } /** @@ -2037,7 +2112,14 @@ public class Binder<BEAN> implements Serializable { */ public Binder<BEAN> withValidator(Validator<? super BEAN> validator) { Objects.requireNonNull(validator, "validator cannot be null"); - validators.add(validator); + Validator<? super BEAN> wrappedValidator = ((value, context) -> { + if (isValidatorsDisabled()) { + return ValidationResult.ok(); + } else { + return validator.apply(value, context); + } + }); + validators.add(wrappedValidator); return this; } @@ -3035,6 +3117,30 @@ public class Binder<BEAN> implements Serializable { .ifPresent(Binding::unbind); } + /** + * Control whether validators including bean level validators are + * disabled or enabled globally for this Binder. + * + * @param validatorsDisabled Boolean value + * + * @since + */ + public void setValidatorsDisabled(boolean validatorsDisabled) { + this.validatorsDisabled = validatorsDisabled; + } + + /** + * Returns if the validators including bean level validators + * are disabled or enabled for this Binder. + * + * @return Boolean value + * + * @since + */ + public boolean isValidatorsDisabled() { + return validatorsDisabled; + } + private static final Logger getLogger() { return Logger.getLogger(Binder.class.getName()); } diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index b3fe5a8194..b64dee9c6b 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -274,8 +274,11 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { Binder<Person> binder = new Binder<>(); binder.forField(nameField) .withValidator((value,context) -> { - if (value.equals("Mike")) return ValidationResult.ok(); - else return ValidationResult.error("value must be Mike"); + if (value.equals("Mike")) { + return ValidationResult.ok(); + } else { + return ValidationResult.error("value must be Mike"); + } }) .bind(Person::getFirstName, Person::setFirstName); binder.forField(ageField) @@ -300,6 +303,78 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { // age is written to draft even if firstname validation // fails assertEquals(age, person.getAge()); + + binder.writeBeanAsDraft(person,true); + // name is now written despite validation as write was forced + assertEquals(fieldValue, person.getFirstName()); + } + + @Test + public void save_bound_bean_disable_validation_binding() throws ValidationException { + Binder<Person> binder = new Binder<>(); + Binding<Person, String> nameBinding = binder.forField(nameField) + .withValidator((value,context) -> { + if (value.equals("Mike")) { + return ValidationResult.ok(); + } else { + return ValidationResult.error("value must be Mike"); + } + }) + .bind(Person::getFirstName, Person::setFirstName); + binder.forField(ageField) + .withConverter(new StringToIntegerConverter("")) + .bind(Person::getAge, Person::setAge); + + Person person = new Person(); + + String fieldValue = "John"; + nameField.setValue(fieldValue); + + int age = 10; + ageField.setValue("10"); + + person.setFirstName("Mark"); + + nameBinding.setValidatorsDisabled(true); + binder.writeBean(person); + + // name is now written as validation was disabled + assertEquals(fieldValue, person.getFirstName()); + assertEquals(age, person.getAge()); + } + + @Test + public void save_bound_bean_disable_validation_binder() throws ValidationException { + Binder<Person> binder = new Binder<>(); + binder.forField(nameField) + .withValidator((value,context) -> { + if (value.equals("Mike")) { + return ValidationResult.ok(); + } else { + return ValidationResult.error("value must be Mike"); + } + }) + .bind(Person::getFirstName, Person::setFirstName); + binder.forField(ageField) + .withConverter(new StringToIntegerConverter("")) + .bind(Person::getAge, Person::setAge); + + Person person = new Person(); + + String fieldValue = "John"; + nameField.setValue(fieldValue); + + int age = 10; + ageField.setValue("10"); + + person.setFirstName("Mark"); + + binder.setValidatorsDisabled(true); + binder.writeBean(person); + + // name is now written as validation was disabled + assertEquals(fieldValue, person.getFirstName()); + assertEquals(age, person.getAge()); } @Test |