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 2016/12/04 23:49:51 UTC

[1/2] incubator-freemarker git commit: Utilizing Java 5 generics at some places where it doesn't break backward compatibility.

Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3-gae c253e33d2 -> 496ddfbc0


Utilizing Java 5 generics at some places where it doesn't break backward compatibility.


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

Branch: refs/heads/2.3-gae
Commit: ed403c83cb0acd0b221ecc6a1daa1ccd3597c291
Parents: c253e33
Author: ddekany <dd...@apache.org>
Authored: Sun Dec 4 21:48:42 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 4 21:57:29 2016 +0100

----------------------------------------------------------------------
 .../test/templatesuite/TemplateTestCase.java    | 45 +++++++++++---------
 .../test/templatesuite/TemplateTestSuite.java   |  2 +-
 2 files changed, 25 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ed403c83/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
index 9e9b4ff..dfac6b3 100644
--- a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
+++ b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
@@ -52,6 +52,7 @@ import com.google.common.collect.ImmutableSet;
 import freemarker.cache.FileTemplateLoader;
 import freemarker.core.ASTPrinter;
 import freemarker.ext.beans.BeansWrapper;
+import freemarker.ext.beans.BeansWrapperBuilder;
 import freemarker.ext.beans.BooleanModel;
 import freemarker.ext.beans.Java7MembersOnlyBeansWrapper;
 import freemarker.ext.beans.ResourceBundleModel;
