Skip to content

Commit

Permalink
Allow configuring how string to number converters handle empty strings (
Browse files Browse the repository at this point in the history
  • Loading branch information
Legioth committed Feb 8, 2017
1 parent 32cfd09 commit c973675
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 29 deletions.
Expand Up @@ -36,24 +36,32 @@
* @author Vaadin Ltd
* @since 8.0
*/
public abstract class AbstractStringToNumberConverter<T>
public abstract class AbstractStringToNumberConverter<T extends Number>
implements Converter<String, T> {

private final String errorMessage;
private T emptyValue;

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
protected AbstractStringToNumberConverter(String errorMessage) {
protected AbstractStringToNumberConverter(T emptyValue,
String errorMessage) {
this.emptyValue = emptyValue;
this.errorMessage = errorMessage;
}

/**
* Returns the format used by {@link #convertToPresentation(Object, ValueContext)}
* and {@link #convertToModel(Object, ValueContext)}.
* Returns the format used by
* {@link #convertToPresentation(Object, ValueContext)} and
* {@link #convertToModel(Object, ValueContext)}.
*
* @param locale
* The locale to use
Expand Down Expand Up @@ -94,8 +102,8 @@ protected Result<Number> convertToNumber(String value, Locale locale) {
}

if (parsedValue == null) {
// Convert "" to null
return Result.ok(null);
// Convert "" to the empty value
return Result.ok(emptyValue);
}

return Result.ok(parsedValue);
Expand Down
Expand Up @@ -41,13 +41,29 @@ public class StringToBigDecimalConverter
extends AbstractStringToNumberConverter<BigDecimal> {

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given error message. Empty
* strings are converted to <code>null</code>.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToBigDecimalConverter(String errorMessage) {
super(errorMessage);
this(null, errorMessage);
}

/**
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToBigDecimalConverter(BigDecimal emptyValue,
String errorMessage) {
super(emptyValue, errorMessage);
}

@Override
Expand Down
Expand Up @@ -40,14 +40,31 @@
*/
public class StringToBigIntegerConverter
extends AbstractStringToNumberConverter<BigInteger> {

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given error message. Empty
* strings are converted to <code>null</code>.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToBigIntegerConverter(String errorMessage) {
super(errorMessage);
this(null, errorMessage);
}

/**
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToBigIntegerConverter(BigInteger emptyValue,
String errorMessage) {
super(emptyValue, errorMessage);
}

@Override
Expand All @@ -68,6 +85,10 @@ public Result<BigInteger> convertToModel(String value,
if (number == null) {
return null;
} else {
// Empty value will be a BigInteger
if (number instanceof BigInteger) {
return (BigInteger) number;
}
return ((BigDecimal) number).toBigInteger();
}
});
Expand Down
Expand Up @@ -40,13 +40,28 @@ public class StringToDoubleConverter
extends AbstractStringToNumberConverter<Double> {

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given error message. Empty
* strings are converted to <code>null</code>.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToDoubleConverter(String errorMessage) {
super(errorMessage);
this(null, errorMessage);
}

/**
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToDoubleConverter(Double emptyValue, String errorMessage) {
super(emptyValue, errorMessage);
}

@Override
Expand Down
Expand Up @@ -38,13 +38,28 @@ public class StringToFloatConverter
extends AbstractStringToNumberConverter<Float> {

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given error message. Empty
* strings are converted to <code>null</code>.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToFloatConverter(String errorMessage) {
super(errorMessage);
this(null, errorMessage);
}

/**
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToFloatConverter(Float emptyValue, String errorMessage) {
super(emptyValue, errorMessage);
}

@Override
Expand Down
Expand Up @@ -37,18 +37,33 @@ public class StringToIntegerConverter
extends AbstractStringToNumberConverter<Integer> {

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given error message. Empty
* strings are converted to <code>null</code>.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToIntegerConverter(String errorMessage) {
super(errorMessage);
this(null, errorMessage);
}

/**
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToIntegerConverter(Integer emptyValue, String errorMessage) {
super(emptyValue, errorMessage);
}

/**
* Returns the format used by
* {@link #convertToPresentation(Object, ValueContext)} and
* {@link #convertToPresentation(Object, ValueContext)} and
* {@link #convertToModel(String, ValueContext)}.
*
* @param locale
Expand Down
Expand Up @@ -37,18 +37,34 @@ public class StringToLongConverter
extends AbstractStringToNumberConverter<Long> {

/**
* Creates a new converter instance with the given error message.
* Creates a new converter instance with the given error message. Empty
* strings are converted to <code>null</code>.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToLongConverter(String errorMessage) {
super(errorMessage);
this(null, errorMessage);
}

/**
* Returns the format used by {@link #convertToPresentation(Object, ValueContext)}
* and {@link #convertToModel(String, ValueContext)}.
* Creates a new converter instance with the given empty string value and
* error message.
*
* @param emptyValue
* the presentation value to return when converting an empty
* string, may be <code>null</code>
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToLongConverter(Long emptyValue, String errorMessage) {
super(emptyValue, errorMessage);
}

/**
* Returns the format used by
* {@link #convertToPresentation(Object, ValueContext)} and
* {@link #convertToModel(String, ValueContext)}.
*
* @param locale
* The locale to use
Expand Down
Expand Up @@ -17,22 +17,23 @@ public void testNullConversion() {

protected abstract Converter<?, ?> getConverter();

protected void assertValue(Object object, Result<?> result) {
assertValue(null, object, result);
protected <T> void assertValue(T expectedValue, Result<?> result) {
assertValue(null, expectedValue, result);
}

protected void assertValue(String error, Object object, Result<?> result) {
protected <T> void assertValue(String assertMessage, T expectedValue,
Result<?> result) {
Assert.assertNotNull("Result should never be null", result);
Assert.assertFalse("Result is not ok", result.isError());
Assert.assertEquals(object,
Assert.assertEquals(expectedValue,
result.getOrThrow(message -> new AssertionError(
error != null ? error : message)));
assertMessage != null ? assertMessage : message)));
}

protected void assertError(String expected, Result<?> result) {
protected void assertError(String expectedResultMessage, Result<?> result) {
Assert.assertNotNull("Result should never be null", result);
Assert.assertTrue("Result should be an error", result.isError());
Assert.assertEquals(expected, result.getMessage().get());
Assert.assertEquals(expectedResultMessage, result.getMessage().get());
}

protected String getErrorMessage() {
Expand Down
Expand Up @@ -50,4 +50,15 @@ public void testValueFormatting() {
new ValueContext(Locale.GERMAN));
Assert.assertEquals(expected, converted);
}

@Test
public void customEmptyValue() {
StringToBigDecimalConverter converter = new StringToBigDecimalConverter(
BigDecimal.ZERO, getErrorMessage());

assertValue(BigDecimal.ZERO,
converter.convertToModel("", new ValueContext()));
Assert.assertEquals("0", converter
.convertToPresentation(BigDecimal.ZERO, new ValueContext()));
}
}
Expand Up @@ -54,4 +54,16 @@ public void testValueFormatting() {
"Value with specific locale was converted incorrectly",
expected, converted);
}

@Test
public void customEmptyValue() {
StringToBigIntegerConverter converter = new StringToBigIntegerConverter(
BigInteger.ZERO, getErrorMessage());

assertValue(BigInteger.ZERO,
converter.convertToModel("", new ValueContext()));
Assert.assertEquals("0", converter
.convertToPresentation(BigInteger.ZERO, new ValueContext()));
}

}
Expand Up @@ -35,4 +35,14 @@ public void testErrorMessage() {
Assert.assertEquals("Failed", result.getMessage().get());
}

@Test
public void customEmptyValue() {
StringToDoubleConverter converter = new StringToDoubleConverter(0.0,
getErrorMessage());

assertValue(0.0, converter.convertToModel("", new ValueContext()));
Assert.assertEquals("0",
converter.convertToPresentation(0.0, new ValueContext()));
}

}
@@ -1,5 +1,6 @@
package com.vaadin.tests.data.converter;

import org.junit.Assert;
import org.junit.Test;

import com.vaadin.data.ValueContext;
Expand Down Expand Up @@ -31,4 +32,15 @@ public void testValueConversion() {
assertValue(Float.valueOf(10),
getConverter().convertToModel("10", new ValueContext()));
}

@Test
public void customEmptyValue() {
StringToFloatConverter converter = new StringToFloatConverter(
(float) 0.0, getErrorMessage());

assertValue((float) 0.0,
converter.convertToModel("", new ValueContext()));
Assert.assertEquals("0", converter.convertToPresentation((float) 0.0,
new ValueContext()));
}
}
Expand Up @@ -51,4 +51,14 @@ public void testErrorMessage() {
Assert.assertTrue(result.isError());
Assert.assertEquals("Failed", result.getMessage().get());
}

@Test
public void customEmptyValue() {
StringToIntegerConverter converter = new StringToIntegerConverter(0,
getErrorMessage());

assertValue(0, converter.convertToModel("", new ValueContext()));
Assert.assertEquals("0",
converter.convertToPresentation(0, new ValueContext()));
}
}

0 comments on commit c973675

Please sign in to comment.