freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [1/2] incubator-freemarker git commit: Added freemarker.core.AliasTemplateNumberFormat and AliasTemplateDateFormat, which can be used to create custom formats that are aliases to other formats. For example, instead of writing ${n?string["0.00"]} again an
Date Wed, 09 Sep 2015 23:04:56 GMT
Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3 dfe0c0978 -> b6d84a082


Added freemarker.core.AliasTemplateNumberFormat and AliasTemplateDateFormat, which can be
used to create custom formats that are aliases to other formats. For example, instead of writing
${n?string["0.00"]} again and again, you can define the custom format "price" as the alias
to the format string "0.00" in the configuration, and then use ${n?string.@price}. Thus, you
can control at a central place how prices look. Furthermore, the alias can chose a different
target format string depending on the current locale; this is especially useful for dates,
where conventions can significantly differ in different countries.


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

Branch: refs/heads/2.3
Commit: 3fab33d91e6aa5e459ffb16e0bd155c5858c1224
Parents: ef18a73
Author: ddekany <ddekany@apache.org>
Authored: Thu Sep 10 01:01:41 2015 +0200
Committer: ddekany <ddekany@apache.org>
Committed: Thu Sep 10 01:01:41 2015 +0200

----------------------------------------------------------------------
 ...AliasTargetTemplateValueFormatException.java | 36 ++++++++
 .../core/AliasTemplateDateFormatFactory.java    | 91 ++++++++++++++++++++
 .../core/AliasTemplateNumberFormatFactory.java  | 90 +++++++++++++++++++
 .../core/TemplateDateFormatFactory.java         |  2 +
 .../core/TemplateNumberFormatFactory.java       |  2 +
 .../java/freemarker/core/_CoreLocaleUtils.java  | 45 ++++++++++
 src/manual/book.xml                             | 35 ++++++++
 .../freemarker/core/CoreLocaleUtilsTest.java    | 72 ++++++++++++++++
 .../java/freemarker/core/DateFormatTest.java    | 49 ++++++++++-
 .../java/freemarker/core/NumberFormatTest.java  | 45 ++++++++++
 10 files changed, 466 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/main/java/freemarker/core/AliasTargetTemplateValueFormatException.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/AliasTargetTemplateValueFormatException.java b/src/main/java/freemarker/core/AliasTargetTemplateValueFormatException.java
