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:01 UTC

[01/15] incubator-freemarker git commit: Version history typo: "Added freemarker.core.AliasTemplateNumberFormat*Factory* and AliasTemplateDateFormat*Factory*..."

Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3 b6d84a082 -> 53bf6b3b3


Version history typo: "Added freemarker.core.AliasTemplateNumberFormat*Factory* and AliasTemplateDateFormat*Factory*..."


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

Branch: refs/heads/2.3
Commit: 26c1ff1ea5a9d2ffa9e1705dd4fd3287cc24998e
Parents: 3fab33d
Author: ddekany <dd...@apache.org>
Authored: Thu Sep 10 01:24:25 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Thu Sep 10 01:24:25 2015 +0200

----------------------------------------------------------------------
 src/manual/book.xml | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/26c1ff1e/src/manual/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/book.xml b/src/manual/book.xml
index f50afda..5978a6d 100644
--- a/src/manual/book.xml
+++ b/src/manual/book.xml
@@ -25678,10 +25678,10 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
                 <listitem>
                   <para>Added
-                  <literal>freemarker.core.AliasTemplateNumberFormat</literal>
-                  and <literal>AliasTemplateDateFormat</literal>, which can be
-                  used to create custom formats that are aliases to other
-                  formats. For example, instead of writing
+                  <literal>freemarker.core.AliasTemplateNumberFormatFactory</literal>
+                  and <literal>AliasTemplateDateFormatFactory</literal>, which
+                  can be used to create custom formats that are aliases to
+                  other formats. For example, instead of writing
                   <literal>${n?string["0.00"]}</literal> again and again, you
                   can define the custom format <literal>"price"</literal> as
                   the alias to the format string <literal>"0.00"</literal> in
@@ -25850,10 +25850,10 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
             <listitem>
               <para>Added
-              <literal>freemarker.core.AliasTemplateNumberFormat</literal> and
-              <literal>AliasTemplateDateFormat</literal>, which can be used to
-              create custom formats that are aliases to other formats. For
-              example, instead of writing
+              <literal>freemarker.core.AliasTemplateNumberFormatFactory</literal>
+              and <literal>AliasTemplateDateFormatFactory</literal>, which can
+              be used to create custom formats that are aliases to other
+              formats. For example, instead of writing
               <literal>${n?string["0.00"]}</literal> again and again, you can
               define the custom format <literal>"price"</literal> as the alias
               to the format string <literal>"0.00"</literal> in the


[15/15] incubator-freemarker git commit: Merge remote-tracking branch 'origin/2.3-gae' into 2.3

Posted by dd...@apache.org.
Merge remote-tracking branch 'origin/2.3-gae' into 2.3


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

Branch: refs/heads/2.3
Commit: 53bf6b3b312f492c83d614b8b596010be563c898
Parents: b6d84a0 89ec237
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 19:54:37 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 19:54:37 2015 +0200

----------------------------------------------------------------------
 .classpath                                      |   4 +-
 .settings/org.eclipse.jdt.core.prefs            |   6 +-
 build.properties.sample                         |   1 +
 build.xml                                       |  35 +-
 ivy.xml                                         |   5 +-
 .../core/ExtendedDecimalFormatParser.java       | 523 +++++++++++++++++++
 .../core/JavaTemplateNumberFormat.java          |   7 +-
 .../core/JavaTemplateNumberFormatFactory.java   |   7 +-
 src/main/java/freemarker/core/_Java6.java       |  35 ++
 src/main/java/freemarker/core/_Java6Impl.java   |  45 ++
 .../java/freemarker/core/_JavaVersions.java     |  77 +++
 src/manual/book.xml                             |  16 +-
 .../core/ExtendedDecimalFormatTest.java         | 330 ++++++++++++
 .../freemarker/template/ConfigurationTest.java  |   2 +
 14 files changed, 1070 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/53bf6b3b/build.xml
----------------------------------------------------------------------


[11/15] incubator-freemarker git commit: (Test for BigDecimal "; ;")

Posted by dd...@apache.org.
(Test for BigDecimal "; ;")


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

Branch: refs/heads/2.3
Commit: be9500d0ae9589f15c4f4923c34f7e62f66ea09f
Parents: a071995
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 14:21:33 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 14:21:33 2015 +0200

----------------------------------------------------------------------
 .../java/freemarker/core/ExtendedDecimalFormatTest.java | 12 ++++++++++++
 1 file changed, 12 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be9500d0/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 612b063..b632069 100644
--- a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -73,6 +73,18 @@ public class ExtendedDecimalFormatTest {
             // Expected
         }
         try {
+            new DecimalFormat("; ;");
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            ExtendedDecimalFormatParser.parse("; ;", LOC);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
             ExtendedDecimalFormatParser.parse(";m", LOC);
             fail();
         } catch (IllegalArgumentException e) {


[04/15] incubator-freemarker git commit: (Suppressed a FindBugs false alarm.)

Posted by dd...@apache.org.
(Suppressed a FindBugs false alarm.)


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

Branch: refs/heads/2.3
Commit: aab02867e31f9d576ab9fad00cb65b2cbfb58837
Parents: 01552a9
Author: ddekany <dd...@apache.org>
Authored: Mon Sep 14 02:25:24 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Mon Sep 14 02:25:24 2015 +0200

----------------------------------------------------------------------
 src/test/java/freemarker/template/ConfigurationTest.java | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aab02867/src/test/java/freemarker/template/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index 9dd4a1c..3480de3 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -1376,6 +1376,7 @@ public class ConfigurationTest extends TestCase {
         }
     }
     
+    @SuppressFBWarnings(value="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS", justification="We test failures")
     @Test
     public void testSetCustomDateFormat() throws Exception {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);


[10/15] incubator-freemarker git commit: Allowed " for quotation in extended DecimalFormat option assignments.

Posted by dd...@apache.org.
Allowed " for quotation in extended DecimalFormat option assignments.


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

Branch: refs/heads/2.3
Commit: a071995ab4f122fb8d20296147747621974f6d59
Parents: 205bcda
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 13:43:06 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 13:43:06 2015 +0200

----------------------------------------------------------------------
 .../core/ExtendedDecimalFormatParser.java       | 29 ++++++++++----------
 .../core/ExtendedDecimalFormatTest.java         | 15 ++++++++++
 2 files changed, 30 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a071995a/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 1a44ece..0a14126 100644
