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);
+    }
+
 }

Reply via email to