From 51afa631835ac603da7bce234aeff0b0154e6296 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 17 May 2017 07:18:22 +0200 Subject: [PATCH] Supports string to float conversion based on locale --- .../conversion/impl/NumberConverter.java | 71 +++++++++++++------ .../conversion/impl/NumberConverterTest.java | 26 +++++++ 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java index 6e7d23114..1fa2512fe 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java @@ -19,21 +19,24 @@ public class NumberConverter extends DefaultTypeConverter { public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { if (value instanceof String) { + String stringValue = String.valueOf(value); + if (toType == BigDecimal.class) { - return convertToBigDecimal(context, value); + return convertToBigDecimal(context, stringValue); } else if (toType == BigInteger.class) { - return new BigInteger((String) value); + return new BigInteger(stringValue); } else if (toType == Double.class || toType == double.class) { - return convertToDouble(context, value); + return convertToDouble(context, stringValue); + } else if (toType == Float.class || toType == float.class) { + return convertToFloat(context, stringValue); } else if (toType.isPrimitive()) { Object convertedValue = super.convertValue(context, value, toType); - String stringValue = (String) value; + if (!isInRange((Number) convertedValue, stringValue, toType)) throw new XWorkException("Overflow or underflow casting: \"" + stringValue + "\" into class " + convertedValue.getClass().getName()); return convertedValue; } else { - String stringValue = (String) value; if (!toType.isPrimitive() && stringValue.isEmpty()) { return null; } @@ -67,48 +70,46 @@ public class NumberConverter extends DefaultTypeConverter { return super.convertValue(context, value, toType); } - protected Object convertToBigDecimal(Map context, Object value) { + protected Object convertToBigDecimal(Map context, String stringValue) { Locale locale = getLocale(context); - String strValue = String.valueOf(value); NumberFormat format = getNumberFormat(locale); if (format instanceof DecimalFormat) { ((DecimalFormat) format).setParseBigDecimal(true); char separator = ((DecimalFormat) format).getDecimalFormatSymbols().getGroupingSeparator(); - strValue = normalize(strValue, separator); + stringValue = normalize(stringValue, separator); } - LOG.debug("Trying to convert a value {} with locale {} to BigDecimal", strValue, locale); + LOG.debug("Trying to convert a value {} with locale {} to BigDecimal", stringValue, locale); ParsePosition parsePosition = new ParsePosition(0); - Number number = format.parse(strValue, parsePosition); + Number number = format.parse(stringValue, parsePosition); - if (parsePosition.getIndex() != strValue.length()) { - throw new XWorkException("Unparseable number: \"" + strValue + "\" at position " + parsePosition.getIndex()); + if (parsePosition.getIndex() != stringValue.length()) { + throw new XWorkException("Unparseable number: \"" + stringValue + "\" at position " + parsePosition.getIndex()); } return number; } - protected Object convertToDouble(Map context, Object value) { + protected Object convertToDouble(Map context, String stringValue) { Locale locale = getLocale(context); - String strValue = String.valueOf(value); NumberFormat format = getNumberFormat(locale); if (format instanceof DecimalFormat) { char separator = ((DecimalFormat) format).getDecimalFormatSymbols().getGroupingSeparator(); - strValue = normalize(strValue, separator); + stringValue = normalize(stringValue, separator); } - LOG.debug("Trying to convert a value {} with locale {} to Double", strValue, locale); + LOG.debug("Trying to convert a value {} with locale {} to Double", stringValue, locale); ParsePosition parsePosition = new ParsePosition(0); - Number number = format.parse(strValue, parsePosition); + Number number = format.parse(stringValue, parsePosition); - if (parsePosition.getIndex() != strValue.length()) { - throw new XWorkException("Unparseable number: \"" + strValue + "\" at position " + parsePosition.getIndex()); + if (parsePosition.getIndex() != stringValue.length()) { + throw new XWorkException("Unparseable number: \"" + stringValue + "\" at position " + parsePosition.getIndex()); } - if (!isInRange(number, strValue, Double.class)) { - throw new XWorkException("Overflow or underflow converting: \"" + strValue + "\" into class " + number.getClass().getName()); + if (!isInRange(number, stringValue, Double.class)) { + throw new XWorkException("Overflow or underflow converting: \"" + stringValue + "\" into class " + number.getClass().getName()); } if (number != null) { @@ -118,6 +119,34 @@ public class NumberConverter extends DefaultTypeConverter { return null; } + protected Object convertToFloat(Map context, String stringValue) { + Locale locale = getLocale(context); + + NumberFormat format = getNumberFormat(locale); + if (format instanceof DecimalFormat) { + char separator = ((DecimalFormat) format).getDecimalFormatSymbols().getGroupingSeparator(); + stringValue = normalize(stringValue, separator); + } + + LOG.debug("Trying to convert a value {} with locale {} to Float", stringValue, locale); + ParsePosition parsePosition = new ParsePosition(0); + Number number = format.parse(stringValue, parsePosition); + + if (parsePosition.getIndex() != stringValue.length()) { + throw new XWorkException("Unparseable number: \"" + stringValue + "\" at position " + parsePosition.getIndex()); + } + + if (!isInRange(number, stringValue, Float.class)) { + throw new XWorkException("Overflow or underflow converting: \"" + stringValue + "\" into class " + number.getClass().getName()); + } + + if (number != null) { + return number.floatValue(); + } + + return null; + } + protected NumberFormat getNumberFormat(Locale locale) { NumberFormat format = NumberFormat.getNumberInstance(locale); format.setGroupingUsed(true); diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java index 8143b00db..4ffa684ac 100644 --- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java @@ -107,5 +107,31 @@ public class NumberConverterTest extends XWorkTestCase { assertEquals(1234.4, value); } + public void testStringToFloatConversionPL() throws Exception { + // given + NumberConverter converter = new NumberConverter(); + Map context = new HashMap<>(); + context.put(ActionContext.LOCALE, new Locale("pl", "PL")); + + // when + Object value = converter.convertValue(context, null, null, null, "1234,4567", Float.class); + + // then + assertEquals(1234.4567F, value); + } + + public void testStringToFloatConversionWithDotsPL() throws Exception { + // given + NumberConverter converter = new NumberConverter(); + Map context = new HashMap<>(); + context.put(ActionContext.LOCALE, new Locale("pl", "PL")); + + // when + Object value = converter.convertValue(context, null, null, null, "1 234,4", Float.class); + + // then + assertEquals(1234.4F, value); + } + }