--- a/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
+++ b/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
@@ -318,46 +318,47 @@ class ExtendedDecimalFormatParser {
     private String fetchValue() throws ParseException {
         int ln = src.length();
         int startPos = pos;
-        boolean quotedMode = false;
+        char openedQuot = 0;
         boolean needsUnescaping = false;
         scanUntilEnd: while (pos < ln) {
             char c = src.charAt(pos);
-            if (c == '\'') {
-                if (!quotedMode) {
+            if (c == '\'' || c == '"') {
+                if (openedQuot == 0) {
                     if (startPos != pos) {
                         throw new java.text.ParseException(
-                                "The \"'\" character can only be used for quoting values, "
+                                "The " + c + " character can only be used for quoting values, "
                                         + "but it was in the middle of an non-quoted value.",
                                 pos);
                     }
-                    quotedMode = true;
-                } else {
-                    if (pos + 1 < ln && src.charAt(pos + 1) == '\'') {
-                        pos++; // skip "''" (escaped "'")
+                    openedQuot = c;
+                } else if (c == openedQuot) {
+                    if (pos + 1 < ln && src.charAt(pos + 1) == openedQuot) {
+                        pos++; // skip doubled quote (escaping)
                         needsUnescaping = true;
                     } else {
                         String str = src.substring(startPos + 1, pos);
                         pos++;
-                        return needsUnescaping ? unescape(str) : str;
+                        return needsUnescaping ? unescape(str, openedQuot) : str;
                     }
                 }
             } else {
-                if (!quotedMode && !Character.isJavaIdentifierPart(c)) {
+                if (openedQuot == 0 && !Character.isJavaIdentifierPart(c)) {
                     break scanUntilEnd;
                 }
             }
             pos++;
         } // while
-        if (quotedMode) {
+        if (openedQuot != 0) {
             throw new java.text.ParseException(
-                    "The \"'\" quotation wasn't closed when the end of the source was reached.",
+                    "The " + openedQuot 
+                    + " quotation wasn't closed when the end of the source was reached.",
                     pos);
         }
         return startPos == pos ? null : src.substring(startPos, pos);
     }
 
-    private String unescape(String s) {
-        return StringUtil.replace(s, "\'\'", "\'");
+    private String unescape(String s, char openedQuot) {
+        return openedQuot == '\'' ? StringUtil.replace(s, "\'\'", "\'") : StringUtil.replace(s, "\"\"", "\"");
     }
 
     private String fetchStandardPattern() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a071995a/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 84ebf52..612b063 100644
--- a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -101,9 +101,17 @@ public class ExtendedDecimalFormatTest {
         
         assertFormatted("0.0;;inf=infinity", Double.POSITIVE_INFINITY, "infinity");
         assertFormatted("0.0;;inf='infinity'", Double.POSITIVE_INFINITY, "infinity");
+        assertFormatted("0.0;;inf=\"infinity\"", Double.POSITIVE_INFINITY, "infinity");
         assertFormatted("0.0;;inf=''", Double.POSITIVE_INFINITY, "");
+        assertFormatted("0.0;;inf=\"\"", Double.POSITIVE_INFINITY, "");
         assertFormatted("0.0;;inf='x''y'", Double.POSITIVE_INFINITY, "x'y");
+        assertFormatted("0.0;;inf=\"x'y\"", Double.POSITIVE_INFINITY, "x'y");
+        assertFormatted("0.0;;inf='x\"\"y'", Double.POSITIVE_INFINITY, "x\"\"y");
+        assertFormatted("0.0;;inf=\"x''y\"", Double.POSITIVE_INFINITY, "x''y");
         assertFormatted("0.0;;dec=''''", 1, "1'0");
+        assertFormatted("0.0;;dec=\"'\"", 1, "1'0");
+        assertFormatted("0.0;;dec='\"'", 1, "1\"0");
+        assertFormatted("0.0;;dec=\"\"\"\"", 1, "1\"0");
         
         try {
             ExtendedDecimalFormatParser.parse(";;dec=D,", LOC);
@@ -127,6 +135,13 @@ public class ExtendedDecimalFormatTest {
                     allOf(containsString("quotation"), containsString("closed")));
         }
         try {
+            ExtendedDecimalFormatParser.parse(";;dec=\"D", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(),
+                    allOf(containsString("quotation"), containsString("closed")));
+        }
+        try {
             ExtendedDecimalFormatParser.parse(";;dec='D'grp=G", LOC);
             fail();
         } catch (java.text.ParseException e) {


[03/15] incubator-freemarker git commit: Eclipse project files update to use Java 6 (the Ant build will still catch non-Java-5 calls where they aren't allowed)

Posted by dd...@apache.org.
Eclipse project files update to use Java 6 (the Ant build will still catch non-Java-5 calls where they aren't allowed)


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

Branch: refs/heads/2.3
Commit: 01552a9c2968c01be09eef9880564a0e1723bf92
Parents: 2daf5f3
Author: ddekany <dd...@apache.org>
Authored: Mon Sep 14 02:24:43 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Mon Sep 14 02:24:43 2015 +0200

----------------------------------------------------------------------
 .classpath                           | 2 +-
 .settings/org.eclipse.jdt.core.prefs | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/01552a9c/.classpath
----------------------------------------------------------------------
diff --git a/.classpath b/.classpath
index ad83438..6ca1ecd 100644
--- a/.classpath
+++ b/.classpath
@@ -9,7 +9,7 @@
 			<attribute name="ignore_optional_problems" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/annotations-3.0.0.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/ant-1.6.5.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/avalon-logkit-2.0.jar"/>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/01552a9c/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 7259bb5..e0e730a 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -17,9 +17,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.compliance=1.6
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -122,7 +122,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.6
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16


[08/15] incubator-freemarker git commit: (Suppressed a FindBugs false alarm.)

Posted by dd...@apache.org.
(Suppressed a FindBugs false alarm.)


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

Branch: refs/heads/2.3
Commit: d21fe9490778ecb80724c3e0b07f4d5a32f7c80f
Parents: 2bdd261
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 10:38:35 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 10:38:35 2015 +0200

----------------------------------------------------------------------
 src/test/java/freemarker/template/ConfigurationTest.java | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d21fe949/src/test/java/freemarker/template/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index 3480de3..6d5964f 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -1305,6 +1305,7 @@ public class ConfigurationTest extends TestCase {
     }
     
     @Test
+    @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS ", justification = "Testing wrong args")
     public void testSetCustomNumberFormat() throws Exception {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
         


[09/15] incubator-freemarker git commit: "rnd" instead of "ro", as the abbreviation of "rounding"

Posted by dd...@apache.org.
"rnd" instead of "ro", as the abbreviation of "rounding"


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

Branch: refs/heads/2.3
Commit: 205bcda44670bae2d705abc0f24ecb7fa92638de
Parents: d21fe94
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 10:43:08 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 10:43:08 2015 +0200

----------------------------------------------------------------------
 .../freemarker/core/ExtendedDecimalFormatParser.java  |  2 +-
 .../freemarker/core/ExtendedDecimalFormatTest.java    | 14 +++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/205bcda4/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 95acbba..1a44ece 100644
--- a/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
+++ b/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
@@ -35,7 +35,7 @@ class ExtendedDecimalFormatParser {
 
     static {
         HashMap<String, ParameterHandler> m = new HashMap<String, ParameterHandler>();
-        m.put("ro", new ParameterHandler() {
+        m.put("rnd", new ParameterHandler() {
 
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/205bcda4/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 d460fd4..84ebf52 100644
--- a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -161,19 +161,19 @@ public class ExtendedDecimalFormatTest {
     public void testExtendedParamsEffect() throws ParseException {
         assertFormatted("0",
                 1.5, "2", 2.5, "2", 3.5, "4", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-2", -2.5, "-2", -1.6, "-2");
-        assertFormatted("0;; ro=he",
+        assertFormatted("0;; rnd=he",
                 1.5, "2", 2.5, "2", 3.5, "4", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-2", -2.5, "-2", -1.6, "-2");
-        assertFormatted("0;; ro=hu",
+        assertFormatted("0;; rnd=hu",
                 1.5, "2", 2.5, "3", 3.5, "4", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-2", -2.5, "-3", -1.6, "-2");
-        assertFormatted("0;; ro=hd",
+        assertFormatted("0;; rnd=hd",
                 1.5, "1", 2.5, "2", 3.5, "3", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-1", -2.5, "-2", -1.6, "-2");
-        assertFormatted("0;; ro=f",
+        assertFormatted("0;; rnd=f",
                 1.5, "1", 2.5, "2", 3.5, "3", 1.4, "1", 1.6, "1", -1.4, "-2", -1.5, "-2", -2.5, "-3", -1.6, "-2");
-        assertFormatted("0;; ro=c",
+        assertFormatted("0;; rnd=c",
                 1.5, "2", 2.5, "3", 3.5, "4", 1.4, "2", 1.6, "2", -1.4, "-1", -1.5, "-1", -2.5, "-2", -1.6, "-1");
-        assertFormatted("0;; ro=un", 2, "2");
+        assertFormatted("0;; rnd=un", 2, "2");
         try {
-            assertFormatted("0;; ro=un", 2.5, "2");
+            assertFormatted("0;; rnd=un", 2.5, "2");
             fail();
         } catch (ArithmeticException e) {
             // Expected


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

Posted by dd...@apache.org.
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);


[05/15] incubator-freemarker git commit: Initial implementation of extended DecimalFormat format string parsing. It's not used by FTL yet. Also currency-related options are missing.

Posted by dd...@apache.org.
Initial implementation of extended DecimalFormat format string parsing. It's not used by FTL yet. Also currency-related options are missing.


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

Branch: refs/heads/2.3
Commit: 1d5198f67c2e90206742ace0900ea989088a2de0
Parents: aab0286
Author: ddekany <dd...@apache.org>
Authored: Mon Sep 14 02:27:27 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Mon Sep 14 02:27:27 2015 +0200

----------------------------------------------------------------------
 .../core/ExtendedDecimalFormatParser.java       | 460 +++++++++++++++++++
 .../core/ExtendedDecimalFormatTest.java         | 246 ++++++++++
 2 files changed, 706 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1d5198f6/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
new file mode 100644
index 0000000..95acbba
--- /dev/null
+++ b/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
@@ -0,0 +1,460 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package freemarker.core;
+
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Set;
+
+import freemarker.template.utility.StringUtil;
+
+class ExtendedDecimalFormatParser {
+
+    private static final HashMap<String, ? extends ParameterHandler> PARAM_HANDLERS;
+
+    static {
+        HashMap<String, ParameterHandler> m = new HashMap<String, ParameterHandler>();
+        m.put("ro", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                RoundingMode parsedValue;
+                if (value.equals("u")) {
+                    parsedValue = RoundingMode.UP;
+                } else if (value.equals("d")) {
+                    parsedValue = RoundingMode.DOWN;
+                } else if (value.equals("c")) {
+                    parsedValue = RoundingMode.CEILING;
+                } else if (value.equals("f")) {
+                    parsedValue = RoundingMode.FLOOR;
+                } else if (value.equals("hd")) {
+                    parsedValue = RoundingMode.HALF_DOWN;
+                } else if (value.equals("he")) {
+                    parsedValue = RoundingMode.HALF_EVEN;
+                } else if (value.equals("hu")) {
+                    parsedValue = RoundingMode.HALF_UP;
+                } else if (value.equals("un")) {
+                    parsedValue = RoundingMode.UNNECESSARY;
+                } else {
+                    throw new InvalidParameterValueException("Should be one of: u, d, c, f, hd, he, hu, un");
+                }
+
+                if (_JavaVersions.JAVA_6 == null) {
+                    throw new InvalidParameterValueException("For setting the rounding mode you need Java 6 or later.");
+                }
+
+                parser.roundingMode = parsedValue;
+            }
+        });
+        m.put("mul", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                try {
+                    parser.multipier = Integer.valueOf(value);
+                } catch (NumberFormatException e) {
+                    throw new InvalidParameterValueException("Malformed integer.");
+                }
+            }
+        });
+        m.put("dec", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setDecimalSeparator(value.charAt(0));
+            }
+        });
+        m.put("grp", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setGroupingSeparator(value.charAt(0));
+            }
+        });
+        m.put("exp", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (_JavaVersions.JAVA_6 == null) {
+                    throw new InvalidParameterValueException(
+                            "For setting the exponent separator you need Java 6 or later.");
+                }
+                _JavaVersions.JAVA_6.setExponentSeparator(parser.symbols, value);
+            }
+        });
+        m.put("min", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setMinusSign(value.charAt(0));
+            }
+        });
+        m.put("inf", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                parser.symbols.setInfinity(value);
+            }
+        });
+        m.put("nan", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                parser.symbols.setNaN(value);
+            }
+        });
+        m.put("prc", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setPercent(value.charAt(0));
+            }
+        });
+        m.put("prm", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setPerMill(value.charAt(0));
+            }
+        });
+        m.put("zero", new ParameterHandler() {
+
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setZeroDigit(value.charAt(0));
+            }
+        });
+        PARAM_HANDLERS = m;
+    }
+
+    private static final String SNIP_MARK = "[...]";
+    private static final int MAX_QUOTATION_LENGTH = 10; // Must be more than SNIP_MARK.length!
+
+    private final String src;
+    private int pos = 0;
+
+    private final DecimalFormatSymbols symbols;
+    private RoundingMode roundingMode;
+    private Integer multipier;
+
+    static DecimalFormat parse(String formatString, Locale locale) throws ParseException {
+        return new ExtendedDecimalFormatParser(formatString, locale).parse();
+    }
+
+    private DecimalFormat parse() throws ParseException {
+        String stdPattern = fetchStandardPattern();
+        skipWS();
+        parseFormatStringExtension();
+
+        DecimalFormat decimalFormat = new DecimalFormat(stdPattern, symbols);
+
+        if (roundingMode != null) {
+            if (_JavaVersions.JAVA_6 == null) {
+                throw new ParseException("Setting rounding mode needs Java 6 or later", 0);
+            }
+            _JavaVersions.JAVA_6.setRoundingMode(decimalFormat, roundingMode);
+        }
+
+        if (multipier != null) {
+            decimalFormat.setMultiplier(multipier.intValue());
+        }
+
+        return decimalFormat;
+    }
+
+    private void parseFormatStringExtension() throws ParseException {
+        int ln = src.length();
+
+        if (pos == ln) {
+            return;
+        }
+
+        do {
+            int namePos = pos;
+            String name = fetchName();
+            if (name == null) {
+                throw newExpectedSgParseException("name");
+            }
+
+            skipWS();
+
+            if (!fetchChar('=')) {
+                throw newExpectedSgParseException("\"=\"");
+            }
+
+            skipWS();
+
+            int valuePos = pos;
+            String value = fetchValue();
+            if (value == null) {
+                throw newExpectedSgParseException("value");
+            }
+            int paramEndPos = pos;
+
+            applyFormatStringExtensionParameter(name, namePos, value, valuePos);
+
+            skipWS();
+
+            // Optional comma
+            if (fetchChar(',')) {
+                skipWS();
+            } else {
+                if (pos == ln) {
+                    return;
+                }
+                if (pos == paramEndPos) {
+                    throw newExpectedSgParseException("parameter separator whitespace or comma");
+                }
+            }
+        } while (true);
+    }
+
+    private void applyFormatStringExtensionParameter(
+            String name, int namePos, String value, int valuePos) throws ParseException {
+        ParameterHandler handler = PARAM_HANDLERS.get(name);
+        if (handler == null) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("Unsupported parameter name, ").append(StringUtil.jQuote(name));
+            sb.append(". The supported names are: ");
+            Set<String> legalNames = PARAM_HANDLERS.keySet();
+            String[] legalNameArr = legalNames.toArray(new String[legalNames.size()]);
+            Arrays.sort(legalNameArr);
+            for (int i = 0; i < legalNameArr.length; i++) {
+                if (i != 0) {
+                    sb.append(", ");
+                }
+                sb.append(legalNameArr[i]);
+            }
+            throw new java.text.ParseException(sb.toString(), namePos);
+        }
+
+        try {
+            handler.handle(this, value);
+        } catch (InvalidParameterValueException e) {
+            throw new java.text.ParseException(
+                    StringUtil.jQuote(value) + " is an invalid value for the \"" + name + "\" parameter: " + e.message,
+                    valuePos);
+        }
+    }
+
+    private void skipWS() {
+        int ln = src.length();
+        while (pos < ln && isWS(src.charAt(pos))) {
+            pos++;
+        }
+    }
+
+    private boolean fetchChar(char fetchedChar) {
+        if (pos < src.length() && src.charAt(pos) == fetchedChar) {
+            pos++;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean isWS(char c) {
+        return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\u00A0';
+    }
+
+    private String fetchName() throws ParseException {
+        int ln = src.length();
+        int startPos = pos;
+        boolean firstChar = true;
+        scanUntilEnd: while (pos < ln) {
+            char c = src.charAt(pos);
+            if (firstChar) {
+                if (!Character.isJavaIdentifierStart(c)) {
+                    break scanUntilEnd;
+                }
+                firstChar = false;
+            } else if (!Character.isJavaIdentifierPart(c)) {
+                break scanUntilEnd;
+            }
+            pos++;
+        }
+        return !firstChar ? src.substring(startPos, pos) : null;
+    }
+
+    private String fetchValue() throws ParseException {
+        int ln = src.length();
+        int startPos = pos;
+        boolean quotedMode = false;
+        boolean needsUnescaping = false;
+        scanUntilEnd: while (pos < ln) {
+            char c = src.charAt(pos);
+            if (c == '\'') {
+                if (!quotedMode) {
+                    if (startPos != pos) {
+                        throw new java.text.ParseException(
+                                "The \"'\" character can only be used for quoting values, "
+                                        + "but it was in the middle of an non-quoted value.",
+                                pos);
+                    }
+                    quotedMode = true;
+                } else {
+                    if (pos + 1 < ln && src.charAt(pos + 1) == '\'') {
+                        pos++; // skip "''" (escaped "'")
+                        needsUnescaping = true;
+                    } else {
+                        String str = src.substring(startPos + 1, pos);
+                        pos++;
+                        return needsUnescaping ? unescape(str) : str;
+                    }
+                }
+            } else {
+                if (!quotedMode && !Character.isJavaIdentifierPart(c)) {
+                    break scanUntilEnd;
+                }
+            }
+            pos++;
+        } // while
+        if (quotedMode) {
+            throw new java.text.ParseException(
+                    "The \"'\" quotation wasn't closed when the end of the source was reached.",
+                    pos);
+        }
+        return startPos == pos ? null : src.substring(startPos, pos);
+    }
+
+    private String unescape(String s) {
+        return StringUtil.replace(s, "\'\'", "\'");
+    }
+
+    private String fetchStandardPattern() {
+        int pos = this.pos;
+        int ln = src.length();
+        int semicolonCnt = 0;
+        boolean quotedMode = false;
+        findStdPartEnd: while (pos < ln) {
+            char c = src.charAt(pos);
+            if (c == ';' && !quotedMode) {
+                semicolonCnt++;
+                if (semicolonCnt == 2) {
+                    break findStdPartEnd;
+                }
+            } else if (c == '\'') {
+                if (quotedMode) {
+                    if (pos + 1 < ln && src.charAt(pos + 1) == '\'') {
+                        // Skips "''" used for escaping "'"
+                        pos++;
+                    } else {
+                        quotedMode = false;
+                    }
+                } else {
+                    quotedMode = true;
+                }
+            }
+            pos++;
+        }
+
+        String stdFormatStr;
+        if (semicolonCnt < 2) { // We have a standard DecimalFormat string
+            // Note that "0.0;" and "0.0" gives the same result with DecimalFormat, so we leave a ';' there
+            stdFormatStr = src;
+        } else { // `pos` points to the 2nd ';'
+            int stdEndPos = pos;
+            if (src.charAt(pos - 1) == ';') { // we have a ";;"
+                // Note that ";;" is illegal in DecimalFormat, so this is backward compatible.
+                stdEndPos--;
+            }
+            stdFormatStr = src.substring(0, stdEndPos);
+        }
+
+        if (pos < ln) {
+            pos++; // Skips closing ';'
+        }
+        this.pos = pos;
+
+        return stdFormatStr;
+    }
+
+    private ExtendedDecimalFormatParser(String formatString, Locale locale) {
+        src = formatString;
+        this.symbols = new DecimalFormatSymbols(locale);
+    }
+
+    private ParseException newExpectedSgParseException(String expectedThing) {
+        String quotation;
+
+        // Ignore trailing WS when calculating the length:
+        int i = src.length() - 1;
+        while (i >= 0 && Character.isWhitespace(src.charAt(i))) {
+            i--;
+        }
+        int ln = i + 1;
+
+        if (pos < ln) {
+            int qEndPos = pos + MAX_QUOTATION_LENGTH;
+            if (qEndPos >= ln) {
+                quotation = src.substring(pos, ln);
+            } else {
+                quotation = src.substring(pos, qEndPos - SNIP_MARK.length()) + SNIP_MARK;
+            }
+        } else {
+            quotation = null;
+        }
+
+        return new ParseException(
+                "Expected a(n) " + expectedThing + " at position " + pos + " (0-based), but "
+                        + (quotation == null ? "reached the end of the input." : "found: " + quotation),
+                pos);
+    }
+
+    private interface ParameterHandler {
+
+        void handle(ExtendedDecimalFormatParser parser, String value)
+                throws InvalidParameterValueException;
+
+    }
+
+    private static class InvalidParameterValueException extends Exception {
+
+        private final String message;
+
+        public InvalidParameterValueException(String message) {
+            this.message = message;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1d5198f6/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
new file mode 100644
index 0000000..d460fd4
--- /dev/null
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package freemarker.core;
+
+import static freemarker.test.hamcerst.Matchers.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.util.Locale;
+
+import org.junit.Test;
+
+public class ExtendedDecimalFormatTest {
+    
+    private static final Locale LOC = Locale.US;
+    
+    @Test
+    public void testNonExtended() throws ParseException {
+        for (String fStr : new String[] { "0.00", "0.###", "#,#0.###", "#0.####", "0.0;m", "0.0;",
+                "0'x'", "0'x';'m'", "0';'", "0';';m", "0';';'#'m';'", "0';;'", "" }) {
+            assertFormatsEquivalent(new DecimalFormat(fStr), ExtendedDecimalFormatParser.parse(fStr, LOC));
+        }
+        
+        try {
+            new DecimalFormat(";");
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";", LOC);
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testNonExtended2() throws ParseException {
+        assertFormatsEquivalent(new DecimalFormat("0.0"), ExtendedDecimalFormatParser.parse("0.0;", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0.0"), ExtendedDecimalFormatParser.parse("0.0;;", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0.0;m"), ExtendedDecimalFormatParser.parse("0.0;m;", LOC));
+        assertFormatsEquivalent(new DecimalFormat(""), ExtendedDecimalFormatParser.parse(";;", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0'x'"), ExtendedDecimalFormatParser.parse("0'x';;", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0'x';'m'"), ExtendedDecimalFormatParser.parse("0'x';'m';", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0';'"), ExtendedDecimalFormatParser.parse("0';';;", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0';';m"), ExtendedDecimalFormatParser.parse("0';';m;", LOC));
+        assertFormatsEquivalent(new DecimalFormat("0';';'#'m';'"), ExtendedDecimalFormatParser.parse("0';';'#'m';';",
+                LOC));
+        assertFormatsEquivalent(new DecimalFormat("0';;'"), ExtendedDecimalFormatParser.parse("0';;';;", LOC));
+        
+        try {
+            new DecimalFormat(";m");
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";m", LOC);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";m;", LOC);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+    
+    @SuppressWarnings("boxing")
+    @Test
+    public void testExtendedParamsParsing() throws ParseException {
+        for (String fs : new String[] {
+                "00.##;; dec='D'", "00.##;;dec=D", "00.##;;  dec  =  D ", "00.##;; dec = 'D' " }) {
+            assertFormatted(fs, 1.125, "01D12");
+        }
+        for (String fs : new String[] {
+                ",#0.0;; dec=D, grp=_", ",#0.0;;dec=D,grp=_", ",#0.0;; dec = D , grp = _ ", ",#0.0;; dec='D', grp='_'"
+                }) {
+            assertFormatted(fs, 12345, "1_23_45D0");
+        }
+        
+        assertFormatted("0.0;;inf=infinity", Double.POSITIVE_INFINITY, "infinity");
+        assertFormatted("0.0;;inf='infinity'", Double.POSITIVE_INFINITY, "infinity");
+        assertFormatted("0.0;;inf=''", Double.POSITIVE_INFINITY, "");
+        assertFormatted("0.0;;inf='x''y'", Double.POSITIVE_INFINITY, "x'y");
+        assertFormatted("0.0;;dec=''''", 1, "1'0");
+        
+        try {
+            ExtendedDecimalFormatParser.parse(";;dec=D,", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(),
+                    allOf(containsStringIgnoringCase("expected a(n) name"), containsString(" end of ")));
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";;xdec=D,", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(),
+                    allOf(containsString("\"xdec\""), containsString("name")));
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";;dec='D", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(),
+                    allOf(containsString("quotation"), containsString("closed")));
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";;dec='D'grp=G", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(), allOf(
+                    containsString("separator"), containsString("whitespace"), containsString("comma")));
+        }
+        try {
+            ExtendedDecimalFormatParser.parse(";;dec=., grp=G", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(), allOf(
+                    containsStringIgnoringCase("expected a(n) value"), containsString("., grp")));
+        }
+        try {
+            ExtendedDecimalFormatParser.parse("0.0;;dec=''", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(), allOf(
+                    containsStringIgnoringCase("\"dec\""), containsString("exactly 1 char")));
+        }
+        try {
+            ExtendedDecimalFormatParser.parse("0.0;;mul=ten", LOC);
+            fail();
+        } catch (java.text.ParseException e) {
+            assertThat(e.getMessage(), allOf(
+                    containsString("\"mul\""), containsString("\"ten\""), containsString("integer")));
+        }
+    }
+    
+    @SuppressWarnings("boxing")
+    @Test
+    public void testExtendedParamsEffect() throws ParseException {
+        assertFormatted("0",
+                1.5, "2", 2.5, "2", 3.5, "4", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-2", -2.5, "-2", -1.6, "-2");
+        assertFormatted("0;; ro=he",
+                1.5, "2", 2.5, "2", 3.5, "4", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-2", -2.5, "-2", -1.6, "-2");
+        assertFormatted("0;; ro=hu",
+                1.5, "2", 2.5, "3", 3.5, "4", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-2", -2.5, "-3", -1.6, "-2");
+        assertFormatted("0;; ro=hd",
+                1.5, "1", 2.5, "2", 3.5, "3", 1.4, "1", 1.6, "2", -1.4, "-1", -1.5, "-1", -2.5, "-2", -1.6, "-2");
+        assertFormatted("0;; ro=f",
+                1.5, "1", 2.5, "2", 3.5, "3", 1.4, "1", 1.6, "1", -1.4, "-2", -1.5, "-2", -2.5, "-3", -1.6, "-2");
+        assertFormatted("0;; ro=c",
+                1.5, "2", 2.5, "3", 3.5, "4", 1.4, "2", 1.6, "2", -1.4, "-1", -1.5, "-1", -2.5, "-2", -1.6, "-1");
+        assertFormatted("0;; ro=un", 2, "2");
+        try {
+            assertFormatted("0;; ro=un", 2.5, "2");
+            fail();
+        } catch (ArithmeticException e) {
+            // Expected
+        }
+
+        assertFormatted("0.##;; mul=100", 12.345, "1234.5");
+        assertFormatted("0.##;; mul=1000", 12.345, "12345");
+        
+        assertFormatted(",##0.##;; grp=_ dec=D", 12345.1, "12_345D1", 1, "1");
+        
+        assertFormatted("0.##E0;; exp='*10^'", 12345.1, "1.23*10^4");
+        
+        assertFormatted("0.##;; min=m", -1, "m1", 1, "1");
+        
+        assertFormatted("0.##;; inf=foo", Double.POSITIVE_INFINITY, "foo", Double.NEGATIVE_INFINITY, "-foo");
+        
+        assertFormatted("0.##;; nan=foo", Double.NaN, "foo");
+        
+        assertFormatted("0%;; prc='c'", 0.75, "75c");
+        
+        assertFormatted("0\u2030;; prm='m'", 0.75, "750m");
+        
+        assertFormatted("0.00;; zero='@'", 10.5, "A@.E@");
+    }
+    
+    @Test
+    public void testLocale() throws ParseException {
+        assertEquals("1000.0", ExtendedDecimalFormatParser.parse("0.0", Locale.US).format(1000));
+        assertEquals("1000,0", ExtendedDecimalFormatParser.parse("0.0", Locale.FRANCE).format(1000));
+        assertEquals("1_000.0", ExtendedDecimalFormatParser.parse(",000.0;;grp=_", Locale.US).format(1000));
+        assertEquals("1_000,0", ExtendedDecimalFormatParser.parse(",000.0;;grp=_", Locale.FRANCE).format(1000));
+    }
+    
+
+    private void assertFormatted(String formatString, Object... numberAndExpectedOutput) throws ParseException {
+        if (numberAndExpectedOutput.length % 2 != 0) {
+            throw new IllegalArgumentException();
+        }
+        
+        DecimalFormat df = ExtendedDecimalFormatParser.parse(formatString, LOC);
+        Number num = null;
+        for (int i = 0; i < numberAndExpectedOutput.length; i++) {
+            if (i % 2 == 0) {
+                num = (Number) numberAndExpectedOutput[i];
+            } else {
+                assertEquals(numberAndExpectedOutput[i], df.format(num));
+            }
+        }
+    }
+    
+    private void assertFormatsEquivalent(DecimalFormat dfExpected, DecimalFormat dfActual) {
+        for (int signum : new int[] { 1, -1 }) {
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 0);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 0.5);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 0.25);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 0.125);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 1);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 10);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 100);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 1000);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 10000);
+            assertFormatsEquivalent(dfExpected, dfActual, signum * 100000);
+        }
+    }
+
+    private void assertFormatsEquivalent(DecimalFormat dfExpected, DecimalFormat dfActual, double n) {
+        assertEquals(dfExpected.format(n), dfActual.format(n));
+    }
+    
+}


[06/15] incubator-freemarker git commit: Changed Jython 2.0 dependency to 2.1, because 2.0 isn't present in the Maven Central Repo. Luckily, the API-s used by us are the same in both versions.

Posted by dd...@apache.org.
Changed Jython 2.0 dependency to 2.1, because 2.0 isn't present in the Maven Central Repo. Luckily, the API-s used by us are the same in both versions.


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

Branch: refs/heads/2.3
Commit: 41ec86442b92dc0fc44be3636f0e96e71d8995c5
Parents: 1d5198f
Author: ddekany <dd...@apache.org>
Authored: Tue Sep 15 22:58:57 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Sep 15 22:58:57 2015 +0200

----------------------------------------------------------------------
 ivy.xml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/41ec8644/ivy.xml
----------------------------------------------------------------------
diff --git a/ivy.xml b/ivy.xml
index f81c3c3..e8457f5 100644
--- a/ivy.xml
+++ b/ivy.xml
@@ -102,7 +102,8 @@
     
     <dependency org="rhino" name="js" rev="1.6R1" conf="build.base->default" />
 
-    <dependency org="org.python" name="jython" rev="2.0.0" conf="build.jython2.0->default" />
+    <!-- We use Jython 2.1 because there was no 2.0 in central; the relevant methods are the same. -->
+    <dependency org="jython" name="jython" rev="2.1" conf="build.jython2.0->default" />
     <dependency org="org.python" name="jython" rev="2.2.1" conf="build.jython2.2->default" />
     <dependency org="org.python" name="jython" rev="2.5.0" conf="build.jython2.5->default" />
     


[02/15] incubator-freemarker git commit: Added support for calling some Java 6 functions (despite that we only require Java 5)

Posted by dd...@apache.org.
Added support for calling some Java 6 functions (despite that we only require Java 5)


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

Branch: refs/heads/2.3
Commit: 2daf5f3d78d15cfed55b93459ef31af9a1889db9
Parents: 26c1ff1
Author: ddekany <dd...@apache.org>
Authored: Mon Sep 14 02:23:29 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Mon Sep 14 02:23:29 2015 +0200

----------------------------------------------------------------------
 build.properties.sample                         |  1 +
 build.xml                                       | 35 ++++++++-
 src/main/java/freemarker/core/_Java6.java       | 35 +++++++++
 src/main/java/freemarker/core/_Java6Impl.java   | 45 ++++++++++++
 .../java/freemarker/core/_JavaVersions.java     | 77 ++++++++++++++++++++
 5 files changed, 190 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2daf5f3d/build.properties.sample
----------------------------------------------------------------------
diff --git a/build.properties.sample b/build.properties.sample
index 82c818b..1a94745 100644
--- a/build.properties.sample
+++ b/build.properties.sample
@@ -1,4 +1,5 @@
 # Copy this file to "build.properties" before editing!
 # These propeties should point to the rt.jar-s of the respective J2SE versions:
 boot.classpath.j2se1.5=C:/Program Files (x86)/Java/jdk1.5.0_16/jre/lib/rt.jar
+boot.classpath.j2se1.6=C:/Program Files/Java/jdk1.6.0_24/jre/lib/rt.jar
 mvnCommand=C:/Program Files (x86)/maven3/bin/mvn.bat
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2daf5f3d/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index 03ac2fb..e6b84cc 100644
--- a/build.xml
+++ b/build.xml
@@ -24,9 +24,13 @@
   <condition property="has.explicit.boot.classpath.j2se1.5">
     <isset property="boot.classpath.j2se1.5"/>
   </condition>
+  <condition property="has.explicit.boot.classpath.j2se1.6">
+    <isset property="boot.classpath.j2se1.6"/>
+  </condition>
   <condition property="has.all.explicit.boot.classpaths">
     <and>
       <isset property="has.explicit.boot.classpath.j2se1.5"/>
+      <isset property="has.explicit.boot.classpath.j2se1.6"/>
     </and>
   </condition>
   <available property="atLeastJDK8" classname="java.util.function.Predicate"/>
@@ -34,12 +38,17 @@
   <!-- When boot.classpath.j2se* is missing, these will be the defaults: -->
   <!-- Note: Target "dist" doesn't allow using these. -->
   <property name="boot.classpath.j2se1.5" value="${sun.boot.class.path}" />
+  <property name="boot.classpath.j2se1.6" value="${sun.boot.class.path}" />
   
   <!-- For checking the correctness of the boot.classpath.j2se* -->
   <available classpath="${boot.classpath.j2se1.5}"
-    classname="java.lang.Object" ignoresystemclasses="true" 
+    classname="java.util.concurrent.ConcurrentHashMap" ignoresystemclasses="true" 
     property="boot.classpath.j2se1.5.correct"
   />
+  <available classpath="${boot.classpath.j2se1.6}"
+    classname="java.util.ServiceLoader" ignoresystemclasses="true" 
+    property="boot.classpath.j2se1.6.correct"
+  />
   
   <condition property="example.freemarker.jar.location"
     value="freemarker.jar" else="build/freemarker.jar">
@@ -179,7 +188,17 @@
       -->the &lt;projectDir>/build.properties file, or wherever you <!--
       -->set it.<!--
     --></fail>
-    <echo level="info">Using boot classpaths: 1.5: ${boot.classpath.j2se1.5}</echo>
+    <fail unless="boot.classpath.j2se1.6.correct"><!--
+      -->The "boot.classpath.j2se1.6" property value (${boot.classpath.j2se1.6}) <!--
+      -->seems to be an incorrect boot classpath. Please fix it in <!--
+      -->the &lt;projectDir>/build.properties file, or wherever you <!--
+      -->set it.<!--
+    --></fail>
+    <echo level="info"><!--
+      -->Using boot classpaths:<!--
+      -->Java 5: ${boot.classpath.j2se1.5}; <!--
+      -->Java 6: ${boot.classpath.j2se1.6}<!--
+    --></echo>
 
     <mkdir dir="build/classes" />
     
@@ -191,6 +210,7 @@
       classpathref="ivy.dep"
       bootclasspath="${boot.classpath.j2se1.5}"
       excludes="
+        freemarker/core/_Java6Impl.java,
         freemarker/ext/jsp/**,
         freemarker/ext/servlet/**,
         freemarker/cache/WebappTemplateLoader.java,
@@ -205,6 +225,15 @@
       </src>
     </javac>
 
+    <ivy:cachepath conf="build.base" pathid="ivy.dep" />
+    <javac srcdir="src/main/java" destdir="build/classes" deprecation="off" 
+      debug="on" optimize="off" target="1.5" source="1.5" encoding="utf-8"
+      includeantruntime="false"
+      classpathref="ivy.dep"
+      bootclasspath="${boot.classpath.j2se1.6}"
+      includes="freemarker/core/_Java6Impl.java"
+    />
+    
     <rmic
       base="build/classes" includes="freemarker/debug/impl/Rmi*Impl.class"
       classpathref="ivy.dep"
@@ -331,7 +360,7 @@
       includeantruntime="false"
       classpath="build/classes"
       classpathref="ivy.dep.build.test"
-      bootclasspath="${boot.classpath.j2se1.5}"
+      bootclasspath="${boot.classpath.j2se1.6}"
     />
     <copy toDir="build/test-classes">
       <fileset dir="src/test/resources"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2daf5f3d/src/main/java/freemarker/core/_Java6.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_Java6.java b/src/main/java/freemarker/core/_Java6.java
new file mode 100644
index 0000000..8a49389
--- /dev/null
+++ b/src/main/java/freemarker/core/_Java6.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package freemarker.core;
+
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+
+/**
+ * Used internally only, might changes without notice!
+ * Used for accessing functionality that's only present in Java 6 or later.
+ */
+public interface _Java6 {
+
+    void setRoundingMode(DecimalFormat df, RoundingMode roundingMode);
+
+    void setExponentSeparator(DecimalFormatSymbols dfs, String exponentSeparator);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2daf5f3d/src/main/java/freemarker/core/_Java6Impl.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_Java6Impl.java b/src/main/java/freemarker/core/_Java6Impl.java
new file mode 100644
index 0000000..ba2b21c
--- /dev/null
+++ b/src/main/java/freemarker/core/_Java6Impl.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package freemarker.core;
+
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+
+/**
+ * Used internally only, might changes without notice!
+ * Used for accessing functionality that's only present in Java 6 or later.
+ */
+public final class _Java6Impl implements _Java6 {
+    
+    public static final _Java6 INSTANCE = new _Java6Impl();
+
+    private _Java6Impl() {
+        // Not meant to be instantiated
+    }
+
+    public void setRoundingMode(DecimalFormat df, RoundingMode roundingMode) {
+        df.setRoundingMode(roundingMode);
+    }
+
+    public void setExponentSeparator(DecimalFormatSymbols dfs, String exponentSeparator) {
+        dfs.setExponentSeparator(exponentSeparator);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2daf5f3d/src/main/java/freemarker/core/_JavaVersions.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_JavaVersions.java b/src/main/java/freemarker/core/_JavaVersions.java
new file mode 100644
index 0000000..244862d
--- /dev/null
+++ b/src/main/java/freemarker/core/_JavaVersions.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package freemarker.core;
+
+import freemarker.log.Logger;
+import freemarker.template.Version;
+import freemarker.template.utility.SecurityUtilities;
+
+/**
+ * Used internally only, might changes without notice!
+ */
+public final class _JavaVersions {
+    
+    private _JavaVersions() {
+        // Not meant to be instantiated
+    }
+
+    private static final boolean IS_AT_LEAST_6;
+    static {
+        boolean result = false;
+        String vStr = SecurityUtilities.getSystemProperty("java.version", null);
+        if (vStr != null) {
+            try {
+                Version v = new Version(vStr);
+                result = v.getMajor() == 1 && v.getMinor() >= 6 || v.getMajor() > 1;
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+        if (vStr == null) {
+            try {
+                Class.forName("java.util.ServiceLoader");
+                result = true;
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+        IS_AT_LEAST_6 = result;
+    }
+    
+    static public final _Java6 JAVA_6;
+    static {
+        _Java6 java6;
+        if (IS_AT_LEAST_6) {
+            try {
+                java6 = (_Java6) Class.forName("freemarker.core._Java6Impl").getField("INSTANCE").get(null);
+            } catch (Exception e) {
+                try {
+                    Logger.getLogger("freemarker.runtime").error("Failed to access Java 6 functionality", e);
+                } catch (Exception e2) {
+                    // Suppressed
+                }
+                java6 = null;
+            }
+        } else {
+            java6 = null;
+        }
+        JAVA_6 = java6;
+    }
+    
+}


[12/15] incubator-freemarker git commit: Extended decimal format strings now support options "curc" for CURrency Code (ISO 4217), "curs" for CURency Symbol, and "mdec" for the monetary version of "dec". Just like the other extended format options, these

Posted by dd...@apache.org.
Extended decimal format strings now support options "curc" for CURrency Code (ISO 4217), "curs" for CURency Symbol, and "mdec" for the monetary version of "dec". Just like the other extended format options, these just make long existing DecimalFormat capabilities accessible. Examples: "0.## ¤;;curs=bucks"  prints something like "10 bucks", "¤0.##;;curc=USD" prints "$10" (at least if locale is US).


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

Branch: refs/heads/2.3
Commit: 9ca1a710efd7a2a8d7e399c10cffa9d6dbb4e5a1
Parents: be9500d
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 17:38:44 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 17:41:46 2015 +0200

----------------------------------------------------------------------
 .../core/ExtendedDecimalFormatParser.java       | 102 ++++++++++++-------
 .../core/ExtendedDecimalFormatTest.java         |  27 ++++-
 2 files changed, 90 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/9ca1a710/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 0a14126..b3f218f 100644
--- a/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
+++ b/src/main/java/freemarker/core/ExtendedDecimalFormatParser.java
@@ -23,6 +23,7 @@ import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.ParseException;
 import java.util.Arrays;
+import java.util.Currency;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Set;
@@ -36,7 +37,6 @@ class ExtendedDecimalFormatParser {
     static {
         HashMap<String, ParameterHandler> m = new HashMap<String, ParameterHandler>();
         m.put("rnd", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 RoundingMode parsedValue;
@@ -68,7 +68,6 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("mul", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 try {
@@ -79,7 +78,6 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("dec", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -88,8 +86,16 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setDecimalSeparator(value.charAt(0));
             }
         });
+        m.put("mdec", new ParameterHandler() {
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                if (value.length() != 1) {
+                    throw new InvalidParameterValueException("Must contain exactly 1 character.");
+                }
+                parser.symbols.setMonetaryDecimalSeparator(value.charAt(0));
+            }
+        });
         m.put("grp", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -99,7 +105,6 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("exp", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (_JavaVersions.JAVA_6 == null) {
@@ -110,7 +115,6 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("min", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -120,21 +124,18 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("inf", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 parser.symbols.setInfinity(value);
             }
         });
         m.put("nan", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 parser.symbols.setNaN(value);
             }
         });
         m.put("prc", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -144,7 +145,6 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("prm", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -154,7 +154,6 @@ class ExtendedDecimalFormatParser {
             }
         });
         m.put("zero", new ParameterHandler() {
-
             public void handle(ExtendedDecimalFormatParser parser, String value)
                     throws InvalidParameterValueException {
                 if (value.length() != 1) {
@@ -163,6 +162,18 @@ class ExtendedDecimalFormatParser {
                 parser.symbols.setZeroDigit(value.charAt(0));
             }
         });
+        m.put("curc", new ParameterHandler() {
+            public void handle(ExtendedDecimalFormatParser parser, String value)
+                    throws InvalidParameterValueException {
+                Currency currency;
+                try {
+                    currency = Currency.getInstance(value);
+                } catch (IllegalArgumentException e) {
+                    throw new InvalidParameterValueException("Not a known ISO 4217 code.");
+                }
+                parser.symbols.setCurrency(currency);
+            }
+        });
         PARAM_HANDLERS = m;
     }
 
@@ -208,7 +219,8 @@ class ExtendedDecimalFormatParser {
             return;
         }
 
-        do {
+        String currencySymbol = null;  // Exceptional, as must be applied after "currency code"
+        fetchParamters: do {
             int namePos = pos;
             String name = fetchName();
             if (name == null) {
@@ -230,7 +242,20 @@ class ExtendedDecimalFormatParser {
             }
             int paramEndPos = pos;
 
-            applyFormatStringExtensionParameter(name, namePos, value, valuePos);
+            ParameterHandler handler = PARAM_HANDLERS.get(name);
+            if (handler == null) {
+                if (name.equals("curs")) {
+                    currencySymbol = value;
+                } else {
+                    throw newUnknownParameterException(name, namePos);
+                }
+            } else {
+                try {
+                    handler.handle(this, value);
+                } catch (InvalidParameterValueException e) {
+                    throw newInvalidParameterValueException(name, value, valuePos, e);
+                }
+            }
 
             skipWS();
 
@@ -239,41 +264,42 @@ class ExtendedDecimalFormatParser {
                 skipWS();
             } else {
                 if (pos == ln) {
-                    return;
+                    break fetchParamters;
                 }
                 if (pos == paramEndPos) {
                     throw newExpectedSgParseException("parameter separator whitespace or comma");
                 }
             }
         } while (true);
+        
+        // This is brought out to here to ensure that it's applied after "currency code":
+        if (currencySymbol != null) {
+            symbols.setCurrencySymbol(currencySymbol);
+        }
     }
 
-    private void applyFormatStringExtensionParameter(
-            String name, int namePos, String value, int valuePos) throws ParseException {
-        ParameterHandler handler = PARAM_HANDLERS.get(name);
-        if (handler == null) {
-            StringBuilder sb = new StringBuilder(128);
-            sb.append("Unsupported parameter name, ").append(StringUtil.jQuote(name));
-            sb.append(". The supported names are: ");
-            Set<String> legalNames = PARAM_HANDLERS.keySet();
-            String[] legalNameArr = legalNames.toArray(new String[legalNames.size()]);
-            Arrays.sort(legalNameArr);
-            for (int i = 0; i < legalNameArr.length; i++) {
-                if (i != 0) {
-                    sb.append(", ");
-                }
-                sb.append(legalNameArr[i]);
-            }
-            throw new java.text.ParseException(sb.toString(), namePos);
-        }
+    private ParseException newInvalidParameterValueException(String name, String value, int valuePos,
+            InvalidParameterValueException e) {
+        return new java.text.ParseException(
+                StringUtil.jQuote(value) + " is an invalid value for the \"" + name + "\" parameter: "
+                + e.message,
+                valuePos);
+    }
 
-        try {
-            handler.handle(this, value);
-        } catch (InvalidParameterValueException e) {
-            throw new java.text.ParseException(
-                    StringUtil.jQuote(value) + " is an invalid value for the \"" + name + "\" parameter: " + e.message,
-                    valuePos);
+    private ParseException newUnknownParameterException(String name, int namePos) throws ParseException {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("Unsupported parameter name, ").append(StringUtil.jQuote(name));
+        sb.append(". The supported names are: ");
+        Set<String> legalNames = PARAM_HANDLERS.keySet();
+        String[] legalNameArr = legalNames.toArray(new String[legalNames.size()]);
+        Arrays.sort(legalNameArr);
+        for (int i = 0; i < legalNameArr.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(legalNameArr[i]);
         }
+        return new java.text.ParseException(sb.toString(), namePos);
     }
 
     private void skipWS() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/9ca1a710/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 b632069..acd8f8b 100644
--- a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -224,6 +224,27 @@ public class ExtendedDecimalFormatTest {
         assertFormatted("0\u2030;; prm='m'", 0.75, "750m");
         
         assertFormatted("0.00;; zero='@'", 10.5, "A@.E@");
+        
+        assertFormatted("0;; curc=USD", 10, "10");
+        assertFormatted("0 \u00A4;; curc=USD", 10, "10 $");
+        assertFormatted("0 \u00A4\u00A4;; curc=USD", 10, "10 USD");
+        assertFormatted(Locale.GERMANY, "0 \u00A4;; curc=EUR", 10, "10 \u20AC");
+        assertFormatted(Locale.GERMANY, "0 \u00A4\u00A4;; curc=EUR", 10, "10 EUR");
+        try {
+            assertFormatted("0;; curc=USDX", 10, "10");
+        } catch (ParseException e) {
+            assertThat(e.getMessage(), containsString("ISO 4217"));
+        }
+        assertFormatted("0 \u00A4;; curc=USD curs=bucks", 10, "10 bucks");
+        assertFormatted("0 \u00A4;; curs=bucks curc=USD", 10, "10 bucks"); // Order doesn't mater
+        assertFormatted("0 \u00A4\u00A4;; curc=USD curs=bucks", 10, "10 USD"); // International symbol isn't affected
+        
+        assertFormatted("0.0 \u00A4;; mdec=m", 10.5, "10m5 $");
+        assertFormatted("0.0 kg;; mdec=m", 10.5, "10.5 kg");
+        assertFormatted("0.0 \u00A4;; dec=d", 10.5, "10.5 $");
+        assertFormatted("0.0 kg;; dec=d", 10.5, "10d5 kg");
+        assertFormatted("0.0 \u00A4;; mdec=m dec=d", 10.5, "10m5 $");
+        assertFormatted("0.0 kg;; mdec=m dec=d", 10.5, "10d5 kg");
     }
     
     @Test
@@ -236,11 +257,15 @@ public class ExtendedDecimalFormatTest {
     
 
     private void assertFormatted(String formatString, Object... numberAndExpectedOutput) throws ParseException {
+        assertFormatted(LOC, formatString, numberAndExpectedOutput);
+    }
+    
+    private void assertFormatted(Locale loc, String formatString, Object... numberAndExpectedOutput) throws ParseException {
         if (numberAndExpectedOutput.length % 2 != 0) {
             throw new IllegalArgumentException();
         }
         
-        DecimalFormat df = ExtendedDecimalFormatParser.parse(formatString, LOC);
+        DecimalFormat df = ExtendedDecimalFormatParser.parse(formatString, loc);
         Number num = null;
         for (int i = 0; i < numberAndExpectedOutput.length; i++) {
             if (i % 2 == 0) {


[07/15] incubator-freemarker git commit: Using JDOM 1.0-beta-8 from the Maven Central Repo instead of from the freemarker.org repo.

Posted by dd...@apache.org.
Using JDOM 1.0-beta-8 from the Maven Central Repo instead of from the freemarker.org repo.


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

Branch: refs/heads/2.3
Commit: 2bdd2615cf91bb97246b08dbeddc718a109ca97c
Parents: 41ec864
Author: ddekany <dd...@apache.org>
Authored: Tue Sep 15 23:07:28 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Sep 15 23:07:28 2015 +0200

----------------------------------------------------------------------
 .classpath | 2 +-
 ivy.xml    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2bdd2615/.classpath
----------------------------------------------------------------------
diff --git a/.classpath b/.classpath
index 6ca1ecd..d86821a 100644
--- a/.classpath
+++ b/.classpath
@@ -22,7 +22,7 @@
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/javax.servlet.jsp-2.1.0.v201105211820.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/javax.servlet.jsp.jstl-1.2.0.v201105211821.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/jaxen-1.0-FCS.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jdom-1.0-beta8-dev.jar"/>
+	<classpathentry kind="lib" path="D:/Temp/git_fm/freemarker-2.3-gae/ide-dependencies/jdom-1.0b8.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-continuation-7.6.16.v20140903.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-http-7.6.16.v20140903.jar"/>
 	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-io-7.6.16.v20140903.jar"/>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2bdd2615/ivy.xml
----------------------------------------------------------------------
diff --git a/ivy.xml b/ivy.xml
index e8457f5..f672bef 100644
--- a/ivy.xml
+++ b/ivy.xml
@@ -86,7 +86,7 @@
       <exclude org="xml-apis" module="xml-apis" />
     </dependency>
     <dependency org="dom4j" name="dom4j" rev="1.3" conf="build.base->default" /> <!-- legacy -->
-    <dependency org="org.jdom" name="jdom" rev="1.0-beta8-dev" conf="build.base->default" /> <!-- legacy -->
+    <dependency org="jdom" name="jdom" rev="1.0b8" conf="build.base->default" /> <!-- legacy -->
 
     <dependency org="ant" name="ant" rev="1.6.5" conf="build.base->default">
       <!-- The lowerst supported xml-apis version depends on JDK version; prevent any collosion: -->


[14/15] incubator-freemarker git commit: Proper template error message when DecimalFormat.format throws ArithmeticException.

Posted by dd...@apache.org.
Proper template error message when DecimalFormat.format throws ArithmeticException.


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

Branch: refs/heads/2.3
Commit: 89ec237f42a28ba0f0b31a100b09e3c7c586fda0
Parents: 25f3b82
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 16 19:32:25 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 16 19:32:25 2015 +0200

----------------------------------------------------------------------
 .../java/freemarker/core/JavaTemplateNumberFormat.java   |  7 ++++++-
 .../java/freemarker/core/ExtendedDecimalFormatTest.java  | 11 ++++++++---
 2 files changed, 14 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/89ec237f/src/main/java/freemarker/core/JavaTemplateNumberFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/JavaTemplateNumberFormat.java b/src/main/java/freemarker/core/JavaTemplateNumberFormat.java
index 3c1763c..b34414b 100644
--- a/src/main/java/freemarker/core/JavaTemplateNumberFormat.java
+++ b/src/main/java/freemarker/core/JavaTemplateNumberFormat.java
@@ -52,7 +52,12 @@ final class JavaTemplateNumberFormat extends BackwardCompatibleTemplateNumberFor
 
     @Override
     String format(Number number) throws UnformattableNumberException {
-        return javaNumberFormat.format(number);
+        try {
+            return javaNumberFormat.format(number);
+        } catch (ArithmeticException e) {
+            throw new UnformattableNumberException(
+                    "This format can't format the " + number + " number. Reason: " + e.getMessage(), e);
+        }
     }
 
     public NumberFormat getJavaNumberFormat() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/89ec237f/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 0c5c9f2..d53fc84 100644
--- a/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
+++ b/src/test/java/freemarker/core/ExtendedDecimalFormatTest.java
@@ -278,9 +278,14 @@ public class ExtendedDecimalFormatTest extends TemplateTest {
                 + "<#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");
+        assertErrorContains("${1?string('#E')}",
+                TemplateException.class, "\"#E\"", "format string", "exponential");
+        assertErrorContains("<#setting numberFormat='#E'>${1}",
+                TemplateException.class, "\"#E\"", "format string", "exponential");
+        assertErrorContains("<#setting numberFormat=';;foo=bar'>${1}",
+                TemplateException.class, "\"foo\"", "supported");
+        assertErrorContains("<#setting numberFormat='0;;rnd=un'>${1.5}",
+                TemplateException.class, "can't format", "1.5", "UNNECESSARY");
     }
 
     private void assertFormatted(String formatString, Object... numberAndExpectedOutput) throws ParseException {