You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2017/05/18 13:29:44 UTC

[2/7] struts git commit: WW-3650 Supports double conversion for different locale

WW-3650 Supports double conversion for different locale


Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/266d78d3
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/266d78d3
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/266d78d3

Branch: refs/heads/master
Commit: 266d78d32c786276f37ae701267f6719ea9f8a75
Parents: f874f9c
Author: Lukasz Lenart <lu...@apache.org>
Authored: Fri May 12 13:48:14 2017 +0200
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Fri May 12 13:48:14 2017 +0200

----------------------------------------------------------------------
 .../xwork2/conversion/impl/NumberConverter.java | 69 ++++++++++++++++----
 .../conversion/impl/NumberConverterTest.java    | 27 ++++++++
 .../conversion/impl/XWorkConverterTest.java     | 24 +++----
 3 files changed, 94 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/266d78d3/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 16bbd49..c4a2a1d 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,6 +1,7 @@
 package com.opensymphony.xwork2.conversion.impl;
 
 import com.opensymphony.xwork2.XWorkException;
+import com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.message.ParameterizedMessage;
@@ -28,6 +29,8 @@ public class NumberConverter extends DefaultTypeConverter {
                 return convertToBigDecimal(context, value);
             } else if (toType == BigInteger.class) {
                 return new BigInteger((String) value);
+            } else if (toType == Double.class || toType == double.class) {
+                return convertToDouble(context, value);
             } else if (toType.isPrimitive()) {
                 Object convertedValue = super.convertValue(context, value, toType);
                 String stringValue = (String) value;
@@ -74,27 +77,65 @@ public class NumberConverter extends DefaultTypeConverter {
         Locale locale = getLocale(context);
         String strValue = String.valueOf(value);
 
-        NumberFormat format = NumberFormat.getNumberInstance(locale);
-        format.setGroupingUsed(true);
+        NumberFormat format = getNumberFormat(locale);
         if (format instanceof DecimalFormat) {
             ((DecimalFormat) format).setParseBigDecimal(true);
             char separator = ((DecimalFormat) format).getDecimalFormatSymbols().getGroupingSeparator();
+            strValue = normalize(strValue, separator);
+        }
 
-            // 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), "");
-            }
+        LOG.debug("Trying to convert a value {} with locale {} to BigDecimal", strValue, locale);
+        ParsePosition parsePosition = new ParsePosition(0);
+        Number number = format.parse(strValue, parsePosition);
+
+        if (parsePosition.getIndex() != strValue.length()) {
+            throw new XWorkException("Unparseable number: \"" + strValue + "\" at position " + parsePosition.getIndex());
         }
 
-        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);
+        return number;
+    }
+
+    protected Object convertToDouble(Map<String, Object> context, Object value) {
+        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);
+        }
+
+        LOG.debug("Trying to convert a value {} with locale {} to Double", strValue, locale);
+        ParsePosition parsePosition = new ParsePosition(0);
+        Number number = format.parse(strValue, parsePosition);
+
+        if (parsePosition.getIndex() != strValue.length()) {
+            throw new XWorkException("Unparseable number: \"" + strValue + "\" at position " + parsePosition.getIndex());
+        }
+
+        if (!isInRange(number, strValue, Double.class)) {
+            throw new XWorkException("Overflow or underflow converting: \"" + strValue + "\" into class " + number.getClass().getName());
+        }
+
+        if (number != null) {
+            return number.doubleValue();
+        }
+
+        return null;
+    }
+
+    protected NumberFormat getNumberFormat(Locale locale) {
+        NumberFormat format = NumberFormat.getNumberInstance(locale);
+        format.setGroupingUsed(true);
+        return format;
+    }
+
+    protected String normalize(String strValue, char separator) {
+        // this is a hack as \160 isn't the same as " " (an empty space)
+        if (separator == 160) {
+            strValue = strValue.replaceAll(" ", String.valueOf(separator));
         }
+        return strValue;
     }
 
     protected boolean isInRange(Number value, String stringValue, Class toType) {

http://git-wip-us.apache.org/repos/asf/struts/blob/266d78d3/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 ca87aae..8143b00 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
@@ -81,4 +81,31 @@ public class NumberConverterTest extends XWorkTestCase {
         assertEquals(BigDecimal.valueOf(100234.4), value);
     }
 
+    public void testStringToDoubleConversionPL() 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", Double.class);
+
+        // then
+        assertEquals(1234.4567, value);
+    }
+
+    public void testStringToDoubleConversionWithDotsPL() 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", Double.class);
+
+        // then
+        assertEquals(1234.4, value);
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/struts/blob/266d78d3/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
index be96416..4607805 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
@@ -519,30 +519,30 @@ public class XWorkConverterTest extends XWorkTestCase {
     }
 
     public void testStringToPrimitiveDouble() {
-        assertEquals(new Double(123), converter.convertValue(context, null, null, null, "123", double.class));
+        assertEquals(123d, converter.convertValue(context, null, null, null, "123", double.class));
         context.put(ActionContext.LOCALE, Locale.US);
-        assertEquals(new Double(123.12), converter.convertValue(context, null, null, null, "123.12", double.class));
+        assertEquals(123.12, converter.convertValue(context, null, null, null, "123.12", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", double.class));
-        assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,234", double.class));
-        assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,234.12", double.class));
-        assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,23", double.class));
-        assertEquals(new Double(1.234), converter.convertValue(context, null, null, null, "1.234", double.class));
+        assertEquals(1234d, converter.convertValue(context, null, null, null, "1,234", double.class));
+        assertEquals(1234.12, converter.convertValue(context, null, null, null, "1,234.12", double.class));
+        assertEquals(123d, converter.convertValue(context, null, null, null, "1,23", double.class));
+        assertEquals(1.234, converter.convertValue(context, null, null, null, "1.234", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234,12", double.class));
 
         context.put(ActionContext.LOCALE, Locale.GERMANY);
-        assertEquals(new Double(123.12), converter.convertValue(context, null, null, null, "123.12", double.class));
+        assertEquals(12312d, converter.convertValue(context, null, null, null, "123.12", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "aa123", double.class));
-        assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,234", double.class));
+        assertEquals(1.234, converter.convertValue(context, null, null, null, "1,234", double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,234.12", double.class));
-        assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1,23", double.class));
-        assertEquals(new Double(1.234), converter.convertValue(context, null, null, null, "1.234", double.class));
-        assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "1.234,12", double.class));
+        assertEquals(1.23, converter.convertValue(context, null, null, null, "1,23", double.class));
+        assertEquals(1234d, converter.convertValue(context, null, null, null, "1.234", double.class));
+        assertEquals(1234.12, converter.convertValue(context, null, null, null, "1.234,12", double.class));
     }
 
     public void testStringToDouble() {
-        assertEquals(new Double(123), converter.convertValue(context, null, null, null, "123", Double.class));
+        assertEquals(123d, converter.convertValue(context, null, null, null, "123", Double.class));
         context.put(ActionContext.LOCALE, Locale.US);
         assertEquals(new Double(123.12), converter.convertValue(context, null, null, null, "123.12", Double.class));
         assertEquals(OgnlRuntime.NoConversionPossible, converter.convertValue(context, null, null, null, "123aa", Double.class));