diff options
author | Teemu Suo-Anttila <tsuoanttila@users.noreply.github.com> | 2018-03-19 19:04:48 +0200 |
---|---|---|
committer | Ilia Motornyi <elmot@vaadin.com> | 2018-03-19 19:04:48 +0200 |
commit | 0a3e1640c69b2a0e9ae772eca08c1dd990aafb7c (patch) | |
tree | c768c6a402ed7422c9dfa401c08b1516a28ead7d /server | |
parent | 5aa6433972b2b0980bcb9a658f28a72e426453f8 (diff) | |
download | vaadin-framework-0a3e1640c69b2a0e9ae772eca08c1dd990aafb7c.tar.gz vaadin-framework-0a3e1640c69b2a0e9ae772eca08c1dd990aafb7c.zip |
Add option to use error message provider for StringTo converters (#10711)
Diffstat (limited to 'server')
9 files changed, 294 insertions, 35 deletions
diff --git a/server/src/main/java/com/vaadin/data/converter/AbstractStringToNumberConverter.java b/server/src/main/java/com/vaadin/data/converter/AbstractStringToNumberConverter.java index b3aff7c0e7..3918dc5447 100644 --- a/server/src/main/java/com/vaadin/data/converter/AbstractStringToNumberConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/AbstractStringToNumberConverter.java @@ -21,6 +21,7 @@ import java.text.ParsePosition; import java.util.Locale; import com.vaadin.data.Converter; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -39,11 +40,29 @@ import com.vaadin.data.ValueContext; public abstract class AbstractStringToNumberConverter<T extends Number> implements Converter<String, T> { - private final String errorMessage; + private final ErrorMessageProvider errorMessageProvider; private T emptyValue; /** * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + protected AbstractStringToNumberConverter(T emptyValue, + ErrorMessageProvider errorMessageProvider) { + this.emptyValue = emptyValue; + this.errorMessageProvider = errorMessageProvider; + } + + /** + * Creates a new converter instance with the given empty string value and * error message. * * @param emptyValue @@ -54,8 +73,7 @@ public abstract class AbstractStringToNumberConverter<T extends Number> */ protected AbstractStringToNumberConverter(T emptyValue, String errorMessage) { - this.emptyValue = emptyValue; - this.errorMessage = errorMessage; + this(emptyValue, ctx -> errorMessage); } /** @@ -81,11 +99,12 @@ public abstract class AbstractStringToNumberConverter<T extends Number> * * @param value * The value to convert - * @param locale - * The locale to use for conversion + * @param context + * The value context for conversion * @return The converted value */ - protected Result<Number> convertToNumber(String value, Locale locale) { + protected Result<Number> convertToNumber(String value, + ValueContext context) { if (value == null) { return Result.ok(null); } @@ -96,9 +115,10 @@ public abstract class AbstractStringToNumberConverter<T extends Number> // Parse and detect errors. If the full string was not used, it is // an error. ParsePosition parsePosition = new ParsePosition(0); - Number parsedValue = getFormat(locale).parse(value, parsePosition); + Number parsedValue = getFormat(context.getLocale().orElse(null)) + .parse(value, parsePosition); if (parsePosition.getIndex() != value.length()) { - return Result.error(getErrorMessage()); + return Result.error(getErrorMessage(context)); } if (parsedValue == null) { @@ -114,8 +134,8 @@ public abstract class AbstractStringToNumberConverter<T extends Number> * * @return the error message */ - protected String getErrorMessage() { - return errorMessage; + protected String getErrorMessage(ValueContext context) { + return errorMessageProvider.apply(context); } @Override diff --git a/server/src/main/java/com/vaadin/data/converter/StringToBigDecimalConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToBigDecimalConverter.java index 9418e53e1f..c3a55561bf 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToBigDecimalConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToBigDecimalConverter.java @@ -20,6 +20,7 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -66,6 +67,37 @@ public class StringToBigDecimalConverter super(emptyValue, errorMessage); } + /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToBigDecimalConverter( + ErrorMessageProvider errorMessageProvider) { + this(null, errorMessageProvider); + } + + /** + * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToBigDecimalConverter(BigDecimal emptyValue, + ErrorMessageProvider errorMessageProvider) { + super(emptyValue, errorMessageProvider); + } + @Override protected NumberFormat getFormat(Locale locale) { NumberFormat numberFormat = super.getFormat(locale); @@ -79,7 +111,7 @@ public class StringToBigDecimalConverter @Override public Result<BigDecimal> convertToModel(String value, ValueContext context) { - return convertToNumber(value, context.getLocale().orElse(null)) + return convertToNumber(value, context) .map(number -> (BigDecimal) number); } diff --git a/server/src/main/java/com/vaadin/data/converter/StringToBigIntegerConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToBigIntegerConverter.java index 840f6ae8c0..0d3642cb94 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToBigIntegerConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToBigIntegerConverter.java @@ -21,6 +21,7 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -67,6 +68,37 @@ public class StringToBigIntegerConverter super(emptyValue, errorMessage); } + /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToBigIntegerConverter( + ErrorMessageProvider errorMessageProvider) { + this(null, errorMessageProvider); + } + + /** + * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToBigIntegerConverter(BigInteger emptyValue, + ErrorMessageProvider errorMessageProvider) { + super(emptyValue, errorMessageProvider); + } + @Override protected NumberFormat getFormat(Locale locale) { NumberFormat numberFormat = super.getFormat(locale); @@ -80,17 +112,16 @@ public class StringToBigIntegerConverter @Override public Result<BigInteger> convertToModel(String value, ValueContext context) { - return convertToNumber(value, context.getLocale().orElse(null)) - .map(number -> { - if (number == null) { - return null; - } - // Empty value will be a BigInteger - if (number instanceof BigInteger) { - return (BigInteger) number; - } - return ((BigDecimal) number).toBigInteger(); - }); + return convertToNumber(value, context).map(number -> { + if (number == null) { + return null; + } + // Empty value will be a BigInteger + if (number instanceof BigInteger) { + return (BigInteger) number; + } + return ((BigDecimal) number).toBigInteger(); + }); } } diff --git a/server/src/main/java/com/vaadin/data/converter/StringToBooleanConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToBooleanConverter.java index 49fa043a86..edb2908afa 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToBooleanConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToBooleanConverter.java @@ -19,13 +19,15 @@ package com.vaadin.data.converter; import java.util.Locale; import com.vaadin.data.Converter; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; /** * A converter that converts from {@link String} to {@link Boolean} and back. * The String representation is given by {@link Boolean#toString()} or provided - * in constructor {@link StringToBooleanConverter#StringToBooleanConverter(String, String, String)}. + * in constructor + * {@link StringToBooleanConverter#StringToBooleanConverter(String, String, String)}. * <p> * Leading and trailing white spaces are ignored when converting from a String. * </p> @@ -43,7 +45,7 @@ public class StringToBooleanConverter implements Converter<String, Boolean> { private final String falseString; - private String errorMessage; + private ErrorMessageProvider errorMessageProvider; /** * Creates converter with default string representations - "true" and @@ -57,6 +59,20 @@ public class StringToBooleanConverter implements Converter<String, Boolean> { } /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToBooleanConverter(ErrorMessageProvider errorMessageProvider) { + this(Boolean.TRUE.toString(), Boolean.FALSE.toString(), + errorMessageProvider); + } + + /** * Creates converter with custom string representation. * * @param errorMessage @@ -68,7 +84,24 @@ public class StringToBooleanConverter implements Converter<String, Boolean> { */ public StringToBooleanConverter(String errorMessage, String trueString, String falseString) { - this.errorMessage = errorMessage; + this(trueString, falseString, ctx -> errorMessage); + } + + /** + * Creates converter with custom string representation. + * + * @param falseString + * string representation for <code>false</code> + * @param trueString + * string representation for <code>true</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToBooleanConverter(String trueString, String falseString, + ErrorMessageProvider errorMessageProvider) { + this.errorMessageProvider = errorMessageProvider; this.trueString = trueString; this.falseString = falseString; } @@ -90,7 +123,7 @@ public class StringToBooleanConverter implements Converter<String, Boolean> { } else if (value.isEmpty()) { return Result.ok(null); } else { - return Result.error(errorMessage); + return Result.error(errorMessageProvider.apply(context)); } } diff --git a/server/src/main/java/com/vaadin/data/converter/StringToDoubleConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToDoubleConverter.java index 627775fbba..b1b11fdd1d 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToDoubleConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToDoubleConverter.java @@ -19,6 +19,7 @@ package com.vaadin.data.converter; import java.text.NumberFormat; import java.util.Locale; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -64,10 +65,39 @@ public class StringToDoubleConverter super(emptyValue, errorMessage); } + /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToDoubleConverter(ErrorMessageProvider errorMessageProvider) { + this(null, errorMessageProvider); + } + + /** + * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToDoubleConverter(Double emptyValue, + ErrorMessageProvider errorMessageProvider) { + super(emptyValue, errorMessageProvider); + } + @Override public Result<Double> convertToModel(String value, ValueContext context) { - Result<Number> n = convertToNumber(value, - context.getLocale().orElse(null)); + Result<Number> n = convertToNumber(value, context); return n.map(number -> { if (number == null) { diff --git a/server/src/main/java/com/vaadin/data/converter/StringToFloatConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToFloatConverter.java index 37e159f844..62c211a2ad 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToFloatConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToFloatConverter.java @@ -19,6 +19,7 @@ package com.vaadin.data.converter; import java.text.NumberFormat; import java.util.Locale; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -62,10 +63,39 @@ public class StringToFloatConverter super(emptyValue, errorMessage); } + /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToFloatConverter(ErrorMessageProvider errorMessageProvider) { + this(null, errorMessageProvider); + } + + /** + * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToFloatConverter(Float emptyValue, + ErrorMessageProvider errorMessageProvider) { + super(emptyValue, errorMessageProvider); + } + @Override public Result<Float> convertToModel(String value, ValueContext context) { - Result<Number> n = convertToNumber(value, - context.getLocale().orElse(null)); + Result<Number> n = convertToNumber(value, context); return n.map(number -> { if (number == null) { diff --git a/server/src/main/java/com/vaadin/data/converter/StringToIntegerConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToIntegerConverter.java index 88f2c29126..b0a9449a56 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToIntegerConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToIntegerConverter.java @@ -19,6 +19,7 @@ package com.vaadin.data.converter; import java.text.NumberFormat; import java.util.Locale; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -62,6 +63,36 @@ public class StringToIntegerConverter } /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToIntegerConverter(ErrorMessageProvider errorMessageProvider) { + this(null, errorMessageProvider); + } + + /** + * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToIntegerConverter(Integer emptyValue, + ErrorMessageProvider errorMessageProvider) { + super(emptyValue, errorMessageProvider); + } + + /** * Returns the format used by * {@link #convertToPresentation(Object, ValueContext)} and * {@link #convertToModel(String, ValueContext)}. @@ -80,8 +111,7 @@ public class StringToIntegerConverter @Override public Result<Integer> convertToModel(String value, ValueContext context) { - Result<Number> n = convertToNumber(value, - context.getLocale().orElse(null)); + Result<Number> n = convertToNumber(value, context); return n.flatMap(number -> { if (number == null) { return Result.ok(null); @@ -94,7 +124,7 @@ public class StringToIntegerConverter // long and thus does not need to consider wrap-around. return Result.ok(intValue); } - return Result.error(getErrorMessage()); + return Result.error(getErrorMessage(context)); }); } diff --git a/server/src/main/java/com/vaadin/data/converter/StringToLongConverter.java b/server/src/main/java/com/vaadin/data/converter/StringToLongConverter.java index 4e65296316..39ef8f777a 100644 --- a/server/src/main/java/com/vaadin/data/converter/StringToLongConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/StringToLongConverter.java @@ -19,6 +19,7 @@ package com.vaadin.data.converter; import java.text.NumberFormat; import java.util.Locale; +import com.vaadin.data.ErrorMessageProvider; import com.vaadin.data.Result; import com.vaadin.data.ValueContext; @@ -62,6 +63,36 @@ public class StringToLongConverter } /** + * Creates a new converter instance with the given error message provider. + * Empty strings are converted to <code>null</code>. + * + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToLongConverter(ErrorMessageProvider errorMessageProvider) { + this(null, errorMessageProvider); + } + + /** + * Creates a new converter instance with the given empty string value and + * error message provider. + * + * @param emptyValue + * the presentation value to return when converting an empty + * string, may be <code>null</code> + * @param errorMessageProvider + * the error message provider to use if conversion fails + * + * @since + */ + public StringToLongConverter(Long emptyValue, + ErrorMessageProvider errorMessageProvider) { + super(emptyValue, errorMessageProvider); + } + + /** * Returns the format used by * {@link #convertToPresentation(Object, ValueContext)} and * {@link #convertToModel(String, ValueContext)}. @@ -80,8 +111,7 @@ public class StringToLongConverter @Override public Result<Long> convertToModel(String value, ValueContext context) { - Result<Number> n = convertToNumber(value, - context.getLocale().orElse(null)); + Result<Number> n = convertToNumber(value, context); return n.map(number -> { if (number == null) { return null; diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index abbbe541ae..ef52ea8ef5 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -1102,4 +1102,27 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> { assertTrue("Binding should be readonly", binding.isReadOnly()); assertTrue("Name field should be readonly", nameField.isReadOnly()); } + + @Test + public void conversionWithLocaleBasedErrorMessage() { + String fiError = "VIRHE"; + String otherError = "ERROR"; + + binder.forField(ageField).withConverter(new StringToIntegerConverter( + context -> context.getLocale().map(Locale::getLanguage) + .orElse("en").equals("fi") ? fiError : otherError)) + .bind(Person::getAge, Person::setAge); + + binder.setBean(item); + + ageField.setValue("not a number"); + + assertEquals(otherError, + ageField.getErrorMessage().getFormattedHtmlMessage()); + ageField.setLocale(new Locale("fi")); + // Re-validate to get the error message with correct locale + binder.validate(); + assertEquals(fiError, + ageField.getErrorMessage().getFormattedHtmlMessage()); + } } |