Skip to content

Commit

Permalink
Add error message constructor to all converters which can fail
Browse files Browse the repository at this point in the history
Change-Id: I3ec60effc75e22765d21e0223ee1537ffbdb29e7
  • Loading branch information
Artur- committed Sep 5, 2016
1 parent ccaabe6 commit 6941d68
Show file tree
Hide file tree
Showing 22 changed files with 309 additions and 114 deletions.
Expand Up @@ -20,6 +20,8 @@
import java.text.ParsePosition; import java.text.ParsePosition;
import java.util.Locale; import java.util.Locale;


import com.vaadin.data.Result;

/** /**
* A converter that converts from the number type T to {@link String} and back. * A converter that converts from the number type T to {@link String} and back.
* Uses the given locale and {@link NumberFormat} for formatting and parsing. * Uses the given locale and {@link NumberFormat} for formatting and parsing.
Expand All @@ -35,6 +37,18 @@
public abstract class AbstractStringToNumberConverter<T> public abstract class AbstractStringToNumberConverter<T>
implements Converter<String, T> { implements Converter<String, T> {


private final String errorMessage;

/**
* Creates a new converter instance with the given error message.
*
* @param errorMessage
* the error message to use if conversion fails
*/
protected AbstractStringToNumberConverter(String errorMessage) {
this.errorMessage = errorMessage;
}

