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 2017/05/16 16:09:16 UTC

[18/19] incubator-freemarker git commit: Moving TemplateTestSuite to freemarker-test-utils, so that it can be used from multiple modules. It had to be generalized for this a bit, as now it has a CoreTemplateTestSuite subclass in freemarker-core-test.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/Listables.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/Listables.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/Listables.java
new file mode 100644
index 0000000..55d06d5
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/Listables.java
@@ -0,0 +1,185 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateCollectionModel;
+import org.apache.freemarker.core.model.TemplateHashModelEx;
+import org.apache.freemarker.core.model.TemplateHashModelEx2;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.WrappingTemplateModel;
+import org.apache.freemarker.core.model.impl.DefaultMapAdapter;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.SimpleCollection;
+import org.apache.freemarker.core.model.impl.SimpleHash;
+
+import com.google.common.collect.ImmutableMap;
+
+@SuppressWarnings("boxing")
+public class Listables {
+    
+    private static final List<Integer> LIST;
+    static {
+        List<Integer> list = new ArrayList<>();
+        list.add(11);
+        list.add(22);
+        list.add(33);
+        LIST = list;
+    }
+
+    private static final List<Integer> LINKED_LIST;
+    static {
+        List<Integer> list = new LinkedList<>();
+        list.add(11);
+        list.add(22);
+        list.add(33);
+        LINKED_LIST = list;
+    }
+
+    private static final List<Integer> EMPTY_LINKED_LIST = new LinkedList<>();
+
+    private static final Set<Integer> SET;
+    static {
+        Set<Integer> set = new TreeSet<>();
+        set.add(11);
+        set.add(22);
+        set.add(33);
+        SET = set;
+    }
+    
+    public List<Integer> getList() {
+        return LIST;
+    }
+    
+    public List<Integer> getLinkedList() {
+        return LINKED_LIST;
+    }
+    
+    public Set<Integer> getSet() {
+        return SET;
+    }
+
+    public Iterator<Integer> getIterator() {
+        return SET.iterator();
+    }
+
+    public List<Integer> getEmptyList() {
+        return Collections.emptyList();
+    }
+    
+    public List<Integer> getEmptyLinkedList() {
+        return Collections.emptyList();
+    }
+    
+    public Set<Integer> getEmptySet() {
+        return Collections.emptySet();
+    }
+
+    public Iterator<Integer> getEmptyIterator() {
+        return Collections.<Integer>emptySet().iterator();
+    }
+    
+    public List<TemplateHashModelEx2> getHashEx2s() throws TemplateModelException {
+        Map<Object, Object> map;
+        map = new LinkedHashMap<>();
+        map.put("k1", "v1");
+        map.put(2, "v2");
+        map.put("k3", "v3");
+        map.put(null, "v4");
+        map.put(true, "v5");
+        map.put(false, null);
+        
+        return getMapsWrappedAsEx2(map);
+    }
+
+    public List<? extends TemplateHashModelEx> getEmptyHashes() throws TemplateModelException {
+        List<TemplateHashModelEx> emptyMaps = new ArrayList<>();
+        emptyMaps.addAll(getMapsWrappedAsEx2(Collections.emptyMap()));
+        emptyMaps.add((TemplateHashModelEx) new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build()
+                .wrap(Collections.emptyMap()));
+        return emptyMaps;
+    }
+    
+    /**
+     * Returns the map wrapped on various ways.
+     */
+    private List<TemplateHashModelEx2> getMapsWrappedAsEx2(Map<?, ?> map) throws TemplateModelException {
+        List<TemplateHashModelEx2> maps = new ArrayList<>();
+        
+        DefaultObjectWrapper ow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+        maps.add(new SimpleHash(map, ow));
+        maps.add((DefaultMapAdapter) ow.wrap(map));
+
+        return maps;
+    }
+    
+    public TemplateHashModelEx getHashNonEx2() {
+        return new NonEx2MapAdapter(ImmutableMap.of("k1", 11, "k2", 22),
+                new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build());
+    }
+    
+    public static class NonEx2MapAdapter extends WrappingTemplateModel implements TemplateHashModelEx {
+
+        private final Map<?, ?> map;
+        
+        public NonEx2MapAdapter(Map<?, ?> map, ObjectWrapper wrapper) {
+            super(wrapper);
+            this.map = map;
+        }
+        
+        @Override
+        public TemplateModel get(String key) throws TemplateModelException {
+            return wrap(map.get(key));
+        }
+        
+        @Override
+        public boolean isEmpty() {
+            return map.isEmpty();
+        }
+        
+        @Override
+        public int size() {
+            return map.size();
+        }
+        
+        @Override
+        public TemplateCollectionModel keys() {
+            return new SimpleCollection(map.keySet(), getObjectWrapper());
+        }
+        
+        @Override
+        public TemplateCollectionModel values() {
+            return new SimpleCollection(map.values(), getObjectWrapper());
+        }
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel1.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel1.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel1.java
new file mode 100644
index 0000000..ce04928
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel1.java
@@ -0,0 +1,116 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.SimpleHash;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+import org.apache.freemarker.core.model.impl.SimpleSequence;
+
+/**
+ * Testcase to see how FreeMarker deals with multiple Template models.
+ */
+public class MultiModel1 implements TemplateHashModel,
+        TemplateSequenceModel, TemplateScalarModel {
+
+    private ObjectWrapper ow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+
+    private TemplateModel m_cSubModel = new MultiModel2();
+    private TemplateModel m_cListHashModel1 = new MultiModel4(ow);
+    private TemplateModel m_cListHashModel2 = new MultiModel5(ow);
+    private TemplateSequenceModel m_cListModel = new SimpleSequence(ow);
+    private TemplateHashModel m_cHashModel = new SimpleHash(ow);
+
+    /** Creates new MultiModel1 */
+    public MultiModel1() {
+        for ( int i = 0; i < 10; i++ ) {
+            ((SimpleSequence) m_cListModel).add( "Model1 value: " + Integer.toString( i ));
+        }
+        ((SimpleSequence) m_cListModel).add( new MultiModel3() );
+        ((SimpleHash) m_cHashModel).put( "nested", new MultiModel3() );
+    }
+
+    /**
+     * Gets a <tt>TemplateModel</tt> from the hash.
+     *
+     * @param key the name by which the <tt>TemplateModel</tt>
+     * is identified in the template.
+     * @return the <tt>TemplateModel</tt> referred to by the key,
+     * or null if not found.
+     */
+    @Override
+    public TemplateModel get(String key) {
+        if ( key.equals( "model2" )) {
+            return m_cSubModel;
+        } else if ( key.equals( "modellist" )) {
+            return m_cListModel;
+        } else if ( key.equals( "selftest" )) {
+            return new SimpleScalar( "Selftest of a hash from MultiModel1" );
+        } else if ( key.equals( "one" )) {
+            return m_cListHashModel1;
+        } else if ( key.equals( "two" )) {
+            return m_cListHashModel2;
+        } else if ( key.equals( "size" )) {
+            return new SimpleScalar( "Nasty!" );
+        } else if ( key.equals( "nesting1" )) {
+            return m_cHashModel;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return true if this object is empty.
+     */
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    /**
+     * @return the specified index in the list
+     */
+    @Override
+    public TemplateModel get(int i) throws TemplateModelException {
+        return m_cListModel.get( i );
+    }
+
+    /**
+     * Returns the scalar's value as a String.
+     *
+     * @return the String value of this scalar.
+     */
+    @Override
+    public String getAsString() {
+        return "MultiModel1 as a string!";
+    }
+
+    @Override
+    public int size() throws TemplateModelException {
+        return m_cListModel.size();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel2.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel2.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel2.java
new file mode 100644
index 0000000..e264936
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel2.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * Testcase to see how FreeMarker deals with multiple Template models.
+ */
+public class MultiModel2 implements TemplateScalarModel, TemplateMethodModel {
+
+    /**
+     * Returns the scalar's value as a String.
+     *
+     * @return the String value of this scalar.
+     */
+    @Override
+    public String getAsString() {
+        return "Model2 is alive!";
+    }
+
+    /**
+     * Executes a method call.
+     *
+     * @param arguments a <tt>List</tt> of <tt>String</tt> objects containing the values
+     * of the arguments passed to the method.
+     * @return the <tt>TemplateModel</tt> produced by the method, or null.
+     */
+    @Override
+    public Object exec(List arguments) {
+        StringBuilder  aResults = new StringBuilder( "Arguments are:<br />" );
+        Iterator    iList = arguments.iterator();
+
+        while ( iList.hasNext() ) {
+            aResults.append( (String) iList.next() );
+            aResults.append( "<br />" );
+        }
+
+        return new SimpleScalar( aResults.toString() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel3.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel3.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel3.java
new file mode 100644
index 0000000..b84150c
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel3.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * Testcase to see how FreeMarker deals with multiple Template models.
+ */
+public class MultiModel3 implements TemplateScalarModel, TemplateHashModel {
+
+    /**
+     * Returns the scalar's value as a String.
+     *
+     * @return the String value of this scalar.
+     */
+    @Override
+    public String getAsString() {
+        return "Model3 is alive!";
+    }
+
+    /**
+     * @return true if this object is empty.
+     */
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    /**
+     * Gets a <tt>TemplateModel</tt> from the hash.
+     *
+     * @param key the name by which the <tt>TemplateModel</tt>
+     * is identified in the template.
+     * @return the <tt>TemplateModel</tt> referred to by the key,
+     * or null if not found.
+     */
+    @Override
+    public TemplateModel get(String key) {
+        if ( key.equals( "selftest" )) {
+            return new SimpleScalar( "Selftest from MultiModel3!" );
+        } else if ( key.equals( "message" )) {
+            return new SimpleScalar( "Hello world from MultiModel3!" );
+        } else {
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel4.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel4.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel4.java
new file mode 100644
index 0000000..a5fb8e5
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel4.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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+import org.apache.freemarker.core.model.impl.SimpleSequence;
+
+/**
+ * Testcase to see how FreeMarker deals with multiple Template models.
+ */
+public class MultiModel4 implements TemplateSequenceModel, TemplateHashModel {
+
+    private final SimpleSequence m_cList;
+
+    public MultiModel4(ObjectWrapper ow) {
+        this.m_cList = new SimpleSequence(ow);
+    }
+
+    /**
+     * @return the specified index in the list
+     */
+    @Override
+    public TemplateModel get(int i) throws TemplateModelException {
+        return m_cList.get( i );
+    }
+
+    /**
+     * Gets a <tt>TemplateModel</tt> from the hash.
+     *
+     * @param key the name by which the <tt>TemplateModel</tt>
+     * is identified in the template.
+     * @return the <tt>TemplateModel</tt> referred to by the key,
+     * or null if not found.
+     */
+    @Override
+    public TemplateModel get(String key) {
+        if ( key.equals( "size" )) {
+            return new SimpleScalar( "Key size, not the listSize method." );
+        } else {
+            return null;
+        }
+    }
+
+
+    @Override
+    public int size() {
+        return m_cList.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel5.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel5.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel5.java
new file mode 100644
index 0000000..f08fb8c
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/MultiModel5.java
@@ -0,0 +1,81 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+import org.apache.freemarker.core.model.impl.SimpleSequence;
+
+/**
+ * Testcase to see how FreeMarker deals with multiple Template models.
+ */
+public class MultiModel5 implements TemplateSequenceModel, TemplateHashModel {
+
+    private final SimpleSequence m_cList;
+
+    /** Creates new MultiModel5 */
+    public MultiModel5(ObjectWrapper ow) {
+        this.m_cList = new SimpleSequence(ow);
+        m_cList.add( new SimpleScalar( "Dummy to make list non-empty" ));
+    }
+
+    /**
+     * @return the specified index in the list
+     */
+    @Override
+    public TemplateModel get(int i) throws TemplateModelException {
+        return m_cList.get( i );
+    }
+
+    /**
+     * @return true if this object is empty.
+     */
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    @Override
+    public int size() {
+        return m_cList.size();
+    }
+
+    /**
+     * Gets a <tt>TemplateModel</tt> from the hash.
+     *
+     * @param key the name by which the <tt>TemplateModel</tt>
+     * is identified in the template.
+     * @return the <tt>TemplateModel</tt> referred to by the key,
+     * or null if not found.
+     */
+    @Override
+    public TemplateModel get(String key) {
+        if ( key.equals( "empty" )) {
+            return new SimpleScalar( "Dummy hash value, for test purposes." );
+        } else {
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel.java
new file mode 100644
index 0000000..98ba89f
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateScalarModel;
+
+/**
+ * Testcase to see how FreeMarker's ?new built-in deals with constructors.
+ */
+public class NewTestModel
+implements
+    TemplateScalarModel {
+    private final String string;
+    
+    public NewTestModel() {
+        string = "default constructor";
+    }
+
+    public NewTestModel(String str) {
+        string = str;
+    }
+
+    public NewTestModel(long i) {
+        string = Long.toString(i);
+    }
+
+    public NewTestModel(Object o1, java.io.Serializable o2) {
+        string = o1 + ":" + o2;
+    }
+
+    @Override
+    public String getAsString() {
+        return string;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel2.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel2.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel2.java
new file mode 100644
index 0000000..f715d5c
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NewTestModel2.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateScalarModel;
+
+/**
+ * Testcase to see how FreeMarker's ?new built-in deals with constructors.
+ */
+public class NewTestModel2
+implements
+    TemplateScalarModel {
+    private final String string;
+    
+    public NewTestModel2() {
+        string = "default constructor";
+    }
+
+    public NewTestModel2(String str) {
+        string = str;
+    }
+
+    public NewTestModel2(long i) {
+        string = Long.toString(i);
+    }
+
+    public NewTestModel2(Object o1, java.io.Serializable o2) {
+        string = o1 + ":" + o2;
+    }
+
+    @Override
+    public String getAsString() {
+        return string;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NumberAndStringModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NumberAndStringModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NumberAndStringModel.java
new file mode 100644
index 0000000..cc4eec1
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/NumberAndStringModel.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateNumberModel;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+
+public class NumberAndStringModel implements TemplateNumberModel,
+		TemplateScalarModel {
+	
+	private final String s;
+	
+	public NumberAndStringModel(String s) {
+		super();
+		this.s = s;
+	}
+
+	@Override
+    public String getAsString() throws TemplateModelException {
+		return s;
+	}
+
+	@Override
+    @SuppressWarnings("boxing")
+    public Number getAsNumber() throws TemplateModelException {
+		return s.length();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedConstructor.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedConstructor.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedConstructor.java
new file mode 100644
index 0000000..f8da268
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedConstructor.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+
+public class OverloadedConstructor implements TemplateScalarModel {
+    
+    String value;
+    
+    public OverloadedConstructor(int i) {
+        value = "int " + i;
+    }
+    
+    public OverloadedConstructor(String s) {
+        value = "String " + s;
+    }
+
+    public OverloadedConstructor(CharSequence s) {
+        value = "CharSequence " + s;
+    }
+    
+    @Override
+    public String getAsString() throws TemplateModelException {
+        return value;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods.java
new file mode 100644
index 0000000..4eac8cc
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods.java
@@ -0,0 +1,191 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.freemarker.core.util.FTLUtil;
+
+/**
+ * For testing overloaded method selection.
+ */
+public class OverloadedMethods {
+
+	public String oneArg(Object a1) {
+		return methodCallToStr("oneArg<Object>", a1);
+	}
+
+	public String oneArg(String a1) {
+		return methodCallToStr("oneArg<String>", a1);
+	}
+
+	public String oneArg(Boolean a1) {
+		return methodCallToStr("oneArg<Boolean>", a1);
+	}
+
+	public String oneArg(boolean a1) {
+		return methodCallToStr("oneArg<boolean>", Boolean.valueOf(a1));
+	}
+	
+	public String oneArg(List a1) {
+		return methodCallToStr("oneArg<List>", a1);
+	}
+
+	public String oneArg(Map a1) {
+		return methodCallToStr("oneArg<Map>", a1);
+	}
+
+    public String oneArg2(Map a1) {
+        return methodCallToStr("oneArg2<Map>", a1);
+    }
+
+    public String oneArg2(List a1) {
+        return methodCallToStr("oneArg2<List>", a1);
+    }
+    
+    public String oneArg3(List a1, List a2) {
+        return methodCallToStr("oneArg3<List, List>", a1, a2);
+    }
+
+    public String oneArg3(List a1) {
+        return methodCallToStr("oneArg3<List>", a1);
+    }
+    
+    public String oneArg4(Integer a1) {
+        return methodCallToStr("oneArg4<Integer>", a1);
+    }
+
+    public String oneArg4(int a1) {
+        return methodCallToStr("oneArg4<int>", Integer.valueOf(a1));
+    }
+
+    public String notOverloaded(List a1) {
+        return methodCallToStr("notOverloaded<List>", a1);
+    }
+    
+	public String varargsIssue1(Map a1, List a2) {
+	    return methodCallToStr("varargsIssue1<Map, List>", a1, a2);
+	}
+
+    public String varargsIssue1(Object... a1) {
+        return methodCallToStr("varargsIssue1<Object...>", a1);
+    }
+
+    public String varargsIssue2(String a1, List a2) {
+        return methodCallToStr("varargsIssue2<String, List>", a1, a2);
+    }
+
+    public String varargsIssue2(String a1, Map a2) {
+        return methodCallToStr("varargsIssue2<String, Map>", a1, a2);
+    }
+
+    public String varargsIssue2(Object... a1) {
+        return methodCallToStr("varargsIssue2<Object...>", a1);
+    }
+    
+    public String numberIssue1(int a1) {
+        return methodCallToStr("numberIssue1<int>", a1);
+    }
+    
+    public String numberIssue1(float a1) {
+        return methodCallToStr("numberIssue1<float>", a1);
+    }
+    
+    public String numberIssue2(int a1) {
+        return methodCallToStr("numberIssue2<int>", a1);
+    }
+    
+    public String numberIssue2(BigDecimal a1) {
+        return methodCallToStr("numberIssue2<BigDecimal>", a1);
+    }
+
+    public String numberIssue3(int a1) {
+        return methodCallToStr("numberIssue3<int>", a1);
+    }
+    
+    public String numberIssue3(double a1) {
+        return methodCallToStr("numberIssue3<double>", a1);
+    }
+    
+	private String methodCallToStr(String methodName, Object... args) {
+		StringBuilder sb = new StringBuilder();
+		
+		sb.append(methodName);
+		sb.append('(');
+		boolean hadItems = false;
+		for (Object arg : args) {
+			if (hadItems) sb.append(", ");
+			sb.append(valueToStr(arg));
+			hadItems = true;
+		}
+		sb.append(')');
+		
+		return sb.toString();
+	}
+	
+	private String valueToStr(Object value) {
+		if (value == null) {
+		    return "null";
+		} else if (value instanceof Character) {
+			return "'" + FTLUtil.escapeStringLiteralPart(value.toString()) + "'";
+		} else if (value instanceof String) {
+			return "\"" + FTLUtil.escapeStringLiteralPart((String) value) + "\"";
+		} else if (value instanceof Map) {
+			StringBuilder sb = new StringBuilder(); 
+			sb.append("{");
+			boolean hadItems = false;
+			for (Map.Entry<?, ?> ent : ((Map<?, ?>) value).entrySet()) {
+				if (hadItems) sb.append(", ");
+				sb.append(valueToStr(ent.getKey()));
+				sb.append(": ");
+				sb.append(valueToStr(ent.getValue()));
+				hadItems = true;
+			}
+			sb.append("}");
+			return sb.toString();
+		} else if (value instanceof Collection || value.getClass().isArray()) {
+			StringBuilder sb = new StringBuilder();
+			
+	        if (value.getClass().isArray()) {
+	            value = Arrays.asList(value);
+                sb.append("array");
+	        } else if (value instanceof Set) {
+				sb.append("set");
+			}
+			sb.append("[");
+			boolean hadItems = false;
+			for (Object i : (Collection) value) {
+				if (hadItems) sb.append(", ");
+				sb.append(i);
+				hadItems = true;
+			}
+			sb.append("]");
+			return sb.toString();
+		} else {
+			return value.toString(); 
+		}
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods2.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods2.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods2.java
new file mode 100644
index 0000000..e9084c9
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/OverloadedMethods2.java
@@ -0,0 +1,1110 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import java.io.File;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.model.AdapterTemplateModel;
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateBooleanModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateNumberModel;
+import org.apache.freemarker.core.model.WrapperTemplateModel;
+import org.apache.freemarker.core.model.impl.RationalNumber;
+import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.test.TestUtil;
+
+public class OverloadedMethods2 {
+
+    public String mVarargs(String... a1) {
+        StringBuilder sb = new StringBuilder();
+        for (String s : a1) {
+            sb.append(s);
+        }
+        return "mVarargs(String... a1 = " + sb + ")";
+    }
+    
+    public BigInteger bigInteger(BigDecimal n) {
+        return n.toBigInteger();
+    }
+
+    public RationalNumber rational(int a, int b) {
+        return new RationalNumber(a, b);
+    }
+    
+    public String mVarargs(File a1, String... a2) {
+        return "mVarargs(File a1, String... a2)";
+    }
+
+    public NumberAndStringModel getNnS(String s) {
+        return new NumberAndStringModel(s);
+    }
+    
+    public String mNull1(String a1) {
+        return "mNull1(String a1 = " + a1 + ")";
+    }
+
+    public String mNull1(int a1) {
+        return "mNull1(int a1 = " + a1 + ")";
+    }
+    
+    public String mNull2(String a1) {
+        return "mNull2(String a1 = " + a1 + ")";
+    }
+    
+    public String mNull2(Object a1) {
+        return "mNull2(Object a1 = " + a1 + ")";
+    }
+    
+    public String mSpecificity(Object a1, String a2) {
+        return "mSpecificity(Object a1, String a2)";
+    }
+    
+    public String mSpecificity(String a1, Object a2) {
+        return "mSpecificity(String a1, Object a2)";
+    }
+    
+    public String mChar(char a1) {
+        return "mChar(char a1 = " + a1 + ")";
+    }
+    
+    public String mChar(Character a1) {
+        return "mChar(Character a1 = " + a1 + ")";
+    }
+    
+    public String mBoolean(boolean a1) {
+        return "mBoolean(boolean a1 = " + a1 + ")";
+    }
+    
+    public String mBoolean(Boolean a1) {
+        return "mBoolean(Boolean a1 = " + a1 + ")";
+    }
+
+    public int mIntNonOverloaded(int a1) {
+        return a1;
+    }
+
+    public String mIntPrimVSBoxed(int a1) {
+        return "mIntPrimVSBoxed(int a1 = " + a1 + ")";
+    }
+    
+    public String mIntPrimVSBoxed(Integer a1) {
+        return "mIntPrimVSBoxed(Integer a1 = " + a1 + ")";
+    }
+
+    public String mNumPrimVSPrim(short a1) {
+        return "mNumPrimVSPrim(short a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimVSPrim(long a1) {
+        return "mNumPrimVSPrim(long a1 = " + a1 + ")";
+    }
+
+    public String mNumBoxedVSBoxed(Short a1) {
+        return "mNumBoxedVSBoxed(Short a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedVSBoxed(Long a1) {
+        return "mNumBoxedVSBoxed(Long a1 = " + a1 + ")";
+    }
+
+    public String mNumUnambigous(Short a1, boolean otherOverload) {
+        return "mmNumUnambigous won't be called";
+    }
+    
+    public String mNumUnambigous(Integer a1) {
+        return "mNumUnambigous(Integer a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(Byte a1) {
+        return "mNumBoxedAll(Byte a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(Short a1) {
+        return "mNumBoxedAll(Short a1 = " + a1 + ")";
+    }
+
+    public String mNumBoxedAll(Integer a1) {
+        return "mNumBoxedAll(Integer a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(Long a1) {
+        return "mNumBoxedAll(Long a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(Float a1) {
+        return "mNumBoxedAll(Float a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(Double a1) {
+        return "mNumBoxedAll(Double a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(BigInteger a1) {
+        return "mNumBoxedAll(BigInteger a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll(BigDecimal a1) {
+        return "mNumBoxedAll(BigDecimal a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(byte a1) {
+        return "mNumPrimAll(byte a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(short a1) {
+        return "mNumPrimAll(short a1 = " + a1 + ")";
+    }
+
+    public String mNumPrimAll(int a1) {
+        return "mNumPrimAll(int a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(long a1) {
+        return "mNumPrimAll(long a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(float a1) {
+        return "mNumPrimAll(float a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(double a1) {
+        return "mNumPrimAll(double a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(BigInteger a1) {
+        return "mNumPrimAll(BigInteger a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll(BigDecimal a1) {
+        return "mNumPrimAll(BigDecimal a1 = " + a1 + ")";
+    }
+
+    
+    public String mNumBoxedAll2nd(Short a1) {
+        return "mNumBoxedAll2nd(Short a1 = " + a1 + ")";
+    }
+
+    public String mNumBoxedAll2nd(Long a1) {
+        return "mNumBoxedAll2nd(Long a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedAll2nd(Double a1) {
+        return "mNumBoxedAll2nd(Double a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll2nd(short a1) {
+        return "mNumPrimAll2nd(short a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll2nd(long a1) {
+        return "mNumPrimAll2nd(long a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimAll2nd(double a1) {
+        return "mNumPrimAll2nd(double a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimFallbackToNumber(long a1) {
+        return "mNumPrimFallbackToNumber(long a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimFallbackToNumber(Number a1) {
+        return "mNumPrimFallbackToNumber(Number a1 = " + a1 + ")";
+    }
+    
+    public String mNumPrimFallbackToNumber(Object a1) {
+        return "mNumPrimFallbackToNumber(Object a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedFallbackToNumber(Long a1) {
+        return "mNumBoxedFallbackToNumber(Long a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedFallbackToNumber(Number a1) {
+        return "mNumBoxedFallbackToNumber(Number a1 = " + a1 + ")";
+    }
+    
+    public String mNumBoxedFallbackToNumber(Object a1) {
+        return "mNumBoxedFallbackToNumber(Object a1 = " + a1 + ")";
+    }
+
+    public String mDecimalLoss(int a1) {
+        return "mDecimalLoss(int a1 = " + a1 + ")";
+    }
+        
+    public String mDecimalLoss(double a1) {
+        return "mDecimalLoss(double a1 = " + a1 + ")";
+    }
+    
+    public String mNumConversionLoses1(byte i, Object o1, Object o2) {
+        return "byte " + i;
+    }
+    
+    public String mNumConversionLoses1(double i, Object o1, Object o2) {
+        return "double " + i;
+    }
+
+    public String mNumConversionLoses1(Number i, String o1, String o2) {
+        return "Number " + i + " " + i.getClass().getName();
+    }
+
+    public String mNumConversionLoses2(int i, Object o1, Object o2) {
+        return "int " + i;
+    }
+
+    public String mNumConversionLoses2(long i, Object o1, Object o2) {
+        return "long " + i;
+    }
+
+    public String mNumConversionLoses2(Number i, String o1, String o2) {
+        return "Number " + i + " " + i.getClass().getName();
+    }
+
+    public String mNumConversionLoses3(int i, Object o1, Object o2) {
+        return "int " + i;
+    }
+
+    public String mNumConversionLoses3(Serializable i, String o1, String o2) {
+        return "Serializable " + i + " " + i.getClass().getName();
+    }
+    
+    public String nIntAndLong(int i) {
+        return "nIntAndLong(int " + i + ")";
+    }
+    
+    public String nIntAndLong(long i) {
+        return "nIntAndLong(long " + i + ")";
+    }
+
+    public String nIntAndShort(int i) {
+        return "nIntAndShort(int " + i + ")";
+    }
+    
+    public String nIntAndShort(short i) {
+        return "nIntAndShort(short " + i + ")";
+    }
+
+    public String nLongAndShort(long i) {
+        return "nLongAndShort(long " + i + ")";
+    }
+    
+    public String nLongAndShort(short i) {
+        return "nLongAndShort(short " + i + ")";
+    }
+
+    public String varargs1(String s, int... xs) {
+        return "varargs1(String s = " + _StringUtil.jQuote(s) + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs1(String s, double... xs) {
+        return "varargs1(String s = " + _StringUtil.jQuote(s) + ", double... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs1(String s, Object... xs) {
+        return "varargs1(String s = " + _StringUtil.jQuote(s) + ", Object... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs1(Object s, Object... xs) {
+        return "varargs1(Object s = " + s + ", Object... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs2(int... xs) {
+        return "varargs2(int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs2(double... xs) {
+        return "varargs2(double... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs3(String... xs) {
+        return "varargs3(String... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs3(Comparable... xs) {
+        return "varargs3(Comparable... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs3(Object... xs) {
+        return "varargs3(Object... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs4(Integer... xs) {
+        return "varargs4(Integer... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs4(int... xs) {
+        return "varargs4(int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs5(int... xs) {
+        return "varargs5(int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs5(int a1, int... xs) {
+        return "varargs5(int a1 = " + a1 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs5(int a1, int a2, int... xs) {
+        return "varargs5(int a1 = " + a1 + ", int a2 = " + a2 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs5(int a1, int a2, int a3, int... xs) {
+        return "varargs5(int a1 = " + a1 + ", int a2 = " + a2 + ", int a3 = " + a3
+                + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+
+    public String varargs6(String a1, int... xs) {
+        return "varargs6(String a1 = " + a1 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs6(Object a1, int a2, int... xs) {
+        return "varargs6(Object a1 = " + a1 + ", int a2 = " + a2 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs7(int... xs) {
+        return "varargs7(int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String varargs7(short a1, int... xs) {
+        return "varargs7(short a1 = " + a1 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
+    }
+    
+    public String mNullAmbiguous(String s) {
+        return "mNullAmbiguous(String s = " + s + ")";
+    }
+
+    public String mNullAmbiguous(int i) {
+        return "mNullAmbiguous(int i = " + i + ")";
+    }
+
+    public String mNullAmbiguous(File f) {
+        return "mNullAmbiguous(File f = " + f + ")";
+    }
+    
+    public String mNullAmbiguous2(String s) {
+        return "mNullNonAmbiguous(String s = " + s + ")";
+    }
+
+    public String mNullAmbiguous2(File f) {
+        return "mNullAmbiguous(File f = " + f + ")";
+    }
+
+    public String mNullAmbiguous2(Object o) {
+        return "mNullAmbiguous(Object o = " + o + ")";
+    }
+
+    public String mNullNonAmbiguous(String s) {
+        return "mNullNonAmbiguous(String s = " + s + ")";
+    }
+
+    public String mNullNonAmbiguous(int i) {
+        return "mNullNonAmbiguous(int i = " + i + ")";
+    }
+    
+    public String mVarargsIgnoredTail(int i, double... ds) {
+        return "mVarargsIgnoredTail(int i = " + i + ", double... ds = " + TestUtil.arrayToString(ds) + ")";
+    }
+    
+    public String mVarargsIgnoredTail(int... is) {
+        return "mVarargsIgnoredTail(int... is = " + TestUtil.arrayToString(is) + ")";
+    }
+    
+    public String mLowRankWins(int x, int y, Object o) {
+        return "mLowRankWins(int x = " + x + ", int y = " + y + ", Object o = " + o + ")";
+    }
+
+    public String mLowRankWins(Integer x, Integer y, String s) {
+        return "mLowRankWins(Integer x = " + x + ", Integer y = " + y + ", String s = " + s + ")";
+    }
+    
+    public String mRareWrappings(File f, double d1, Double d2, double d3, boolean b) {
+        return "mRareWrappings(File f = " + f + ", double d1 = " + d1 + ", Double d2 = " + d2
+                + ", double d3 = " + d3 + ", b = " + b + ")";
+    }
+
+    public String mRareWrappings(Object o, double d1, Double d2, Double d3, boolean b) {
+        return "mRareWrappings(Object o = " + o + ", double d1 = " + d1 + ", Double d2 = " + d2
+                + ", double d3 = " + d3 + ", b = " + b + ")";
+    }
+
+    public String mRareWrappings(String s, double d1, Double d2, Double d3, boolean b) {
+        return "mRareWrappings(String s = " + s + ", double d1 = " + d1 + ", Double d2 = " + d2
+                + ", double d3 = " + d3 + ", b = " + b + ")";
+    }
+
+    public String mRareWrappings2(String s) {
+        return "mRareWrappings2(String s = " + s + ")";
+    }
+    
+    public String mRareWrappings2(byte b) {
+        return "mRareWrappings2(byte b = " + b + ")";
+    }
+    
+    public File getFile() {
+        return new File("file");
+    }
+
+    public String mSeqToArrayNonOverloaded(String[] items, String s) {
+        return "mSeqToArrayNonOverloaded(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
+    }
+    
+    public String mSeqToArrayGoodHint(String[] items, String s) {
+        return "mSeqToArrayGoodHint(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
+    }
+
+    public String mSeqToArrayGoodHint(String[] items, int i) {
+        return "mSeqToArrayGoodHint(String[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
+    }
+
+    public String mSeqToArrayGoodHint2(String[] items, String s) {
+        return "mSeqToArrayGoodHint2(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
+    }
+
+    public String mSeqToArrayGoodHint2(String item) {
+        return "mSeqToArrayGoodHint2(String " + item + ")";
+    }
+    
+    public String mSeqToArrayPoorHint(String[] items, String s) {
+        return "mSeqToArrayPoorHint(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
+    }
+
+    public String mSeqToArrayPoorHint(String item, int i) {
+        return "mSeqToArrayPoorHint(String " + item + ", int " + i + ")";
+    }
+
+    public String mSeqToArrayPoorHint2(String[] items) {
+        return "mSeqToArrayPoorHint2(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mSeqToArrayPoorHint2(String item) {
+        return "mSeqToArrayPoorHint2(String " + item + ")";
+    }
+    
+    public String mSeqToArrayPoorHint3(String[] items) {
+        return "mSeqToArrayPoorHint3(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mSeqToArrayPoorHint3(int[] items) {
+        return "mSeqToArrayPoorHint3(int[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVsListPreference(String[] items) {
+        return "mStringArrayVsListPreference(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVsListPreference(List items) {
+        return "mStringArrayVsListPreference(List " + TestUtil.listToString(items) + ")";
+    }
+
+    public String mStringArrayVsObjectArrayPreference(String[] items) {
+        return "mStringArrayVsObjectArrayPreference(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVsObjectArrayPreference(Object[] items) {
+        return "mStringArrayVsObjectArrayPreference(Object[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mIntArrayVsIntegerArrayPreference(int[] items) {
+        return "mIntArrayVsIntegerArrayPreference(int[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mIntArrayVsIntegerArrayPreference(Integer[] items) {
+        return "mIntArrayVsIntegerArrayPreference(Integer[] " + TestUtil.arrayToString(items) + ")";
+    }
+    
+    public String mIntArrayNonOverloaded(int[] items) {
+        return "mIntArrayNonOverloaded(int[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mIntegerArrayNonOverloaded(Integer[] items) {
+        return "mIntegerArrayNonOverloaded(Integer[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mIntegerListNonOverloaded(List<Integer> items) {
+        return "mIntegerListNonOverloaded(List<Integer> " + items + ")";
+    }
+
+    public String mStringListNonOverloaded(List<String> items) {
+        return "mStringListNonOverloaded(List<String> " + items + ")";
+    }
+
+    public String mStringArrayNonOverloaded(String[] items) {
+        return "mStringArrayNonOverloaded(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mObjectListNonOverloaded(List<Object> items) {
+        return "mObjectListNonOverloaded(List<Object> " + items + ")";
+    }
+
+    public String mObjectArrayNonOverloaded(Object[] items) {
+        return "mObjectArrayNonOverloaded(Object[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mIntegerArrayOverloaded(Integer[] items, int i) {
+        return "mIntegerArrayOverloaded(Integer[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
+    }
+
+    public String mIntegerArrayOverloaded(Object obj, boolean b) {
+        return "mIntegerArrayOverloaded(Object " + obj + ", boolean " + b + ")";
+    }
+
+    public String mStringArrayOverloaded(String[] items, int i) {
+        return "mStringArrayOverloaded(String[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
+    }
+
+    public String mStringArrayOverloaded(Object obj, boolean b) {
+        return "mStringArrayOverloaded(Object " + obj + ", boolean " + b + ")";
+    }
+
+    public String mCharArrayOverloaded(char[] items, int i) {
+        return "mCharArrayOverloaded(char[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
+    }
+
+    public String mCharArrayOverloaded(Character[] items, String s) {
+        return "mCharArrayOverloaded(Character[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
+    }
+    
+    public String mCharArrayOverloaded(Object obj, boolean b) {
+        return "mCharArrayOverloaded(Object " + obj + ", boolean " + b + ")";
+    }
+
+    public String mStringArrayArrayOverloaded(String[][] arrayArray, int i) {
+        return "mStringArrayArrayOverloaded(String[][] " + TestUtil.arrayToString(arrayArray) + ", int " + i + ")";
+    }
+    
+    public String mStringArrayArrayOverloaded(Object obj, boolean b) {
+        return "mStringArrayArrayOverloaded(Object " + obj + ", boolean " + b + ")";
+    }
+    
+    public String mIntArrayArrayOverloaded(int[][] xss) {
+        return "mIntArrayArrayOverloaded(" + TestUtil.arrayToString(xss) + ")";
+    }
+
+    public String mIntArrayArrayOverloaded(String s) {
+        return "mIntArrayArrayOverloaded(" + s + ")";
+    }
+    
+    public String mArrayOfListsOverloaded(List[] xss) {
+        return "mArrayOfListsOverloaded(" + TestUtil.arrayToString(xss) + ")";
+    }
+
+    public String mArrayOfListsOverloaded(String x) {
+        return "mArrayOfListsOverloaded(" + x + ")";
+    }
+    
+    public String mIntArrayArrayNonOverloaded(int[][] xss) {
+        return "mIntArrayArrayNonOverloaded(" + TestUtil.arrayToString(xss) + ")";
+    }
+
+    public String mArrayOfListsNonOverloaded(List[] xss) {
+        return "mArrayOfListsNonOverloaded(" + TestUtil.arrayToString(xss) + ")";
+    }
+    
+    public String mStringArrayVarargsNonOverloaded(String... items) {
+        return "mStringArrayVarargsNonOverloaded(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded(String... items) {
+        return "mStringArrayVarargsNonOverloaded(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded1(String... items) {
+        return "mStringArrayVarargsOverloaded1(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded1(List<String> items) {
+        return "mStringArrayVarargsOverloaded1(List " + TestUtil.listToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded2(String... items) {
+        return "mStringArrayVarargsOverloaded2(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded2(String item) {
+        return "mStringArrayVarargsOverloaded2(String " + item + ")";
+    }
+    
+    public String mStringArrayVarargsOverloaded3(String... items) {
+        return "mStringArrayVarargsOverloaded3(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded3(String item1, String item2) {
+        return "mStringArrayVarargsOverloaded3(String " + item1 + ", String " + item2 + ")";
+    }
+    
+    public String mStringArrayVarargsOverloaded4(String... items) {
+        return "mStringArrayVarargsOverloaded4(String[] " + TestUtil.arrayToString(items) + ")";
+    }
+
+    public String mStringArrayVarargsOverloaded4(List... items) {
+        return "mStringArrayVarargsOverloaded4(List[] " + TestUtil.arrayToString(items) + ")";
+    }
+    
+    public String mListOrString(List<String> items) {
+        return "mListOrString(List " + TestUtil.listToString(items) + ")";
+    }
+
+    public String mListOrString(String item) {
+        return "mListOrString(String " + item + ")";
+    }
+
+    public String mListListOrString(List<List<Object>> items) {
+        return "mListListOrString(List " + TestUtil.listToString(items) + ")";
+    }
+
+    public String mListListOrString(String item) {
+        return "mListListOrString(String " + item + ")";
+    }
+    
+    public String mMapOrBoolean(Map v) {
+        return "mMapOrBoolean(Map " + v + ")";
+    }
+
+    public String mMapOrBoolean(boolean v) {
+        return "mMapOrBoolean(boolean " + v + ")";
+    }
+
+    public String mMapOrBooleanVarargs(Map... v) {
+        return "mMapOrBooleanVarargs(Map... " + TestUtil.arrayToString(v) + ")";
+    }
+
+    public String mMapOrBooleanVarargs(boolean... v) {
+        return "mMapOrBooleanVarargs(boolean... " + TestUtil.arrayToString(v) + ")";
+    }
+
+    public String mMapOrBooleanFixedAndVarargs(Map v) {
+        return "mMapOrBooleanFixedAndVarargs(Map " + v + ")";
+    }
+
+    public String mMapOrBooleanFixedAndVarargs(boolean v) {
+        return "mMapOrBooleanFixedAndVarargs(boolean " + v + ")";
+    }
+
+    public String mMapOrBooleanFixedAndVarargs(Map... v) {
+        return "mMapOrBooleanFixedAndVarargs(Map... " + TestUtil.arrayToString(v) + ")";
+    }
+
+    public String mMapOrBooleanFixedAndVarargs(boolean... v) {
+        return "mMapOrBooleanFixedAndVarargs(boolean... " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mNumberOrArray(Number v) {
+        return "mNumberOrArray(Number " + v + ")";
+    }
+
+    public String mNumberOrArray(Object[] v) {
+        return "mNumberOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mIntOrArray(int v) {
+        return "mIntOrArray(int " + v + ")";
+    }
+
+    public String mIntOrArray(Object[] v) {
+        return "mIntOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+
+    public String mDateOrArray(Date v) {
+        return "mDateOrArray(Date " + v.getTime() + ")";
+    }
+
+    public String mDateOrArray(Object[] v) {
+        return "mDateOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mStringOrArray(String v) {
+        return "mStringOrArray(String " + v + ")";
+    }
+
+    public String mStringOrArray(Object[] v) {
+        return "mStringOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mBooleanOrArray(boolean v) {
+        return "mBooleanOrArray(boolean " + v + ")";
+    }
+
+    public String mBooleanOrArray(Object[] v) {
+        return "mBooleanOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mMapOrArray(Map v) {
+        return "mMapOrArray(Map " + v + ")";
+    }
+
+    public String mMapOrArray(Object[] v) {
+        return "mMapOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mListOrArray(List v) {
+        return "mListOrArray(List " + v + ")";
+    }
+
+    public String mListOrArray(Object[] v) {
+        return "mListOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mSetOrArray(Set v) {
+        return "mSetOrArray(Set " + v + ")";
+    }
+
+    public String mSetOrArray(Object[] v) {
+        return "mSetOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
+    }
+    
+    public String mCharNonOverloaded(char c) {
+        return "mCharNonOverloaded(char " + c + ")";
+    }
+
+    public String mCharacterNonOverloaded(Character c) {
+        return "mCharacterNonOverloaded(Character " + c + ")";
+    }
+    
+    public String mCharOrCharacterOverloaded(char c) {
+        return "mCharOrCharacterOverloaded(char " + c + ")";
+    }
+
+    public String mCharOrCharacterOverloaded(Character c) {
+        return "mCharOrCharacterOverloaded(Character " + c + ")";
+    }
+
+    public String mCharOrBooleanOverloaded(char c) {
+        return "mCharOrBooleanOverloaded(char " + c + ")";
+    }
+
+    public String mCharOrBooleanOverloaded(boolean b) {
+        return "mCharOrBooleanOverloaded(boolean " + b + ")";
+    }
+
+    public String mCharOrStringOverloaded(char c, boolean b) {
+        return "mCharOrStringOverloaded(char " + c + ", boolean " + b + ")";
+    }
+
+    public String mCharOrStringOverloaded(String s, int i) {
+        return "mCharOrStringOverloaded(String " + s + ", int " + i + ")";
+    }
+
+    public String mCharacterOrStringOverloaded(Character c, boolean b) {
+        return "mCharacterOrStringOverloaded(Character " + c + ", boolean " + b + ")";
+    }
+
+    public String mCharacterOrStringOverloaded(String s, int i) {
+        return "mCharacterOrStringOverloaded(String " + s + ", int " + i + ")";
+    }
+    
+    public String mCharOrStringOverloaded2(String s) {
+        return "mCharOrStringOverloaded2(String " + s + ")";
+    }
+
+    public String mCharOrStringOverloaded2(char c) {
+        return "mCharOrStringOverloaded2(char " + c + ")";
+    }
+    
+    public String mCharacterOrStringOverloaded2(String s) {
+        return "mCharacterOrStringOverloaded2(String " + s + ")";
+    }
+
+    public String mCharacterOrStringOverloaded2(Character c) {
+        return "mCharacterOrStringOverloaded2(Character " + c + ")";
+    }
+    
+
+    public String getJavaString() {
+        return "s";
+    }
+    
+    public List getJavaStringList() {
+        List list = new ArrayList();
+        list.add("a");
+        list.add("b");
+        return list;
+    }
+
+    public List getJavaString2List() {
+        List list = new ArrayList();
+        list.add("aa");
+        list.add("bb");
+        return list;
+    }
+
+    public List getJavaStringListList() {
+        List listList = new ArrayList();
+        {
+            List list = new ArrayList();
+            list.add("a");
+            list.add("b");
+            
+            listList.add(list);
+        }
+        {
+            List list = new ArrayList();
+            list.add("c");
+            
+            listList.add(list);
+        }
+        return listList;
+    }
+
+    public List getJavaStringSequenceList() throws TemplateModelException {
+        ObjectWrapper ow = Environment.getCurrentEnvironment().getObjectWrapper();
+        
+        List listList = new ArrayList();
+        {
+            List list = new ArrayList();
+            list.add("a");
+            list.add("b");
+            
+            listList.add(ow.wrap(list));
+        }
+        {
+            List list = new ArrayList();
+            list.add("c");
+            
+            listList.add(ow.wrap(list));
+        }
+        return listList;
+    }
+    
+    public List<int[]> getJavaListOfIntArrays() {
+        List list = new ArrayList();
+        list.add(new int[] {1, 2, 3});
+        list.add(new int[] {});
+        list.add(new int[] {4});
+        return list;
+    }
+    
+    @SuppressWarnings("boxing")
+    public List getJavaIntegerListList() {
+        List listList = new ArrayList();
+        {
+            List list = new ArrayList();
+            list.add(1);
+            list.add(2);
+            
+            listList.add(list);
+        }
+        {
+            List list = new ArrayList();
+            list.add(3);
+            
+            listList.add(list);
+        }
+        return listList;
+    }
+    
+    @SuppressWarnings("boxing")
+    public List<Integer> getJavaIntegerList() {
+        List<Integer> list = new ArrayList<>();
+        list.add(1);
+        list.add(2);
+        return list;
+    }
+
+    @SuppressWarnings("boxing")
+    public List<Byte> getJavaByteList() {
+        List<Byte> list = new ArrayList<>();
+        list.add((byte) 1);
+        list.add((byte) 2);
+        return list;
+    }
+
+    @SuppressWarnings("boxing")
+    public List<Character> getJavaCharacterList() {
+        List<Character> list = new ArrayList<>();
+        list.add('c');
+        list.add('C');
+        return list;
+    }
+    
+    public String[] getJavaStringArray() {
+        return new String[] { "a", "b" };
+    }
+
+    public int[] getJavaIntArray() {
+        return new int[] { 11, 22 };
+    }
+
+    public Integer[] getJavaIntegerArray() {
+        return new Integer[] { Integer.valueOf(11), Integer.valueOf(22) };
+    }
+    
+    public String[] getJavaEmptyStringArray() {
+        return new String[] { };
+    }
+    
+    public String[][] getJavaStringArrayArray() {
+        return new String[][] { new String[] { "a", "b" }, new String[] { }, new String[] { "c" } };
+    }
+    
+    public Object[] getJavaObjectArray() {
+        return new Object[] { "a", "b" };
+    }
+    
+    public TemplateModel getHashAndScalarModel() {
+        return HashAndScalarModel.INSTANCE;
+    }
+
+    public TemplateModel getBooleanAndScalarModel() {
+        return BooleanAndScalarModel.INSTANCE;
+    }
+    
+    public TemplateModel getAllModels() {
+        return AllTemplateModels.INSTANCE;
+    }
+
+    public TemplateNumberModel getAdaptedNumber() {
+        return new MyAdapterNumberModel();
+    }
+
+    public TemplateNumberModel getWrapperNumber() {
+        return new MyWrapperNumberModel();
+    }
+
+    public TemplateBooleanModel getStringAdaptedToBoolean() {
+        return new MyStringAdaptedToBooleanModel();
+    }
+    
+    public TemplateBooleanModel getStringAdaptedToBoolean2() {
+        return new MyStringAdaptedToBooleanModel2();
+    }
+    
+    public TemplateBooleanModel getStringWrappedAsBoolean() {
+        return new MyStringWrapperAsBooleanModel();
+    }
+    
+    public TemplateBooleanModel getBooleanWrappedAsAnotherBoolean() {
+        return new MyBooleanWrapperAsAnotherBooleanModel(); 
+    }
+    
+    public String bugReport363(Map<String, ?> fields, List<?> listField) {
+        return "Executed: testMethod(Map fields, List listField) on input: fields=" + fields
+                + " and listField=" + listField;
+    }
+
+    public String bugReport363(Object... fields) {
+        return "Executed: testMethod(Object... fields) on input: fields=" + TestUtil.arrayToString(fields);
+    }
+    
+    private static class MyAdapterNumberModel implements TemplateNumberModel, AdapterTemplateModel {
+
+        @Override
+        public Object getAdaptedObject(Class hint) {
+            if (hint == double.class) {
+                return Double.valueOf(123.0001);
+            } else if (hint == Double.class) {
+                return Double.valueOf(123.0002);
+            } else {
+                return Long.valueOf(124L);
+            }
+        }
+
+        @Override
+        public Number getAsNumber() throws TemplateModelException {
+            return Integer.valueOf(122);
+        }
+        
+    }
+    
+    private static class MyWrapperNumberModel implements TemplateNumberModel, WrapperTemplateModel {
+
+        @Override
+        public Number getAsNumber() throws TemplateModelException {
+            return Integer.valueOf(122);
+        }
+
+        @Override
+        public Object getWrappedObject() {
+            return Double.valueOf(123.0001);
+        }
+        
+    }
+    
+    private static class MyStringWrapperAsBooleanModel implements TemplateBooleanModel, WrapperTemplateModel {
+
+        @Override
+        public Object getWrappedObject() {
+            return "yes";
+        }
+
+        @Override
+        public boolean getAsBoolean() throws TemplateModelException {
+            return true;
+        }
+        
+    }
+
+    private static class MyBooleanWrapperAsAnotherBooleanModel implements TemplateBooleanModel, WrapperTemplateModel {
+
+        @Override
+        public Object getWrappedObject() {
+            return Boolean.TRUE;
+        }
+
+        @Override
+        public boolean getAsBoolean() throws TemplateModelException {
+            return false;
+        }
+        
+    }
+    
+    private static class MyStringAdaptedToBooleanModel implements TemplateBooleanModel, AdapterTemplateModel {
+
+        @Override
+        public Object getAdaptedObject(Class hint) {
+            if (hint != Boolean.class && hint != boolean.class) {
+                return "yes";
+            } else {
+                return Boolean.TRUE;
+            }
+        }
+
+        @Override
+        public boolean getAsBoolean() throws TemplateModelException {
+            return false;
+        }
+        
+    }
+
+    private static class MyStringAdaptedToBooleanModel2 implements TemplateBooleanModel, AdapterTemplateModel {
+
+        @Override
+        public Object getAdaptedObject(Class hint) {
+            return "yes";
+        }
+
+        @Override
+        public boolean getAsBoolean() throws TemplateModelException {
+            return true;
+        }
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleMapAndCollectionObjectWrapper.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleMapAndCollectionObjectWrapper.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleMapAndCollectionObjectWrapper.java
new file mode 100644
index 0000000..7992b1e
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleMapAndCollectionObjectWrapper.java
@@ -0,0 +1,60 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.freemarker.core.Version;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.SimpleHash;
+import org.apache.freemarker.core.model.impl.SimpleSequence;
+
+/**
+ * Forces using "simple" models for {@link Map}-s, {@link Collection}-s and arrays. This is mostly useful for template
+ * test cases that wish to test with these models, but otherwise need to able to wrap beans and such. 
+ */
+public class SimpleMapAndCollectionObjectWrapper extends DefaultObjectWrapper {
+
+    public SimpleMapAndCollectionObjectWrapper(Version incompatibleImprovements) {
+        super(new DefaultObjectWrapper.Builder(incompatibleImprovements), true);
+    }
+
+    @Override
+    public TemplateModel wrap(Object obj) throws TemplateModelException {
+        if (obj == null) {
+            return super.wrap(null);
+        }        
+        if (obj.getClass().isArray()) {
+            obj = Arrays.asList((Object[]) obj);
+        }
+        if (obj instanceof Collection) {
+            return new SimpleSequence((Collection<?>) obj, this);
+        }
+        if (obj instanceof Map) {
+            return new SimpleHash((Map<?, ?>) obj, this);
+        }
+        
+        return super.wrap(obj);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleTestMethod.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleTestMethod.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleTestMethod.java
new file mode 100644
index 0000000..21fc5c0
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/SimpleTestMethod.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import java.util.List;
+
+import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * A simple method model used as a test bed.
+ */
+public class SimpleTestMethod implements TemplateMethodModel {
+
+    /**
+     * Executes a method call.
+     *
+     * @param arguments a <tt>List</tt> of <tt>String</tt> objects containing
+     * the values of the arguments passed to the method.
+     * @return the <tt>TemplateModel</tt> produced by the method, or null.
+     */
+    @Override
+    public Object exec(List arguments) {
+        if ( arguments.size() == 0 ) {
+            return new SimpleScalar( "Empty list provided" );
+        } else if ( arguments.size() > 1 ) {
+            return new SimpleScalar( "Argument size is: " + arguments.size() );
+        } else {
+            return new SimpleScalar( "Single argument value is: " + arguments.get(0) );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBean.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBean.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBean.java
new file mode 100644
index 0000000..b963bd7
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBean.java
@@ -0,0 +1,17 @@
+package org.apache.freemarker.core.templatesuite.models;
+
+public class TestBean {
+
+    public int m(int n) {
+        return n * 10;
+    }
+
+    public int mOverloaded(int n) {
+        return n * 10;
+    }
+
+    public String mOverloaded(String s) {
+        return s.toUpperCase();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBoolean.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBoolean.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBoolean.java
new file mode 100644
index 0000000..8339d59
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestBoolean.java
@@ -0,0 +1,16 @@
+package org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateBooleanModel;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+
+public class TestBoolean implements TemplateBooleanModel, TemplateScalarModel {
+    @Override
+    public boolean getAsBoolean() {
+        return true;
+    }
+
+    @Override
+    public String getAsString() {
+        return "de";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestMethod.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestMethod.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestMethod.java
new file mode 100644
index 0000000..d9087a3
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestMethod.java
@@ -0,0 +1,12 @@
+package org.apache.freemarker.core.templatesuite.models;
+
+import java.util.List;
+
+import org.apache.freemarker.core.model.TemplateMethodModel;
+
+public class TestMethod implements TemplateMethodModel {
+    @Override
+    public Object exec(List arguments) {
+        return "x";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestNode.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestNode.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestNode.java
new file mode 100644
index 0000000..dfc68c7
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TestNode.java
@@ -0,0 +1,32 @@
+package org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.model.TemplateNodeModel;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+
+public class TestNode implements TemplateNodeModel {
+
+    @Override
+    public String getNodeName() {
+        return "name";
+    }
+
+    @Override
+    public TemplateNodeModel getParentNode() {
+        return null;
+    }
+
+    @Override
+    public String getNodeType() {
+        return "element";
+    }
+
+    @Override
+    public TemplateSequenceModel getChildNodes() {
+        return null;
+    }
+
+    @Override
+    public String getNodeNamespace() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b75ea93/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TransformHashWrapper.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TransformHashWrapper.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TransformHashWrapper.java
new file mode 100644
index 0000000..7771d6d
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templatesuite/models/TransformHashWrapper.java
@@ -0,0 +1,79 @@
+/*
+ * 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 org.apache.freemarker.core.templatesuite.models;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.SimpleHash;
+import org.apache.freemarker.core.util.HtmlEscape;
+import org.apache.freemarker.core.util.StandardCompress;
+
+/**
+ * Part of the TestTransform testcase suite.
+ */
+public class TransformHashWrapper implements TemplateHashModel,
+        TemplateScalarModel {
+
+    private ObjectWrapper ow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+    private SimpleHash m_cHashModel = new SimpleHash(ow);
+
+    /** Creates new TransformHashWrapper */
+    public TransformHashWrapper() {
+        m_cHashModel.put( "htmlEscape", new HtmlEscape() );
+        m_cHashModel.put( "compress", new StandardCompress() );
+        m_cHashModel.put( "escape", new TransformMethodWrapper1() );
+        m_cHashModel.put( "special", new TransformMethodWrapper2() );
+    }
+
+    /**
+     * Gets a <tt>TemplateModel</tt> from the hash.
+     *
+     * @param key the name by which the <tt>TemplateModel</tt>
+     * is identified in the template.
+     * @return the <tt>TemplateModel</tt> referred to by the key,
+     * or null if not found.
+     */
+    @Override
+    public TemplateModel get(String key) throws TemplateModelException {
+        return m_cHashModel.get( key );
+    }
+
+    /**
+     * @return true if this object is empty.
+     */
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    /**
+     * Returns the scalar's value as a String.
+     * @return the String value of this scalar.
+     */
+    @Override
+    public String getAsString() {
+        return "Utility transformations";
+    }
+}