Repository: struts Updated Branches: refs/heads/master 3a9f86a60 -> 2fb431d97
WW-4581 Uses proper logic to convert String to BigDecimal Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/f874f9cd Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/f874f9cd Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/f874f9cd Branch: refs/heads/master Commit: f874f9cde56f74c5161b17e645f779805c51a04b Parents: 5a6c336 Author: Lukasz Lenart <lukaszlen...@apache.org> Authored: Fri May 12 12:19:48 2017 +0200 Committer: Lukasz Lenart <lukaszlen...@apache.org> Committed: Fri May 12 12:19:48 2017 +0200 ---------------------------------------------------------------------- .../xwork2/conversion/impl/NumberConverter.java | 40 ++++++++++++++++++- .../conversion/impl/NumberConverterTest.java | 42 ++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/f874f9cd/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java ---------------------------------------------------------------------- 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 ab6efc0..16bbd49 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 @@ -1,20 +1,31 @@ package com.opensymphony.xwork2.conversion.impl; import com.opensymphony.xwork2.XWorkException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.message.ParameterizedMessage; import java.lang.reflect.Member; import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.text.NumberFormat; +import java.text.ParseException; import java.text.ParsePosition; +import java.util.Formatter; +import java.util.Locale; import java.util.Map; public class NumberConverter extends DefaultTypeConverter { + private static final Logger LOG = LogManager.getLogger(NumberConverter.class); + public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) { if (value instanceof String) { if (toType == BigDecimal.class) { - return new BigDecimal((String) value); + return convertToBigDecimal(context, value); } else if (toType == BigInteger.class) { return new BigInteger((String) value); } else if (toType.isPrimitive()) { @@ -59,6 +70,33 @@ public class NumberConverter extends DefaultTypeConverter { return super.convertValue(context, value, toType); } + protected Object convertToBigDecimal(Map<String, Object> context, Object value) { + Locale locale = getLocale(context); + String strValue = String.valueOf(value); + + NumberFormat format = NumberFormat.getNumberInstance(locale); + format.setGroupingUsed(true); + if (format instanceof DecimalFormat) { + ((DecimalFormat) format).setParseBigDecimal(true); + char separator = ((DecimalFormat) format).getDecimalFormatSymbols().getGroupingSeparator(); + + // this is a hack as \160 isn't the same as " " (an empty space) + if (separator == 160) { + strValue = strValue.replaceAll(" ", ""); + } else { + strValue = strValue.replaceAll(String.valueOf(separator), ""); + } + } + + try { + LOG.info("Trying parse value {} with locale {}", strValue, locale); + return format.parse(strValue); + } catch (ParseException e) { + LOG.warn(new ParameterizedMessage("Cannot convert value {} to BigDecimal, trying with default converter", value, e)); + return super.convertValue(context, value, BigDecimal.class); + } + } + protected boolean isInRange(Number value, String stringValue, Class toType) { Number bigValue = null; Number lowerBound = null; http://git-wip-us.apache.org/repos/asf/struts/blob/f874f9cd/core/src/test/java/com/opensymphony/xwork2/conversion/impl/NumberConverterTest.java ---------------------------------------------------------------------- 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 76be6e1..ca87aae 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 @@ -4,6 +4,8 @@ import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.SimpleFooAction; import com.opensymphony.xwork2.XWorkTestCase; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -39,4 +41,44 @@ public class NumberConverterTest extends XWorkTestCase { // then assertEquals(1234, value); } + + public void testStringToBigDecimalConversionPL() throws Exception { + // given + NumberConverter converter = new NumberConverter(); + Map<String, Object> context = new HashMap<>(); + context.put(ActionContext.LOCALE, new Locale("pl", "PL")); + + // when + Object value = converter.convertValue(context, null, null, null, "1234,4567", BigDecimal.class); + + // then + assertEquals(BigDecimal.valueOf(1234.4567), value); + } + + public void testStringToBigDecimalConversionWithDotsPL() throws Exception { + // given + NumberConverter converter = new NumberConverter(); + Map<String, Object> context = new HashMap<>(); + context.put(ActionContext.LOCALE, new Locale("pl", "PL")); + + // when + Object value = converter.convertValue(context, null, null, null, "1 234,4", BigDecimal.class); + + // then + assertEquals(BigDecimal.valueOf(1234.4), value); + } + + public void testStringToBigDecimalConversionWithCommasEN() throws Exception { + // given + NumberConverter converter = new NumberConverter(); + Map<String, Object> context = new HashMap<>(); + context.put(ActionContext.LOCALE, new Locale("en", "US")); + + // when + Object value = converter.convertValue(context, null, null, null, "100,234.4", BigDecimal.class); + + // then + assertEquals(BigDecimal.valueOf(100234.4), value); + } + }