@@ -117,7 +118,7 @@ public class TemplateTestCase extends FileTestCase {
     private final boolean noOutput;
     
     private final Configuration conf;
-    private final HashMap dataModel = new HashMap();
+    private final HashMap<String, Object> dataModel = new HashMap<String, Object>();
     
     public TemplateTestCase(String testName, String simpleTestName, String templateName, String expectedFileName, boolean noOutput,
             Version incompatibleImprovements) {
@@ -181,6 +182,8 @@ public class TemplateTestCase extends FileTestCase {
         conf.setTemplateLoader(new CopyrightCommentRemoverTemplateLoader(
                 new FileTemplateLoader(new File(getTestClassDirectory(), "templates"))));
         
+        BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_0).build();
+        
         dataModel.put(ASSERT_VAR_NAME, AssertDirective.INSTANCE);
         dataModel.put(ASSERT_EQUALS_VAR_NAME, AssertEqualsDirective.INSTANCE);
         dataModel.put(ASSERT_FAILS_VAR_NAME, AssertFailsDirective.INSTANCE);
@@ -239,7 +242,7 @@ public class TemplateTestCase extends FileTestCase {
         } else if (simpleTestName.equals("beans")) {
             dataModel.put("array", new String[] { "array-0", "array-1"});
             dataModel.put("list", Arrays.asList(new String[] { "list-0", "list-1", "list-2"}));
-            Map tmap = new HashMap();
+            Map<Object, Object> tmap = new HashMap<Object, Object>();
             tmap.put("key", "value");
             Object objKey = new Object();
             tmap.put(objKey, "objValue");
@@ -248,8 +251,8 @@ public class TemplateTestCase extends FileTestCase {
             dataModel.put("obj", new freemarker.test.templatesuite.models.BeanTestClass());
             dataModel.put("resourceBundle", new ResourceBundleModel(ResourceBundle.getBundle("freemarker.test.templatesuite.models.BeansTestResources"), BeansWrapper.getDefaultInstance()));
             dataModel.put("date", new GregorianCalendar(1974, 10, 14).getTime());
-            dataModel.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
-            dataModel.put("enums", BeansWrapper.getDefaultInstance().getEnumModels());
+            dataModel.put("statics", beansWrapper.getStaticModels());
+            dataModel.put("enums", beansWrapper.getEnumModels());
         } else if (simpleTestName.equals("boolean")) {
             dataModel.put( "boolean1", TemplateBooleanModel.FALSE);
             dataModel.put( "boolean2", TemplateBooleanModel.TRUE);
@@ -290,23 +293,23 @@ public class TemplateTestCase extends FileTestCase {
             dataModel.put("bigDecimal", new SimpleNumber(java.math.BigDecimal.valueOf(1)));
             dataModel.put("bigDecimal2", new SimpleNumber(java.math.BigDecimal.valueOf(1, 16)));
         } else if (simpleTestName.equals("simplehash-char-key")) {
-            HashMap mStringC = new HashMap();
+            HashMap<String, String> mStringC = new HashMap<String, String>();
             mStringC.put("c", "string");
             dataModel.put("mStringC", mStringC);
             
-            HashMap mStringCNull = new HashMap();
+            HashMap<String, String> mStringCNull = new HashMap<String, String>();
             mStringCNull.put("c", null);
             dataModel.put("mStringCNull", mStringCNull);
             
-            HashMap mCharC = new HashMap();
+            HashMap<Character, String> mCharC = new HashMap<Character, String>();
             mCharC.put(Character.valueOf('c'), "char");
             dataModel.put("mCharC", mCharC);
             
-            HashMap mCharCNull = new HashMap();
+            HashMap<String, String> mCharCNull = new HashMap<String, String>();
             mCharCNull.put("c", null);
             dataModel.put("mCharCNull", mCharCNull);
             
-            HashMap mMixed = new HashMap();
+            HashMap<Object, String> mMixed = new HashMap<Object, String>();
             mMixed.put(Character.valueOf('c'), "char");
             mMixed.put("s", "string");
             mMixed.put("s2", "string2");
@@ -326,8 +329,8 @@ public class TemplateTestCase extends FileTestCase {
         } else if (simpleTestName.startsWith("type-builtins")) {
             dataModel.put("testmethod", new TestMethod());
             dataModel.put("testnode", new TestNode());
-            dataModel.put("testcollection", new SimpleCollection(new ArrayList()));
-            dataModel.put("testcollectionEx", DefaultNonListCollectionAdapter.adapt(new HashSet(), null));
+            dataModel.put("testcollection", new SimpleCollection(new ArrayList<Object>()));
+            dataModel.put("testcollectionEx", DefaultNonListCollectionAdapter.adapt(new HashSet<Object>(), null));
             dataModel.put("bean", new TestBean());
         } else if (simpleTestName.equals("date-type-builtins")) {
             GregorianCalendar cal = new GregorianCalendar(2003, 4 - 1, 5, 6, 7, 8);
@@ -369,19 +372,19 @@ public class TemplateTestCase extends FileTestCase {
             NodeModel nm = NodeModel.parse(is);
             dataModel.put("doc", nm);
         } else if (simpleTestName.startsWith("sequence-builtins")) {
-            Set abcSet = new TreeSet();
+            Set<String> abcSet = new TreeSet<String>();
             abcSet.add("a");
             abcSet.add("b");
             abcSet.add("c");
             dataModel.put("abcSet", abcSet);
             
-            List listWithNull = new ArrayList();
+            List<String> listWithNull = new ArrayList<String>();
             listWithNull.add("a");
             listWithNull.add(null);
             listWithNull.add("c");
             dataModel.put("listWithNull", listWithNull);
             
-            List listWithNullsOnly = new ArrayList();
+            List<String> listWithNullsOnly = new ArrayList<String>();
             listWithNull.add(null);
             listWithNull.add(null);
             listWithNull.add(null);
@@ -389,7 +392,7 @@ public class TemplateTestCase extends FileTestCase {
             
             dataModel.put("abcCollection", new SimpleCollection(abcSet));
             
-            Set set = new HashSet();
+            Set<String> set = new HashSet<String>();
             set.add("a");
             set.add("b");
             set.add("c");
@@ -430,9 +433,9 @@ public class TemplateTestCase extends FileTestCase {
             dataModel.put("bdp", BigDecimal.valueOf(0.05));
           } else if (simpleTestName.startsWith("classic-compatible")) {
             dataModel.put("array", new String[] { "a", "b", "c" });
-            dataModel.put("beansArray", new BeansWrapper().wrap(new String[] { "a", "b", "c" }));
-            dataModel.put("beanTrue", new BeansWrapper().wrap(Boolean.TRUE));
-            dataModel.put("beanFalse", new BeansWrapper().wrap(Boolean.FALSE));
+            dataModel.put("beansArray", beansWrapper.wrap(new String[] { "a", "b", "c" }));
+            dataModel.put("beanTrue", beansWrapper.wrap(Boolean.TRUE));
+            dataModel.put("beanFalse", beansWrapper.wrap(Boolean.FALSE));
         } else if (simpleTestName.startsWith("overloaded-methods-2-")) {
             dataModel.put("obj", new OverloadedMethods2());
             final boolean dow = conf.getObjectWrapper() instanceof DefaultObjectWrapper;
@@ -499,7 +502,7 @@ public class TemplateTestCase extends FileTestCase {
     }
     
     static class TestMethod implements TemplateMethodModel {
-      public Object exec(java.util.List arguments) {
+      public Object exec(List arguments) {
           return "x";
       }
     }
@@ -528,14 +531,14 @@ public class TemplateTestCase extends FileTestCase {
     }
 
    public Object getTestMapBean() {
-        Map testBean = new TestMapBean();
+        Map<String, Object> testBean = new TestMapBean();
         testBean.put("name", "Chris");
         testBean.put("location", "San Francisco");
         testBean.put("age", Integer.valueOf(27));
         return testBean;
     }
 
-    public static class TestMapBean extends HashMap {
+    public static class TestMapBean extends HashMap<String, Object> {
         public String getName() {
             return "Christopher";
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ed403c83/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java b/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
index dd0a74c..2ba6dac 100644
--- a/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
+++ b/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
@@ -82,7 +82,7 @@ public class TemplateTestSuite extends TestSuite {
     public static final String INCOMPATIBLE_IMPROVEMENTS_PROPERTY_NAME
             = "freemareker.templateTestSuite.incompatibleImprovements";
     
-    private final Map<String, String> testSuiteSettings = new LinkedHashMap();
+    private final Map<String, String> testSuiteSettings = new LinkedHashMap<String, String>();
 
     private final ArrayList<Version> testSuiteIcis;
 


[2/2] incubator-freemarker git commit: FREEMARKER-42: ?first now works with FTL collections (things that can be listed but doesn't support getting items by index), not only with sequences. The practical importance of this is that ?first now always works

Posted by dd...@apache.org.
FREEMARKER-42: ?first now works with FTL collections (things that can be listed but doesn't support getting items by index), not only with sequences. The practical importance of this is that ?first now always works on Java Set-s (which is useful for Set-s with well defined ordering), while earlier it has failed depending on the object_wrapper configuration setting.


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

Branch: refs/heads/2.3-gae
Commit: 496ddfbc08c6d3242ab5c31694db152d9c1e4c58
Parents: ed403c8
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 5 00:49:38 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 5 00:49:38 2016 +0100

----------------------------------------------------------------------
 .../freemarker/core/BuiltInsForSequences.java   | 33 ++++++++++--
 src/manual/en_US/book.xml                       | 57 ++++++++++++++++++--
 .../test/templatesuite/TemplateTestCase.java    |  1 +
 .../expected/sequence-builtins.txt              |  7 +++
 .../templates/sequence-builtins.ftl             |  8 ++-
 5 files changed, 98 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/main/java/freemarker/core/BuiltInsForSequences.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltInsForSequences.java b/src/main/java/freemarker/core/BuiltInsForSequences.java
index a12d274..d56a95f 100644
--- a/src/main/java/freemarker/core/BuiltInsForSequences.java
+++ b/src/main/java/freemarker/core/BuiltInsForSequences.java
@@ -138,15 +138,40 @@ class BuiltInsForSequences {
         
     }
     
-    static class firstBI extends BuiltInForSequence {
+    static class firstBI extends BuiltIn {
+        
         @Override
-        TemplateModel calculateResult(TemplateSequenceModel tsm)
+        TemplateModel _eval(Environment env)
+                throws TemplateException {
+            TemplateModel model = target.eval(env);
+            // In 2.3.x only, we prefer TemplateSequenceModel for
+            // backward compatibility. In 2.4.x, we prefer TemplateCollectionModel. 
+            if (model instanceof TemplateSequenceModel && !isBuggySeqButGoodCollection(model)) {
+                return calculateResultForSequence((TemplateSequenceModel) model);
+            } else if (model instanceof TemplateCollectionModel) {
+                return calculateResultForColletion((TemplateCollectionModel) model);
+            } else {
+                throw new NonSequenceOrCollectionException(target, model, env);
+            }
+        }        
+        
+        private TemplateModel calculateResultForSequence(TemplateSequenceModel seq)
         throws TemplateModelException {
-            if (tsm.size() == 0) {
+            if (seq.size() == 0) {
+                return null;
+            }
+            return seq.get(0);
+        }
+        
+        private TemplateModel calculateResultForColletion(TemplateCollectionModel coll)
+        throws TemplateModelException {
+            TemplateModelIterator iter = coll.iterator();
+            if (!iter.hasNext()) {
                 return null;
             }
-            return tsm.get(0);
+            return iter.next();
         }
+        
     }
 
     static class joinBI extends BuiltIn {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index e592d47..4adf154 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -30,7 +30,7 @@
 
     <titleabbrev>Manual</titleabbrev>
 
-    <productname>Freemarker 2.3.25</productname>
+    <productname>Freemarker 2.3.26</productname>
   </info>
 
   <preface role="index.html" xml:id="preface">
@@ -16416,8 +16416,19 @@ N
             <primary>first built-in</primary>
           </indexterm>
 
-          <para>The first subvariable of the sequence. Template processing
-          will die with error if the sequence is empty.</para>
+          <para>Returns the first item of the sequence. Thus
+          <literal><replaceable>value</replaceable>?first</literal> is the
+          same as <literal><replaceable>value</replaceable>[0]</literal>,
+          except that, since FreeMarker 2.3.26,
+          <literal><replaceable>value</replaceable>?first</literal> also works
+          if <literal><replaceable>value</replaceable></literal> doesn't
+          support getting items with numerical index, but still supports to be
+          listed (i.e., with FTL collection values).</para>
+
+          <para>If the sequence or collection is empty, the result will be a
+          missing value (as in
+          <literal><replaceable>empty</replaceable>?first!'No item was
+          found'</literal>).</para>
         </section>
 
         <section xml:id="ref_builtin_join">
@@ -26603,6 +26614,46 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
     <appendix xml:id="app_versions">
       <title>Version history</title>
 
+      <section xml:id="versions_2_3_26">
+        <title>2.3.26 (incubating at Apache)</title>
+
+        <para>Release date: FIXME</para>
+
+        <para><emphasis role="bold">This is a stable, final
+        release.</emphasis> The <quote>incubating</quote> suffix is required
+        by the Apache Software Foundation until the project becomes a fully
+        accepted (graduated) Apache project.</para>
+
+        <section>
+          <title>Changes on the FTL side</title>
+
+          <itemizedlist>
+            <listitem>
+              <para>Bug fixed (<link
+              xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-42">FREEMARKER-42</link>):
+              <literal>?first</literal> now works with FTL collections (things
+              that can be listed but doesn't support getting items by index),
+              not only with sequences. The practical importance of this is
+              that <literal>?first</literal> now always works on Java
+              <literal>Set</literal>-s (which is useful for
+              <literal>Set</literal>-s with well defined ordering), while
+              earlier it has failed depending on the
+              <literal>object_wrapper</literal> configuration setting.</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section>
+          <title>Changes on the Java side</title>
+
+          <itemizedlist>
+            <listitem>
+              <para>FIXME</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+      </section>
+
       <section xml:id="versions_2_3_25">
         <title>2.3.25 (incubating at Apache)</title>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
index dfac6b3..24b67f8 100644
--- a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
+++ b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
@@ -377,6 +377,7 @@ public class TemplateTestCase extends FileTestCase {
             abcSet.add("b");
             abcSet.add("c");
             dataModel.put("abcSet", abcSet);
+            dataModel.put("abcSetNonSeq", DefaultNonListCollectionAdapter.adapt(abcSet, beansWrapper));
             
             List<String> listWithNull = new ArrayList<String>();
             listWithNull.add("a");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt b/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
index 664c95b..1201da9 100644
--- a/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
+++ b/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
@@ -395,3 +395,10 @@ Join
 - (empty)
 - a, b, c.
 - a, b, c.
+
+
+Misc
+----
+
+First of set 1: a
+First of set 2: a
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl b/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
index c431048..1586ad9 100644
--- a/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
+++ b/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
@@ -351,4 +351,10 @@ Join
 - ${listWithNullsOnly?join(", ", "(empty)", ".")}
 - ${abcSet?join(", ", "(empty)", ".")}
 - ${abcCollection?join(", ", "(empty)", ".")}
-<@assertFails message="index 1">${['a', [], 'c']?join(", ", "(empty)", ".")}</@>
\ No newline at end of file
+<@assertFails message="index 1">${['a', [], 'c']?join(", ", "(empty)", ".")}</@>
+
+Misc
+----
+
+First of set 1: ${abcSet?first}
+First of set 2: ${abcSetNonSeq?first}
\ No newline at end of file