/** /**
* Returns the format used by {@link #convertToPresentation(Object, Locale)} * Returns the format used by {@link #convertToPresentation(Object, Locale)}
* and {@link #convertToModel(Object, Locale)}. * and {@link #convertToModel(Object, Locale)}.
Expand All @@ -61,9 +75,9 @@ protected NumberFormat getFormat(Locale locale) {
* The locale to use for conversion * The locale to use for conversion
* @return The converted value * @return The converted value
*/ */
protected Number convertToNumber(String value, Locale locale) { protected Result<Number> convertToNumber(String value, Locale locale) {
if (value == null) { if (value == null) {
return null; return Result.ok(null);
} }


// Remove leading and trailing white space // Remove leading and trailing white space
Expand All @@ -74,16 +88,24 @@ protected Number convertToNumber(String value, Locale locale) {
ParsePosition parsePosition = new ParsePosition(0); ParsePosition parsePosition = new ParsePosition(0);
Number parsedValue = getFormat(locale).parse(value, parsePosition); Number parsedValue = getFormat(locale).parse(value, parsePosition);
if (parsePosition.getIndex() != value.length()) { if (parsePosition.getIndex() != value.length()) {
throw new IllegalArgumentException( return Result.error(getErrorMessage());
"Could not convert '" + value + "'");
} }


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


return parsedValue; return Result.ok(parsedValue);
}

/**
* Gets the error message to use when conversion fails.
*
* @return the error message
*/
protected String getErrorMessage() {
return errorMessage;
} }


@Override @Override
Expand Down
Expand Up @@ -38,6 +38,17 @@
*/ */
public class StringToBigDecimalConverter public class StringToBigDecimalConverter
extends AbstractStringToNumberConverter<BigDecimal> { extends AbstractStringToNumberConverter<BigDecimal> {

/**
* Creates a new converter instance with the given error message.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToBigDecimalConverter(String errorMessage) {
super(errorMessage);
}

@Override @Override
protected NumberFormat getFormat(Locale locale) { protected NumberFormat getFormat(Locale locale) {
NumberFormat numberFormat = super.getFormat(locale); NumberFormat numberFormat = super.getFormat(locale);
Expand All @@ -50,7 +61,8 @@ protected NumberFormat getFormat(Locale locale) {


@Override @Override
public Result<BigDecimal> convertToModel(String value, Locale locale) { public Result<BigDecimal> convertToModel(String value, Locale locale) {
return Result.ok((BigDecimal) convertToNumber(value, locale)); return convertToNumber(value, locale)
.map(number -> (BigDecimal) number);
} }


} }
Expand Up @@ -39,6 +39,15 @@
*/ */
public class StringToBigIntegerConverter public class StringToBigIntegerConverter
extends AbstractStringToNumberConverter<BigInteger> { extends AbstractStringToNumberConverter<BigInteger> {
/**
* Creates a new converter instance with the given error message.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToBigIntegerConverter(String errorMessage) {
super(errorMessage);
}


@Override @Override
protected NumberFormat getFormat(Locale locale) { protected NumberFormat getFormat(Locale locale) {
Expand All @@ -52,12 +61,13 @@ protected NumberFormat getFormat(Locale locale) {


@Override @Override
public Result<BigInteger> convertToModel(String value, Locale locale) { public Result<BigInteger> convertToModel(String value, Locale locale) {

return convertToNumber(value, locale).map(number -> {
BigDecimal bigDecimalValue = (BigDecimal) convertToNumber(value, if (number == null) {
locale); return null;

} else {
return (bigDecimalValue != null) return ((BigDecimal) number).toBigInteger();
? Result.ok(bigDecimalValue.toBigInteger()) : Result.ok(null); }
});
} }


} }
Expand Up @@ -41,31 +41,39 @@ public class StringToBooleanConverter implements Converter<String, Boolean> {


private final String falseString; private final String falseString;


private String errorMessage;

/** /**
* Creates converter with default string representations - "true" and * Creates converter with default string representations - "true" and
* "false". * "false".
* *
* @param errorMessage
* the error message to use if conversion fails
*/ */
public StringToBooleanConverter() { public StringToBooleanConverter(String errorMessage) {
this(Boolean.TRUE.toString(), Boolean.FALSE.toString()); this(errorMessage, Boolean.TRUE.toString(), Boolean.FALSE.toString());
} }


/** /**
* Creates converter with custom string representation. * Creates converter with custom string representation.
* *
* @param errorMessage
* the error message to use if conversion fails
* @param falseString * @param falseString
* string representation for <code>false</code> * string representation for <code>false</code>
* @param trueString * @param trueString
* string representation for <code>true</code> * string representation for <code>true</code>
*/ */
public StringToBooleanConverter(String trueString, String falseString) { public StringToBooleanConverter(String errorMessage, String trueString,
String falseString) {
this.errorMessage = errorMessage;
this.trueString = trueString; this.trueString = trueString;
this.falseString = falseString; this.falseString = falseString;
} }


@Override @Override
public Result<Boolean> convertToModel(String value, Locale locale) { public Result<Boolean> convertToModel(String value, Locale locale) {
if (value == null || value.isEmpty()) { if (value == null) {
return Result.ok(null); return Result.ok(null);
} }


Expand All @@ -76,8 +84,10 @@ public Result<Boolean> convertToModel(String value, Locale locale) {
return Result.ok(true); return Result.ok(true);
} else if (getFalseString(locale).equals(value)) { } else if (getFalseString(locale).equals(value)) {
return Result.ok(false); return Result.ok(false);
} else if (value.isEmpty()) {
return Result.ok(null);
} else { } else {
throw new IllegalArgumentException("Cannot convert " + value); return Result.error(errorMessage);
} }
} }


Expand Down
Expand Up @@ -38,10 +38,27 @@
public class StringToDoubleConverter public class StringToDoubleConverter
extends AbstractStringToNumberConverter<Double> { extends AbstractStringToNumberConverter<Double> {


/**
* Creates a new converter instance with the given error message.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToDoubleConverter(String errorMessage) {
super(errorMessage);
}

@Override @Override
public Result<Double> convertToModel(String value, Locale locale) { public Result<Double> convertToModel(String value, Locale locale) {
Number n = convertToNumber(value, locale); Result<Number> n = convertToNumber(value, locale);
return n == null ? Result.ok(null) : Result.ok(n.doubleValue());
return n.map(number -> {
if (number == null) {
return null;
} else {
return number.doubleValue();
}
});
} }


} }
Expand Up @@ -27,21 +27,36 @@
* parsing. * parsing.
* <p> * <p>
* Leading and trailing white spaces are ignored when converting from a String. * Leading and trailing white spaces are ignored when converting from a String.
* </p>
* <p> * <p>
* Override and overwrite {@link #getFormat(Locale)} to use a different format. * Override and overwrite {@link #getFormat(Locale)} to use a different format.
* </p>
* *
* @author Vaadin Ltd * @author Vaadin Ltd
* @since 8.0 * @since 8.0
*/ */
public class StringToFloatConverter public class StringToFloatConverter
extends AbstractStringToNumberConverter<Float> { extends AbstractStringToNumberConverter<Float> {


/**
* Creates a new converter instance with the given error message.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToFloatConverter(String errorMessage) {
super(errorMessage);
}

@Override @Override
public Result<Float> convertToModel(String value, Locale locale) { public Result<Float> convertToModel(String value, Locale locale) {
Number n = convertToNumber(value, locale); Result<Number> n = convertToNumber(value, locale);
return n == null ? Result.ok(null) : Result.ok(n.floatValue());
return n.map(number -> {
if (number == null) {
return null;
} else {
return number.floatValue();
}
});
} }


} }
Expand Up @@ -35,16 +35,14 @@
public class StringToIntegerConverter public class StringToIntegerConverter
extends AbstractStringToNumberConverter<Integer> { extends AbstractStringToNumberConverter<Integer> {


private final String errorMessage;

/** /**
* Creates a new converter instance with the given error message. * Creates a new converter instance with the given error message.
* *
* @param errorMessage * @param errorMessage
* the error message to use if conversion fails * the error message to use if conversion fails
*/ */
public StringToIntegerConverter(String errorMessage) { public StringToIntegerConverter(String errorMessage) {
this.errorMessage = errorMessage; super(errorMessage);
} }


/** /**
Expand All @@ -66,22 +64,23 @@ protected NumberFormat getFormat(Locale locale) {


@Override @Override
public Result<Integer> convertToModel(String value, Locale locale) { public Result<Integer> convertToModel(String value, Locale locale) {
Number n = convertToNumber(value, locale); Result<Number> n = convertToNumber(value, locale);

return n.flatMap(number -> {
if (n == null) { if (number == null) {
return Result.ok(null); return Result.ok(null);
} } else {

int intValue = number.intValue();
int intValue = n.intValue(); if (intValue == number.longValue()) {
if (intValue == n.longValue()) { // If the value of n is outside the range of long, the
// If the value of n is outside the range of long, the return value // return value of longValue() is either Long.MIN_VALUE or
// of longValue() is either Long.MIN_VALUE or Long.MAX_VALUE. The // Long.MAX_VALUE. The/ above comparison promotes int to
// above comparison promotes int to long and thus does not need to // long and thus does not need to consider wrap-around.
// consider wrap-around. return Result.ok(intValue);
return Result.ok(intValue); } else {
} else { return Result.error(getErrorMessage());
return Result.error(errorMessage); }
} }
});
} }


} }
Expand Up @@ -35,6 +35,16 @@
public class StringToLongConverter public class StringToLongConverter
extends AbstractStringToNumberConverter<Long> { extends AbstractStringToNumberConverter<Long> {


/**
* Creates a new converter instance with the given error message.
*
* @param errorMessage
* the error message to use if conversion fails
*/
public StringToLongConverter(String errorMessage) {
super(errorMessage);
}

/** /**
* Returns the format used by {@link #convertToPresentation(Long, Locale)} * Returns the format used by {@link #convertToPresentation(Long, Locale)}
* and {@link #convertToModel(String, Locale)}. * and {@link #convertToModel(String, Locale)}.
Expand All @@ -53,9 +63,14 @@ protected NumberFormat getFormat(Locale locale) {


@Override @Override
public Result<Long> convertToModel(String value, Locale locale) { public Result<Long> convertToModel(String value, Locale locale) {
Number n = convertToNumber(value, locale); Result<Number> n = convertToNumber(value, locale);
return n == null ? Result.ok(null) : Result.ok(n.longValue()); return n.map(number -> {

if (number == null) {
return null;
} else {
return number.longValue();
}
});
} }


} }
Expand Up @@ -109,7 +109,8 @@ public String convertToPresentation(Boolean value, Locale locale) {
final DecimalFormat fmt = new DecimalFormat("0.###", symbols); final DecimalFormat fmt = new DecimalFormat("0.###", symbols);
fmt.setGroupingUsed(false); fmt.setGroupingUsed(false);


Converter<String, ?> floatConverter = new StringToFloatConverter() { Converter<String, ?> floatConverter = new StringToFloatConverter(
"Error converting value") {
@Override @Override
protected NumberFormat getFormat(Locale locale) { protected NumberFormat getFormat(Locale locale) {
return fmt; return fmt;
Expand All @@ -118,7 +119,8 @@ protected NumberFormat getFormat(Locale locale) {
converterMap.put(Float.class, floatConverter); converterMap.put(Float.class, floatConverter);
converterMap.put(float.class, floatConverter); converterMap.put(float.class, floatConverter);


Converter<String, ?> doubleConverter = new StringToDoubleConverter() { Converter<String, ?> doubleConverter = new StringToDoubleConverter(
"Error converting value") {
@Override @Override
protected NumberFormat getFormat(Locale locale) { protected NumberFormat getFormat(Locale locale) {
return fmt; return fmt;
Expand All @@ -130,12 +132,13 @@ protected NumberFormat getFormat(Locale locale) {
final DecimalFormat bigDecimalFmt = new DecimalFormat("0.###", symbols); final DecimalFormat bigDecimalFmt = new DecimalFormat("0.###", symbols);
bigDecimalFmt.setGroupingUsed(false); bigDecimalFmt.setGroupingUsed(false);
bigDecimalFmt.setParseBigDecimal(true); bigDecimalFmt.setParseBigDecimal(true);
converterMap.put(BigDecimal.class, new StringToBigDecimalConverter() { converterMap.put(BigDecimal.class,
@Override new StringToBigDecimalConverter("Error converting value") {
protected NumberFormat getFormat(Locale locale) { @Override
return bigDecimalFmt; protected NumberFormat getFormat(Locale locale) {
}; return bigDecimalFmt;
}); };
});


// strings do nothing // strings do nothing
converterMap.put(String.class, new Converter<String, String>() { converterMap.put(String.class, new Converter<String, String>() {
Expand Down

0 comments on commit 6941d68

Please sign in to comment.