Skip to content

Commit

Permalink
Added equality predicate to Binding level
Browse files Browse the repository at this point in the history
and deprecated the old handleFieldValueChange method
  • Loading branch information
onuridrisoglu committed Jun 17, 2024
1 parent c6f5f92 commit e48ac6b
Showing 1 changed file with 63 additions and 1 deletion.
64 changes: 63 additions & 1 deletion flow-data/src/main/java/com/vaadin/flow/data/binder/Binder.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.vaadin.flow.data.converter.StringToIntegerConverter;
import com.vaadin.flow.data.validator.BeanValidator;
import com.vaadin.flow.dom.Style;
import com.vaadin.flow.function.SerializableBiPredicate;
import com.vaadin.flow.function.SerializableConsumer;
import com.vaadin.flow.function.SerializableFunction;
import com.vaadin.flow.function.SerializablePredicate;
Expand Down Expand Up @@ -320,6 +321,8 @@ default BindingValidationStatus<TARGET> validate() {
* changes, otherwise {@literal false}.
*/
boolean hasChanges();

SerializableBiPredicate<Object, Object> getEqualityPredicate();
}

/**
Expand Down Expand Up @@ -949,6 +952,18 @@ BindingBuilder<BEAN, TARGET> asRequired(
*/
public BindingBuilder<BEAN, TARGET> asRequired(
Validator<TARGET> customRequiredValidator);

/**
* Sets the {@code equalityPredicate} used to compare the current value of a field with its initial value.
* <p>
* The default implementation uses {@link Objects#equals(Object, Object)}, but a custom equality predicate
* can be provided for cases where the value type does not support the standard {@code equals} method.
* </p>
*
* @param equalityPredicate the predicate to use for equality comparison
* @return this {@code BindingBuilder}, for method chaining
*/
public BindingBuilder<BEAN, TARGET> withEqualityPredicate(SerializableBiPredicate<Object, Object> equalityPredicate);
}

/**
Expand Down Expand Up @@ -983,6 +998,13 @@ protected static class BindingBuilderImpl<BEAN, FIELDVALUE, TARGET>
private boolean asRequiredSet;

private Boolean defaultValidatorEnabled;

/**
* A predicate used to compare the current value of a field with its initial value.
* The default implementation is {@link Objects#equals(Object, Object)}
* but can be customized if the value type does not support equals
*/
private SerializableBiPredicate<Object, Object> equalityPredicate = (val1, val2) -> Objects.equals(val1, val2);

/**
* Creates a new binding builder associated with the given field.
Expand Down Expand Up @@ -1201,6 +1223,13 @@ public BindingBuilder<BEAN, TARGET> asRequired(
}
});
}

@Override
public BindingBuilder<BEAN, TARGET> withEqualityPredicate(SerializableBiPredicate<Object, Object> equalityPredicate) {
Objects.requireNonNull(equalityPredicate, "equality predicate cannot be null");
this.equalityPredicate = equalityPredicate;
return this;
}

/**
* Implements {@link #withConverter(Converter)} method with additional
Expand Down Expand Up @@ -1315,6 +1344,8 @@ protected static class BindingImpl<BEAN, FIELDVALUE, TARGET>
private Registration onValidationStatusChange;

private Boolean defaultValidatorEnabled;

private SerializableBiPredicate<Object, Object> equalityPredicate;

public BindingImpl(BindingBuilderImpl<BEAN, FIELDVALUE, TARGET> builder,
ValueProvider<BEAN, TARGET> getter,
Expand All @@ -1326,6 +1357,8 @@ public BindingImpl(BindingBuilderImpl<BEAN, FIELDVALUE, TARGET> builder,
converterValidatorChain = ((Converter<FIELDVALUE, TARGET>) builder.converterValidatorChain);

defaultValidatorEnabled = builder.defaultValidatorEnabled;

equalityPredicate = builder.equalityPredicate;

onValueChange = getField().addValueChangeListener(
event -> handleFieldValueChange(event));
Expand Down Expand Up @@ -1702,6 +1735,11 @@ public boolean hasChanges() throws IllegalStateException {

return this.binder.hasChanges(this);
}

@Override
public SerializableBiPredicate<Object, Object> getEqualityPredicate() {
return equalityPredicate;
}
}

/**
Expand Down Expand Up @@ -1917,6 +1955,30 @@ public static <BEAN> Binder<BEAN> withPropertySet(
return new Binder<>(propertySet);
}

/**
* Informs the Binder that a value in Binding was changed.
*
* If {@link #readBean(Object)} was used, this method will only validate the
* changed binding and ignore state of other bindings.
*
* If {@link #setBean(Object)} was used, all pending changed bindings will
* be validated and non-changed ones will be ignored. The changed value will
* be written to the bean immediately, assuming that Binder-level validators
* also pass.
*
* @param binding
* the binding whose value has been changed
*
* @Deprecated(since = "24.5", forRemoval = true)
*/
protected void handleFieldValueChange(Binding<BEAN, ?> binding) {
if (getBean() == null) {
binding.validate();
} else {
doWriteIfValid(getBean(), changedBindings);
}
}

/**
* Informs the Binder that a value in Binding was changed.
*
Expand Down Expand Up @@ -1962,7 +2024,7 @@ protected void handleFieldValueChange(Binding<BEAN, ?> binding, ValueChangeEvent
* @return true if the field value is reverted
*/
protected boolean isRevertedToInitialValue(Binding<BEAN, ?> binding, Object newValue) {
return Objects.equals(bindingInitialValuesMap.get(binding), newValue);
return binding.getEqualityPredicate().test(bindingInitialValuesMap.get(binding), newValue);
}

/**
Expand Down

0 comments on commit e48ac6b

Please sign in to comment.