new file mode 100644
index 0000000..bf37e66
--- /dev/null
+++ b/src/main/java/freemarker/core/AliasTargetTemplateValueFormatException.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * Can't create a template format that the template format refers to (typically thrown by
alias template formats).
+ * 
+ * @since 2.3.24
+ */
+class AliasTargetTemplateValueFormatException extends TemplateValueFormatException {
+
+    public AliasTargetTemplateValueFormatException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public AliasTargetTemplateValueFormatException(String message) {
+        super(message);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/main/java/freemarker/core/AliasTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/AliasTemplateDateFormatFactory.java b/src/main/java/freemarker/core/AliasTemplateDateFormatFactory.java
new file mode 100644
index 0000000..b8db181
--- /dev/null
+++ b/src/main/java/freemarker/core/AliasTemplateDateFormatFactory.java
@@ -0,0 +1,91 @@
+/*
+ * 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.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Creates an alias to another format, so that the format can be referred to with a simple
name in the template, rather
+ * than as a concrete pattern or other kind of format string.
+ * 
+ * @since 2.3.24
+ */
+public final class AliasTemplateDateFormatFactory extends TemplateDateFormatFactory {
+
+    private final String defaultTargetFormatString;
+    private final Map<Locale, String> localizedTargetFormatStrings;
+
+    /**
+     * @param targetFormatString
+     *            The format string this format will be an alias to.
+     */
+    public AliasTemplateDateFormatFactory(String targetFormatString) {
+        this.defaultTargetFormatString = targetFormatString;
+        localizedTargetFormatStrings = null;
+    }
+
+    /**
+     * @param defaultTargetFormatString
+     *            The format string this format will be an alias to if there's no locale-specific
format string for the
+     *            requested locale in {@code localizedTargetFormatStrings}
+     * @param localizedTargetFormatStrings
+     *            Maps {@link Locale}-s to format strings. If the desired locale doesn't
occur in the map, a less
+     *            specific locale is tried, repeatedly until only the language part remains.
For example, if locale is
+     *            {@code new Locale("en", "US", "Linux")}, then these keys will be attempted
untol a match is found, in
+     *            this order: {@code new Locale("en", "US", "Linux")}, {@code new Locale("en",
"US")},
+     *            {@code new Locale("en")}. If there's still no matching key, the value of
the
+     *            {@code targetFormatString} will be used.
+     */
+    public AliasTemplateDateFormatFactory(
+            String defaultTargetFormatString, Map<Locale, String> localizedTargetFormatStrings)
{
+        this.defaultTargetFormatString = defaultTargetFormatString;
+        this.localizedTargetFormatStrings = localizedTargetFormatStrings;
+    }
+    
+    @Override
+    public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone,
boolean zonelessInput,
+            Environment env) throws TemplateValueFormatException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        try {
+            String targetFormatString;
+            if (localizedTargetFormatStrings != null) {
+                Locale lookupLocale = locale;
+                targetFormatString = localizedTargetFormatStrings.get(lookupLocale);
+                while (targetFormatString == null
+                        && (lookupLocale = _CoreLocaleUtils.getLessSpecificLocale(lookupLocale))
!= null) {
+                    targetFormatString = localizedTargetFormatStrings.get(lookupLocale);
+                }
+            } else {
+                targetFormatString = null;
+            }
+            if (targetFormatString == null) {
+                targetFormatString = this.defaultTargetFormatString;
+            }
+            return env.getTemplateDateFormat(targetFormatString, dateType, locale, timeZone,
zonelessInput);
+        } catch (TemplateValueFormatException e) {
+            throw new AliasTargetTemplateValueFormatException("Failed to create format based
on target format string,  "
+                    + StringUtil.jQuote(params) + ". Reason given: " + e.getMessage(), e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/main/java/freemarker/core/AliasTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/AliasTemplateNumberFormatFactory.java b/src/main/java/freemarker/core/AliasTemplateNumberFormatFactory.java
new file mode 100644
index 0000000..69d3ece
--- /dev/null
+++ b/src/main/java/freemarker/core/AliasTemplateNumberFormatFactory.java
@@ -0,0 +1,90 @@
+/*
+ * 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.util.Locale;
+import java.util.Map;
+
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Creates an alias to another format, so that the format can be referred to with a simple
name in the template, rather
+ * than as a concrete pattern or other kind of format string.
+ * 
+ * @since 2.3.24
+ */
+public final class AliasTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    private final String defaultTargetFormatString;
+    private final Map<Locale, String> localizedTargetFormatStrings;
+
+    /**
+     * @param targetFormatString
+     *            The format string this format will be an alias to
+     */
+    public AliasTemplateNumberFormatFactory(String targetFormatString) {
+        this.defaultTargetFormatString = targetFormatString;
+        localizedTargetFormatStrings = null;
+    }
+
+    /**
+     * @param defaultTargetFormatString
+     *            The format string this format will be an alias to if there's no locale-specific
format string for the
+     *            requested locale in {@code localizedTargetFormatStrings}
+     * @param localizedTargetFormatStrings
+     *            Maps {@link Locale}-s to format strings. If the desired locale doesn't
occur in the map, a less
+     *            specific locale is tried, repeatedly until only the language part remains.
For example, if locale is
+     *            {@code new Locale("en", "US", "Linux")}, then these keys will be attempted
untol a match is found, in
+     *            this order: {@code new Locale("en", "US", "Linux")}, {@code new Locale("en",
"US")},
+     *            {@code new Locale("en")}. If there's still no matching key, the value of
the
+     *            {@code targetFormatString} will be used.
+     */
+    public AliasTemplateNumberFormatFactory(
+            String defaultTargetFormatString, Map<Locale, String> localizedTargetFormatStrings)
{
+        this.defaultTargetFormatString = defaultTargetFormatString;
+        this.localizedTargetFormatStrings = localizedTargetFormatStrings;
+    }
+
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws TemplateValueFormatException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        try {
+            String targetFormatString;
+            if (localizedTargetFormatStrings != null) {
+                Locale lookupLocale = locale;
+                targetFormatString = localizedTargetFormatStrings.get(lookupLocale);
+                while (targetFormatString == null
+                        && (lookupLocale = _CoreLocaleUtils.getLessSpecificLocale(lookupLocale))
!= null) {
+                    targetFormatString = localizedTargetFormatStrings.get(lookupLocale);
+                }
+            } else {
+                targetFormatString = null;
+            }
+            if (targetFormatString == null) {
+                targetFormatString = this.defaultTargetFormatString;
+            }
+            return env.getTemplateNumberFormat(targetFormatString, locale);
+        } catch (TemplateValueFormatException e) {
+            throw new AliasTargetTemplateValueFormatException("Failed to create format based
on target format string,  "
+                    + StringUtil.jQuote(params) + ". Reason given: " + e.getMessage(), e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/main/java/freemarker/core/TemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateDateFormatFactory.java b/src/main/java/freemarker/core/TemplateDateFormatFactory.java
index cf7aad5..23b88e0 100644
--- a/src/main/java/freemarker/core/TemplateDateFormatFactory.java
+++ b/src/main/java/freemarker/core/TemplateDateFormatFactory.java
@@ -30,6 +30,8 @@ import freemarker.template.TemplateDateModel;
  * Factory for a certain kind of date/time/dateTime formatting ({@link TemplateDateFormat}).
Usually a singleton
  * (one-per-VM or one-per-{@link Configuration}), and so must be thread-safe.
  * 
+ * @see Configurable#setCustomDateFormats(java.util.Map)
+ * 
  * @since 2.3.24
  */
 public abstract class TemplateDateFormatFactory extends TemplateValueFormatFactory {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateNumberFormatFactory.java b/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
index 90e84e0..9a404d3 100644
--- a/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
+++ b/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
@@ -26,6 +26,8 @@ import freemarker.template.Configuration;
  * Factory for a certain kind of number formatting ({@link TemplateNumberFormat}). Usually
a singleton (one-per-VM or
  * one-per-{@link Configuration}), and so must be thread-safe.
  * 
+ * @see Configurable#setCustomNumberFormats(java.util.Map)
+ * 
  * @since 2.3.24
  */
 public abstract class TemplateNumberFormatFactory extends TemplateValueFormatFactory {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/main/java/freemarker/core/_CoreLocaleUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_CoreLocaleUtils.java b/src/main/java/freemarker/core/_CoreLocaleUtils.java
new file mode 100644
index 0000000..6ddbe9c
--- /dev/null
+++ b/src/main/java/freemarker/core/_CoreLocaleUtils.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.util.Locale;
+
+/**
+ * For internal use only; don't depend on this, there's no backward compatibility guarantee
at all!
+ * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker
packages can
+ * access things inside this package that users shouldn't. 
+ */ 
+public class _CoreLocaleUtils {
+
+    /**
+     * Returns a locale that's one less specific, or {@code null} if there's no less specific
locale.
+     */
+    public static Locale getLessSpecificLocale(Locale locale) {
+        String country = locale.getCountry();
+        if (locale.getVariant().length() != 0) {
+            String language = locale.getLanguage();
+            return country != null ? new Locale(language, country) : new Locale(language);
+        }
+        if (country.length() != 0) {
+            return new Locale(locale.getLanguage());
+        }
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/manual/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/book.xml b/src/manual/book.xml
index 5524684..f50afda 100644
--- a/src/manual/book.xml
+++ b/src/manual/book.xml
@@ -25677,6 +25677,24 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 </listitem>
 
                 <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>${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 configuration, and then use
+                  <literal>${n?string.@price}</literal>. Thus, you can control
+                  at a central place how prices look. Furthermore, the alias
+                  can chose a different target format string depending on the
+                  current locale; this is especially useful for dates, where
+                  conventions can significantly differ in different
+                  countries.</para>
+                </listitem>
+
+                <listitem>
                   <para>The internal format object caching architecture has
                   been reworked, so that it can handle custom formats too. But
                   this reworking also fixes some bottlenecks under highly
@@ -25829,6 +25847,23 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <literal>TemplateValueFormatException</literal>, which is now
               what the methods of said classes throw (mostly).</para>
             </listitem>
+
+            <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>${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
+              configuration, and then use
+              <literal>${n?string.@price}</literal>. Thus, you can control at
+              a central place how prices look. Furthermore, the alias can
+              chose a different target format string depending on the current
+              locale; this is especially useful for dates, where conventions
+              can significantly differ in different countries.</para>
+            </listitem>
           </itemizedlist>
         </section>
       </section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/test/java/freemarker/core/CoreLocaleUtilsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/CoreLocaleUtilsTest.java b/src/test/java/freemarker/core/CoreLocaleUtilsTest.java
new file mode 100644
index 0000000..144138e
--- /dev/null
+++ b/src/test/java/freemarker/core/CoreLocaleUtilsTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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 org.junit.Assert.*;
+
+import java.util.Locale;
+
+import org.junit.Test;
+
+public class CoreLocaleUtilsTest {
+
+    @Test
+    public void testGetLessSpecificLocale() {
+        Locale locale;
+        
+        locale = new Locale("ru", "RU", "Linux");
+        assertEquals("ru_RU_Linux", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertEquals("ru_RU", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertEquals("ru", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertNull(locale);
+        
+        locale = new Locale("ch", "CH");
+        assertEquals("ch_CH", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertEquals("ch", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertNull(locale);
+        
+        locale = new Locale("ja");
+        assertEquals("ja", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertNull(locale);
+
+        locale = new Locale("ja", "", "");
+        assertEquals("ja", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertNull(locale);
+        
+        locale = new Locale("");
+        assertEquals("", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertNull(locale);
+        
+        locale = new Locale("hu", "", "Linux");
+        assertEquals("hu__Linux", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertEquals("hu", locale.toString());
+        locale = _CoreLocaleUtils.getLessSpecificLocale(locale);
+        assertNull(locale);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/test/java/freemarker/core/DateFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/DateFormatTest.java b/src/test/java/freemarker/core/DateFormatTest.java
index 4b6d996..e421189 100644
--- a/src/test/java/freemarker/core/DateFormatTest.java
+++ b/src/test/java/freemarker/core/DateFormatTest.java
@@ -32,6 +32,8 @@ import org.junit.Test;
 
 import com.google.common.collect.ImmutableMap;
 
+import freemarker.cache.ConditionalTemplateConfigurerFactory;
+import freemarker.cache.FileNameGlobMatcher;
 import freemarker.template.Configuration;
 import freemarker.template.SimpleDate;
 import freemarker.template.Template;
@@ -39,7 +41,6 @@ import freemarker.template.TemplateDateModel;
 import freemarker.template.TemplateModelException;
 import freemarker.test.TemplateTest;
 
-@SuppressWarnings("boxing")
 public class DateFormatTest extends TemplateTest {
     
     /** 2015-09-06T12:00:00Z */
@@ -304,6 +305,52 @@ public class DateFormatTest extends TemplateTest {
         assertErrorContains("${d?time}", "\"time_format\"", "[wrong t]");
     }
     
+    @Test
+    public void testAlieses() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.setCustomDateFormats(ImmutableMap.of(
+                "d", new AliasTemplateDateFormatFactory("yyyy-MMM-dd"),
+                "m", new AliasTemplateDateFormatFactory("yyyy-MMM"),
+                "epoch", EpochMillisTemplateDateFormatFactory.INSTANCE));
+        
+        TemplateConfigurer tc = new TemplateConfigurer();
+        tc.setCustomDateFormats(ImmutableMap.of(
+                "m", new AliasTemplateDateFormatFactory("yyyy-MMMM"),
+                "i", new AliasTemplateDateFormatFactory("@epoch")));
+        cfg.setTemplateConfigurers(new ConditionalTemplateConfigurerFactory(new FileNameGlobMatcher("*2*"),
tc));
+        
+        addToDataModel("d", TM);
+        String commonFtl = "${d?string.@d} ${d?string.@m} "
+                + "<#setting locale='fr_FR'>${d?string.@m} "
+                + "<#attempt>${d?string.@i}<#recover>E</#attempt>";
+        addTemplate("t1.ftl", commonFtl);
+        addTemplate("t2.ftl", commonFtl);
+        
+        // 2015-09-06T12:00:00Z
+        assertOutputForNamed("t1.ftl", "2015-Sep-06 2015-Sep 2015-sept. E");
+        assertOutputForNamed("t2.ftl", "2015-Sep-06 2015-September 2015-septembre " + T);
+    }
+    
+    @Test
+    public void testAlieses2() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.setCustomDateFormats(ImmutableMap.of(
+                "d", new AliasTemplateDateFormatFactory("yyyy-MMM",
+                        ImmutableMap.of(
+                                new Locale("en"), "yyyy-MMM'_en'",
+                                Locale.UK, "yyyy-MMM'_en_GB'",
+                                Locale.FRANCE, "yyyy-MMM'_fr_FR'"))));
+        cfg.setDateTimeFormat("@d");
+        addToDataModel("d", TM);
+        assertOutput(
+                "<#setting locale='en_US'>${d} "
+                + "<#setting locale='en_GB'>${d} "
+                + "<#setting locale='en_GB_Win'>${d} "
+                + "<#setting locale='fr_FR'>${d} "
+                + "<#setting locale='hu_HU'>${d}",
+                "2015-Sep_en 2015-Sep_en_GB 2015-Sep_en_GB 2015-sept._fr_FR 2015-szept.");
+    }
+    
     private static class MutableTemplateDateModel implements TemplateDateModel {
         
         private Date date;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fab33d9/src/test/java/freemarker/core/NumberFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/NumberFormatTest.java b/src/test/java/freemarker/core/NumberFormatTest.java
index 22fe5c2..e2fc2b2 100644
--- a/src/test/java/freemarker/core/NumberFormatTest.java
+++ b/src/test/java/freemarker/core/NumberFormatTest.java
@@ -30,6 +30,8 @@ import org.junit.Test;
 
 import com.google.common.collect.ImmutableMap;
 
+import freemarker.cache.ConditionalTemplateConfigurerFactory;
+import freemarker.cache.FileNameGlobMatcher;
 import freemarker.template.Configuration;
 import freemarker.template.SimpleNumber;
 import freemarker.template.Template;
@@ -217,6 +219,49 @@ public class NumberFormatTest extends TemplateTest {
         cfg.setNumberFormat("@hex");
         assertOutput("${10}", "@hex10");
     }
+
+    @Test
+    public void testAlieses() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.setCustomNumberFormats(ImmutableMap.of(
+                "f", new AliasTemplateNumberFormatFactory("0.#'f'"),
+                "d", new AliasTemplateNumberFormatFactory("0.0#"),
+                "hex", HexTemplateNumberFormatFactory.INSTANCE));
+        
+        TemplateConfigurer tc = new TemplateConfigurer();
+        tc.setCustomNumberFormats(ImmutableMap.of(
+                "d", new AliasTemplateNumberFormatFactory("0.#'d'"),
+                "i", new AliasTemplateNumberFormatFactory("@hex")));
+        cfg.setTemplateConfigurers(new ConditionalTemplateConfigurerFactory(new FileNameGlobMatcher("*2*"),
tc));
+        
+        String commonFtl = "${1?string.@f} ${1?string.@d} "
+                + "<#setting locale='fr_FR'>${1.5?string.@d} "
+                + "<#attempt>${10?string.@i}<#recover>E</#attempt>";
+        addTemplate("t1.ftl", commonFtl);
+        addTemplate("t2.ftl", commonFtl);
+        
+        assertOutputForNamed("t1.ftl", "1f 1.0 1,5 E");
+        assertOutputForNamed("t2.ftl", "1f 1d 1,5d a");
+    }
+
+    @Test
+    public void testAlieses2() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.setCustomNumberFormats(ImmutableMap.of(
+                "n", new AliasTemplateNumberFormatFactory("0.0",
+                        ImmutableMap.of(
+                                new Locale("en"), "0.0'_en'",
+                                Locale.UK, "0.0'_en_GB'",
+                                Locale.FRANCE, "0.0'_fr_FR'"))));
+        cfg.setNumberFormat("@n");
+        assertOutput(
+                "<#setting locale='en_US'>${1} "
+                + "<#setting locale='en_GB'>${1} "
+                + "<#setting locale='en_GB_Win'>${1} "
+                + "<#setting locale='fr_FR'>${1} "
+                + "<#setting locale='hu_HU'>${1}",
+                "1.0_en 1.0_en_GB 1.0_en_GB 1,0_fr_FR 1,0");
+    }
     
     private static class MutableTemplateNumberModel implements TemplateNumberModel {
         


Mime
View raw message