summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlia Motornyi <elmot@vaadin.com>2017-06-29 10:30:57 +0300
committerGitHub <noreply@github.com>2017-06-29 10:30:57 +0300
commit9c3868e897541c014e19341f3d58066734f8a6c0 (patch)
tree6e0d00326c37e80d6478895e5a2470b6a203e445
parentb2c0ac2bac558a4bc497fa3a6d29b8f030511e1a (diff)
downloadvaadin-framework-9c3868e897541c014e19341f3d58066734f8a6c0.tar.gz
vaadin-framework-9c3868e897541c014e19341f3d58066734f8a6c0.zip
Add an optional HasValue to a ValueContext
-rw-r--r--documentation/components/components-fields.asciidoc6
-rw-r--r--server/src/main/java/com/vaadin/data/Binder.java4
-rw-r--r--server/src/main/java/com/vaadin/data/ValueContext.java54
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractDateField.java2
-rw-r--r--server/src/test/java/com/vaadin/data/ValueContextTest.java23
5 files changed, 85 insertions, 4 deletions
diff --git a/documentation/components/components-fields.asciidoc b/documentation/components/components-fields.asciidoc
index 1415f98e73..77a308a3bb 100644
--- a/documentation/components/components-fields.asciidoc
+++ b/documentation/components/components-fields.asciidoc
@@ -170,7 +170,11 @@ class MyValidator implements Validator<String> {
Since [interfacename]#Validator# is a functional
interface, you can often simply write a lambda expression instead of a full class
declaration. There is also an [methodname]#withValidator# overload that creates a
-validator from a boolean function and an error message.
+validator from a boolean function and an error message. If the application requires
+more sophisticated validation diagnostics (e.g. locale-specific), there is a
+method [methodname]#withValidator#, which uses a boolean function and an [classname]#ErrorMessageProvider#.
+The [classname]#ErrorMessageProvider# can compose diagnostic messages based on the locale of the validation
+and the source component value, which are provided with the [classname]#ValueContext#.
[source, java]
----
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java
index c36029aa83..26720a3274 100644
--- a/server/src/main/java/com/vaadin/data/Binder.java
+++ b/server/src/main/java/com/vaadin/data/Binder.java
@@ -872,9 +872,9 @@ public class Binder<BEAN> implements Serializable {
*/
protected ValueContext createValueContext() {
if (field instanceof Component) {
- return new ValueContext((Component) field);
+ return new ValueContext((Component) field, field);
}
- return new ValueContext(findLocale());
+ return new ValueContext(null, field, findLocale());
}
/**
diff --git a/server/src/main/java/com/vaadin/data/ValueContext.java b/server/src/main/java/com/vaadin/data/ValueContext.java
index 07857d34af..4ce1111ed0 100644
--- a/server/src/main/java/com/vaadin/data/ValueContext.java
+++ b/server/src/main/java/com/vaadin/data/ValueContext.java
@@ -33,6 +33,7 @@ import com.vaadin.ui.UI;
public class ValueContext implements Serializable {
private final Component component;
+ private final HasValue<?> hasValue;
private final Locale locale;
/**
@@ -40,6 +41,7 @@ public class ValueContext implements Serializable {
*/
public ValueContext() {
component = null;
+ hasValue = null;
locale = findLocale();
}
@@ -52,6 +54,7 @@ public class ValueContext implements Serializable {
public ValueContext(Locale locale) {
component = null;
this.locale = locale;
+ hasValue = null;
}
/**
@@ -59,14 +62,54 @@ public class ValueContext implements Serializable {
*
* @param component
* The component related to current value. Can be null.
+ * If the component implements {@link HasValue}, it will be returned by {@link #getHasValue()} as well.
*/
+ @SuppressWarnings("unchecked")
public ValueContext(Component component) {
Objects.requireNonNull(component,
"Component can't be null in ValueContext construction");
this.component = component;
+ if(component instanceof HasValue) {
+ hasValue = (HasValue<?>) component;
+ } else {
+ hasValue = null;
+ }
+ locale = findLocale();
+ }
+
+ /**
+ * Constructor for {@code ValueContext}.
+ *
+ * @param component
+ * The component related to current value. Can be null.
+ * @param hasValue
+ * The value source related to current value. Can be null.
+ */
+ public ValueContext(Component component, HasValue<?> hasValue) {
+ Objects.requireNonNull(component,
+ "Component can't be null in ValueContext construction");
+ this.component = component;
+ this.hasValue = hasValue;
locale = findLocale();
}
+ /**
+ * Constructor for {@code ValueContext}.
+ *
+ * @param
+ * component
+ * The component can be {@code null}.
+ * @param locale
+ * The locale used with conversion. Can be {@code null}.
+ * @param hasValue
+ * The value source related to current value. Can be {@code null}.
+ */
+ public ValueContext(Component component, HasValue<?> hasValue, Locale locale) {
+ this.component = component;
+ this.hasValue = hasValue;
+ this.locale = locale;
+ }
+
private Locale findLocale() {
Locale l = null;
if (component != null) {
@@ -100,4 +143,15 @@ public class ValueContext implements Serializable {
public Optional<Locale> getLocale() {
return Optional.ofNullable(locale);
}
+
+ /**
+ * Returns an {@code Optional} for the {@code HasValue} used in the value
+ * conversion. In certain complicated cases, ex. cross-field validation, HasValue might be not available.
+ *
+ * @return the optional of {@code HasValue}
+ */
+ @SuppressWarnings("unused")
+ public Optional<HasValue<?>> getHasValue() {
+ return Optional.ofNullable(hasValue);
+ }
}
diff --git a/server/src/main/java/com/vaadin/ui/AbstractDateField.java b/server/src/main/java/com/vaadin/ui/AbstractDateField.java
index 06e6d74c30..0e738de253 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractDateField.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractDateField.java
@@ -684,7 +684,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
} else {
RangeValidator<T> validator = getRangeValidator();
ValidationResult result = validator.apply(value,
- new ValueContext(this));
+ new ValueContext(this, this));
if (result.isError()) {
setComponentError(new UserError(getDateOutOfRangeMessage()));
}
diff --git a/server/src/test/java/com/vaadin/data/ValueContextTest.java b/server/src/test/java/com/vaadin/data/ValueContextTest.java
index 2f13a71dbb..b96f7463cb 100644
--- a/server/src/test/java/com/vaadin/data/ValueContextTest.java
+++ b/server/src/test/java/com/vaadin/data/ValueContextTest.java
@@ -3,6 +3,7 @@ package com.vaadin.data;
import java.util.Locale;
import java.util.Objects;
+import com.vaadin.ui.CheckBox;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -46,6 +47,28 @@ public class ValueContextTest extends UI {
Locale.getDefault(), locale);
}
+ @Test
+ public void testHasValue1() {
+ setLocale(null);
+ ValueContext fromComponent = new ValueContext(textField);
+ Assert.assertEquals(textField, fromComponent.getHasValue().get());
+ }
+
+ @Test
+ public void testHasValue2() {
+ setLocale(null);
+ ValueContext fromComponent = new ValueContext(new CheckBox(), textField);
+ Assert.assertEquals(textField, fromComponent.getHasValue().get());
+ }
+
+ @Test
+ public void testHasValue3() {
+ setLocale(null);
+ ValueContext fromComponent = new ValueContext(new CheckBox(), textField, Locale.CANADA);
+ Assert.assertEquals(textField, fromComponent.getHasValue().get());
+ Assert.assertEquals(Locale.CANADA, fromComponent.getLocale().get());
+ }
+
@Before
public void setUp() {
setLocale(UI_LOCALE);