You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2015/09/16 19:59:13 UTC

[13/15] incubator-freemarker git commit: FTL now uses the ExtendedDecimalFormatParser. Some cleanups in the code.

FTL now uses the ExtendedDecimalFormatParser. Some cleanups in the code.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/25f3b824
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/25f3b824
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/25f3b824

Branch: refs/heads/2.3
Commit: 25f3b824b263713dc48e32f05546a8a19e92f57d
Parents: 9ca1a71
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 19:23:12 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 19:23:12 2015 +0200

----------------------------------------------------------------------
 .../core/ExtendedDecimalFormatParser.java       | 86 ++++++++++++++------
 .../core/JavaTemplateNumberFormatFactory.java   |  7 +-
 .../core/ExtendedDecimalFormatTest.java         | 37 +++++++--
 3 files changed, 96 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/25f3b824/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java b/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
index b3f218f..76484cf 100644
--- a/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
+++ b/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
@@ -31,30 +31,53 @@ import java.util.Set;
 import freemarker.template.utility.StringUtil;
 
 class ExtendedDecimalFormatParser {
-
+    
+    private static final String PARAM_ROUNDING_MODE = "rnd";
+    private static final String PARAM_MULTIPIER = "mul";
+    private static final String PARAM_DECIMAL_SEPARATOR = "dec";
+    private static final String PARAM_MONETARY_DECIMAL_SEPARATOR = "mdec";
+    private static final String PARAM_GROUP_SEPARATOR = "grp";
+    private static final String PARAM_EXPONENT_SEPARATOR = "exp";
+    private static final String PARAM_MINUS_SIGN = "min";
+    private static final String PARAM_INFINITY = "inf";
+    private static final String PARAM_NAN = "nan";
+    private static final String PARAM_PERCENT = "prc";
+    private static final String PARAM_PER_MILL = "prm";
+    private static final String PARAM_ZERO_DIGIT = "zero";
+    private static final String PARAM_CURRENCY_CODE = "curc";
+    private static final String PARAM_CURRENCY_SYMBOL = "curs";
+
+    private static final String PARAM_VALUE_RND_UP = "u";
+    private static final String PARAM_VALUE_RND_DOWN = "d";
+    private static final String PARAM_VALUE_RND_CEILING = "c";
+    private static final String PARAM_VALUE_RND_FLOOR = "f";
+    private static final String PARAM_VALUE_RND_HALF_DOWN = "hd";
+    private static final String PARAM_VALUE_RND_HALF_EVEN = "he";
+    private static final String PARAM_VALUE_RND_HALF_UP = "hu";
+    private static final String PARAM_VALUE_RND_UNNECESSARY = "un";
+    
     private static final HashMap<String, ? extends ParameterHandler> PARAM_HANDLERS;
-
     static {
         HashMap<String, ParameterHandler> m = new HashMap<String, ParameterHandler>();
-        m.put("rnd", new ParameterHandler() {
+        m.put(PARAM_ROUNDING_MODE, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 RoundingMode parsedValue;
-                if (value.equals("u")) {
+                if (value.equals(PARAM_VALUE_RND_UP)) {
                     parsedValue = RoundingMode.UP;
-                } else if (value.equals("d")) {
+                } else if (value.equals(PARAM_VALUE_RND_DOWN)) {
                     parsedValue = RoundingMode.DOWN;
-                } else if (value.equals("c")) {
+                } else if (value.equals(PARAM_VALUE_RND_CEILING)) {
                     parsedValue = RoundingMode.CEILING;
-                } else if (value.equals("f")) {
+                } else if (value.equals(PARAM_VALUE_RND_FLOOR)) {
                     parsedValue = RoundingMode.FLOOR;
-                } else if (value.equals("hd")) {
+                } else if (value.equals(PARAM_VALUE_RND_HALF_DOWN)) {
                     parsedValue = RoundingMode.HALF_DOWN;
-                } else if (value.equals("he")) {
+                } else if (value.equals(PARAM_VALUE_RND_HALF_EVEN)) {
                     parsedValue = RoundingMode.HALF_EVEN;
-                } else if (value.equals("hu")) {
+                } else if (value.equals(PARAM_VALUE_RND_HALF_UP)) {
                     parsedValue = RoundingMode.HALF_UP;
-                } else if (value.equals("un")) {
+                } else if (value.equals(PARAM_VALUE_RND_UNNECESSARY)) {
                     parsedValue = RoundingMode.UNNECESSARY;
                 } else {
                     throw new InvalidParameterValueException("Should be one of: u, d, c, f, hd, he, hu, un");
@@ -67,7 +90,7 @@ class ExtendedDecimalFormatParser {
                 parser.roundingMode = parsedValue;
             }
         });
-        m.put("mul", new ParameterHandler() {
+        m.put(PARAM_MULTIPIER, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 try {
@@ -77,7 +100,7 @@ class ExtendedDecimalFormatParser {
                 }
             }
         });
-        m.put("dec", new ParameterHandler() {
+        m.put(PARAM_DECIMAL_SEPARATOR, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -86,7 +109,7 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setDecimalSeparator(value.charAt(0));
             }
         });
-        m.put("mdec", new ParameterHandler() {
+        m.put(PARAM_MONETARY_DECIMAL_SEPARATOR, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -95,7 +118,7 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setMonetaryDecimalSeparator(value.charAt(0));
             }
         });
-        m.put("grp", new ParameterHandler() {
+        m.put(PARAM_GROUP_SEPARATOR, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -104,7 +127,7 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setGroupingSeparator(value.charAt(0));
             }
         });
-        m.put("exp", new ParameterHandler() {
+        m.put(PARAM_EXPONENT_SEPARATOR, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (_JavaVersions.JAVA_6 == null) {
@@ -114,7 +137,7 @@ class ExtendedDecimalFormatParser {
                 _JavaVersions.JAVA_6.setExponentSeparator(parser.symbols, value);
             }
         });
-        m.put("min", new ParameterHandler() {
+        m.put(PARAM_MINUS_SIGN, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -123,19 +146,19 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setMinusSign(value.charAt(0));
             }
         });
-        m.put("inf", new ParameterHandler() {
+        m.put(PARAM_INFINITY, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 parser.symbols.setInfinity(value);
             }
         });
-        m.put("nan", new ParameterHandler() {
+        m.put(PARAM_NAN, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 parser.symbols.setNaN(value);
             }
         });
-        m.put("prc", new ParameterHandler() {
+        m.put(PARAM_PERCENT, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -144,7 +167,7 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setPercent(value.charAt(0));
             }
         });
-        m.put("prm", new ParameterHandler() {
+        m.put(PARAM_PER_MILL, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -153,7 +176,7 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setPerMill(value.charAt(0));
             }
         });
-        m.put("zero", new ParameterHandler() {
+        m.put(PARAM_ZERO_DIGIT, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -162,7 +185,7 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setZeroDigit(value.charAt(0));
             }
         });
-        m.put("curc", new ParameterHandler() {
+        m.put(PARAM_CURRENCY_CODE, new ParameterHandler() {
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 Currency currency;
@@ -196,7 +219,20 @@ class ExtendedDecimalFormatParser {
         skipWS();
         parseFormatStringExtension();
 
-        DecimalFormat decimalFormat = new DecimalFormat(stdPattern, symbols);
+        DecimalFormat decimalFormat;
+        try {
+            decimalFormat = new DecimalFormat(stdPattern, symbols);
+        } catch (IllegalArgumentException e) {
+            ParseException pe = new ParseException(e.getMessage(), 0);
+            if (e.getCause() != null) {
+                try {
+                    e.initCause(e.getCause());
+                } catch (Exception e2) {
+                    // Supress
+                }
+            }
+            throw pe;
+        }
 
         if (roundingMode != null) {
             if (_JavaVersions.JAVA_6 == null) {
@@ -244,7 +280,7 @@ class ExtendedDecimalFormatParser {
 
             ParameterHandler handler = PARAM_HANDLERS.get(name);
             if (handler == null) {
-                if (name.equals("curs")) {
+                if (name.equals(PARAM_CURRENCY_SYMBOL)) {
                     currencySymbol = value;
                 } else {
                     throw newUnknownParameterException(name, namePos);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/25f3b824/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java b/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java
index 21db3af..330d4f6 100644
--- a/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java
+++ b/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java
@@ -18,9 +18,8 @@
  */
 package freemarker.core;
 
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
+import java.text.ParseException;
 import java.util.Locale;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -59,8 +58,8 @@ class JavaTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
                 jFormat = env.getCNumberFormat();
             } else {
                 try {
-                    jFormat = new DecimalFormat(params, new DecimalFormatSymbols(locale));
-                } catch (IllegalArgumentException e) {
+                    jFormat = ExtendedDecimalFormatParser.parse(params, locale);
+                } catch (ParseException e) {
                     String msg = e.getMessage();
                     throw new InvalidFormatParametersException(
                             msg != null ? msg : "Invalid DecimalFormat pattern", e);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/25f3b824/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
index acd8f8b..0c5c9f2 100644
--- a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -22,13 +22,18 @@ import static freemarker.test.hamcerst.Matchers.*;
 import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
+import java.io.IOException;
 import java.text.DecimalFormat;
 import java.text.ParseException;
 import java.util.Locale;
 
 import org.junit.Test;
 
-public class ExtendedDecimalFormatTest {
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import freemarker.test.TemplateTest;
+
+public class ExtendedDecimalFormatTest extends TemplateTest {
     
     private static final Locale LOC = Locale.US;
     
@@ -47,7 +52,7 @@ public class ExtendedDecimalFormatTest {
         }
         try {
             ExtendedDecimalFormatParser.parse(";", LOC);
-        } catch (IllegalArgumentException e) {
+        } catch (ParseException e) {
             // Expected
         }
     }
@@ -81,19 +86,19 @@ public class ExtendedDecimalFormatTest {
         try {
             ExtendedDecimalFormatParser.parse("; ;", LOC);
             fail();
-        } catch (IllegalArgumentException e) {
+        } catch (ParseException e) {
             // Expected
         }
         try {
             ExtendedDecimalFormatParser.parse(";m", LOC);
             fail();
-        } catch (IllegalArgumentException e) {
+        } catch (ParseException e) {
             // Expected
         }
         try {
             ExtendedDecimalFormatParser.parse(";m;", LOC);
             fail();
-        } catch (IllegalArgumentException e) {
+        } catch (ParseException e) {
             // Expected
         }
     }
@@ -255,6 +260,28 @@ public class ExtendedDecimalFormatTest {
         assertEquals("1_000,0", ExtendedDecimalFormatParser.parse(",000.0;;grp=_", Locale.FRANCE).format(1000));
     }
     
+    @Test
+    public void testTemplates() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+        cfg.setLocale(Locale.US);
+        
+        cfg.setNumberFormat(",000.#");
+        assertOutput("${1000.15} ${1000.25}", "1,000.2 1,000.2");
+        cfg.setNumberFormat(",000.#;; rnd=hu grp=_");
+        assertOutput("${1000.15} ${1000.25}", "1_000.2 1_000.3");
+        cfg.setLocale(Locale.GERMANY);
+        assertOutput("${1000.15} ${1000.25}", "1_000,2 1_000,3");
+        cfg.setLocale(Locale.US);
+        assertOutput(
+                "${1000.15}; "
+                + "${1000.15?string(',##.#;;grp=\" \"')}; "
+                + "<#setting locale='de_DE'>${1000.15}; "
+                + "<#setting numberFormat='0.0;;rnd=d'>${1000.15}",
+                "1_000.2; 10 00.2; 1_000,2; 1000,1");
+        assertErrorContains("${1?string('#E')}", "\"#E\"", "format string", "exponential");
+        assertErrorContains("<#setting numberFormat='#E'>${1}", "\"#E\"", "format string", "exponential");
+        assertErrorContains("<#setting numberFormat=';;foo=bar'>${1}", "\"foo\"", "supported");
+    }
 
     private void assertFormatted(String formatString, Object... numberAndExpectedOutput) throws ParseException {
         assertFormatted(LOC, formatString, numberAndExpectedOutput);