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/08/07 22:41:28 UTC

[2/8] incubator-freemarker git commit: FREEMARKER-64: TemplateModel and TemplateModelEx changes (but they will be probably replaced by TemplateFunctionModel later): Removed FM2 `TemplateMethodModel`, then renamed `TemplateMethodModelEx` to `TemplateMetho

FREEMARKER-64: TemplateModel and TemplateModelEx changes (but they will be probably replaced by TemplateFunctionModel later): Removed FM2 `TemplateMethodModel`, then renamed `TemplateMethodModelEx` to `TemplateMethodModel`. Then changed it further to return `TemplateModel` (instead of `Object`, which allowed returning a non-wrapped value by design in FM2), changed the parameter `List` to `List<? extends TemplateModel>` (which it was earlier too, but there were no generic paramters back then), and allowed throwing `TemplateException` instead of the more restrictive `TemplateModelException`.


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

Branch: refs/heads/3
Commit: 1333a715f2a305391907eefd74fcb8ad7a48db5f
Parents: 3cacd9e
Author: ddekany <dd...@apache.org>
Authored: Fri Aug 4 23:04:19 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Fri Aug 4 23:33:34 2017 +0200

----------------------------------------------------------------------
 FM3-CHANGE-LOG.txt                              |  10 +-
 ...a8DefaultObjectWrapperBridgeMethodsTest.java |  23 ++-
 .../impl/Java8DefaultObjectWrapperTest.java     |  33 ++--
 .../impl/AbstractParallelIntrospectionTest.java |   7 +-
 .../model/impl/DefaultObjectWrapperTest.java    |  55 ++++---
 .../core/model/impl/EnumModelsTest.java         |   6 +-
 .../core/model/impl/ErrorMessagesTest.java      |  22 +--
 .../impl/FineTuneMethodAppearanceTest.java      |   4 +-
 .../core/model/impl/StaticModelsTest.java       |   6 +-
 .../core/templatesuite/models/MultiModel2.java  |  17 +-
 .../templatesuite/models/SimpleTestMethod.java  |  13 +-
 .../core/templatesuite/models/TestMethod.java   |   8 +-
 .../core/userpkg/AllFeaturesDirective.java      |  19 ++-
 .../core/userpkg/AllFeaturesFunction.java       |  20 ++-
 .../core/userpkg/TestTemplateCallableModel.java |  14 +-
 .../templatesuite/expected/stringbimethods.txt  |   2 -
 .../templatesuite/templates/stringbimethods.ftl |   4 -
 .../freemarker/core/ASTExpListLiteral.java      |  27 +---
 .../freemarker/core/ASTExpMethodCall.java       |   8 +-
 .../freemarker/core/BuiltInsForDates.java       |  25 ++-
 .../core/BuiltInsForExistenceHandling.java      |  14 +-
 .../core/BuiltInsForMultipleTypes.java          |  32 ++--
 .../BuiltInsForNestedContentParameters.java     |   6 +-
 .../freemarker/core/BuiltInsForNodes.java       |   4 +-
 .../freemarker/core/BuiltInsForSequences.java   |  62 ++++----
 .../core/BuiltInsForStringsBasic.java           |  78 +++++-----
 .../core/BuiltInsForStringsEncoding.java        |   6 +-
 .../freemarker/core/BuiltInsForStringsMisc.java |  22 +--
 .../core/BuiltInsForStringsRegexp.java          |  18 ++-
 .../org/apache/freemarker/core/Environment.java |   4 +-
 .../freemarker/core/NonStringException.java     |  14 +-
 .../apache/freemarker/core/_CallableUtils.java  | 156 +++++++++++++++++++
 .../core/_ObjectBuilderSettingEvaluator.java    |   8 +-
 .../core/_TemplateCallableModelUtils.java       | 112 -------------
 .../freemarker/core/debug/DebugModel.java       |   1 -
 .../core/debug/RmiDebugModelImpl.java           |   6 +-
 .../core/model/GeneralPurposeNothing.java       |   4 +-
 .../core/model/TemplateMethodModel.java         |  41 ++---
 .../core/model/TemplateMethodModelEx.java       |  54 -------
 .../freemarker/core/model/impl/BeanModel.java   |   3 +-
 .../core/model/impl/DefaultObjectWrapper.java   |   8 +-
 .../core/model/impl/JavaMethodModel.java        |  11 +-
 .../core/model/impl/OverloadedMethodsModel.java |   8 +-
 .../core/model/impl/ResourceBundleModel.java    |  20 +--
 .../freemarker/core/model/impl/StaticModel.java |   3 +-
 .../model/impl/TemplateModelListSequence.java   |   4 +-
 .../jsp/CustomTagAndELFunctionCombiner.java     |  26 ++--
 .../freemarker/servlet/jsp/TaglibFactory.java   |   8 +-
 .../freemarker/servlet/jsp/TLDParsingTest.java  |  12 +-
 49 files changed, 521 insertions(+), 547 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt
index aab66b7..d38866b 100644
--- a/FM3-CHANGE-LOG.txt
+++ b/FM3-CHANGE-LOG.txt
@@ -135,7 +135,10 @@ Node: Changes already mentioned above aren't repeated here!
   - When parameter default expressions are evaluated, only the parameters defined earlier are already set.
     So `<#macro m a b=a>` works, but `<#macro m a=b b>` won't work anymore (unless there's `b` outside the
     parameter list), as `b` is not yet set when the default of `a` is calculated.
-
+- Built-ins don't convert their parameters to tring anymore; in FM some (not all) of them did, because they
+  were based on the TemplateMethod interface (deprecated even in FM2) that required String paramteters and
+  was auto-converted by FM2.
+    
   
 Java API changes
 ================
@@ -372,6 +375,11 @@ Core / Models and Object wrapping
   get method (`get(String)`) had priority over methods of similar name. The generic get method is only recognized from its
   name and parameter type, so it's a quite consfusing feature, and might will be removed alltogether.
 - Renamed TemplateDateModel.DATETIME to DATE_TIME (to be consistent with "dateTime" used elsewhere).
+- TemplateModel and TemplateModelEx changes (but they will be probably replaced by TemplateFunctionModel later):
+  Removed FM2 `TemplateMethodModel`, then renamed `TemplateMethodModelEx` to `TemplateMethodModel`. Then changed it further to return
+  `TemplateModel` (instead of `Object`, which allowed returning a non-wrapped value by design in FM2), changed the parameter `List` to
+  `List<? extends TemplateModel>` (which it was earlier too, but there were no generic paramters back then), and allowed throwing
+  `TemplateException` instead of the more restrictive `TemplateModelException`.
 
 Core / Template loading and caching
 ...................................

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperBridgeMethodsTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperBridgeMethodsTest.java b/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperBridgeMethodsTest.java
index 495f3f9..abb373e 100644
--- a/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperBridgeMethodsTest.java
+++ b/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperBridgeMethodsTest.java
@@ -22,31 +22,30 @@ import static org.junit.Assert.*;
 
 import java.util.Collections;
 
-import org.junit.Test;
-
 import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
-import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.junit.Test;
 
 public class Java8DefaultObjectWrapperBridgeMethodsTest {
     
     @Test
-    public void testWithoutDefaultMethod() throws TemplateModelException {
+    public void testWithoutDefaultMethod() throws TemplateException {
         test(BridgeMethodsBean.class);
     }
 
     @Test
-    public void testWithDefaultMethod() throws TemplateModelException {
+    public void testWithDefaultMethod() throws TemplateException {
         test(Java8BridgeMethodsWithDefaultMethodBean.class);
     }
 
     @Test
-    public void testWithDefaultMethod2() throws TemplateModelException {
+    public void testWithDefaultMethod2() throws TemplateException {
         test(Java8BridgeMethodsWithDefaultMethodBean2.class);
     }
 
-    private void test(Class<?> pClass) throws TemplateModelException {
+    private void test(Class<?> pClass) throws TemplateException {
         DefaultObjectWrapper ow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
         TemplateHashModel wrapped;
         try {
@@ -55,11 +54,11 @@ public class Java8DefaultObjectWrapperBridgeMethodsTest {
             throw new IllegalStateException(e);
         }
         
-        TemplateMethodModelEx m1 = (TemplateMethodModelEx) wrapped.get("m1");
-        assertEquals(BridgeMethodsBean.M1_RETURN_VALUE, "" + m1.exec(Collections.emptyList()));
+        TemplateMethodModel m1 = (TemplateMethodModel) wrapped.get("m1");
+        assertEquals(BridgeMethodsBean.M1_RETURN_VALUE, "" + m1.execute(Collections.emptyList()));
         
-        TemplateMethodModelEx m2 = (TemplateMethodModelEx) wrapped.get("m2");
-        assertNull(m2.exec(Collections.emptyList()));
+        TemplateMethodModel m2 = (TemplateMethodModel) wrapped.get("m2");
+        assertNull(m2.execute(Collections.emptyList()));
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperTest.java b/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperTest.java
index 905d536..08dc5b1 100644
--- a/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperTest.java
+++ b/freemarker-core-test-java8/src/test/java/org/apache/freemarker/core/model/impl/Java8DefaultObjectWrapperTest.java
@@ -22,20 +22,19 @@ import static org.junit.Assert.*;
 
 import java.util.Collections;
 
-import org.junit.Test;
-
 import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
-import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateNumberModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
+import org.junit.Test;
 
 public class Java8DefaultObjectWrapperTest {
 
     @Test
-    public void testDefaultMethodRecognized() throws TemplateModelException {
+    public void testDefaultMethodRecognized() throws TemplateException {
         DefaultObjectWrapper.Builder owb = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0);
         DefaultObjectWrapper ow = owb.build();
         TemplateHashModel wrappedBean = (TemplateHashModel) ow.wrap(new Java8DefaultMethodsBean());
@@ -62,11 +61,11 @@ public class Java8DefaultObjectWrapperTest {
             // Has only indexed read method, so it's not exposed as a property
             assertNull(wrappedBean.get(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_INDEXED_PROP));
 
-            TemplateMethodModelEx indexedReadMethod = (TemplateMethodModelEx) wrappedBean.get(
+            TemplateMethodModel indexedReadMethod = (TemplateMethodModel) wrappedBean.get(
                     Java8DefaultMethodsBeanBase.DEFAULT_METHOD_INDEXED_PROP_GETTER);
             assertNotNull(indexedReadMethod);
             assertEquals(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_INDEXED_PROP_VALUE,
-                    ((TemplateScalarModel) indexedReadMethod.exec(Collections.singletonList(new SimpleNumber(0))))
+                    ((TemplateScalarModel) indexedReadMethod.execute(Collections.singletonList(new SimpleNumber(0))))
                             .getAsString
                             ());
         }
@@ -115,45 +114,45 @@ public class Java8DefaultObjectWrapperTest {
             // Has only indexed read method, so it's not exposed as a property
             assertNull(wrappedBean.get(Java8DefaultMethodsBean.INDEXED_PROP_4));
 
-            TemplateMethodModelEx indexedReadMethod = (TemplateMethodModelEx) wrappedBean.get(
+            TemplateMethodModel indexedReadMethod = (TemplateMethodModel) wrappedBean.get(
                     Java8DefaultMethodsBean.INDEXED_PROP_GETTER_4);
             assertNotNull(indexedReadMethod);
             assertEquals(Java8DefaultMethodsBean.INDEXED_PROP_4_VALUE,
-                    ((TemplateScalarModel) indexedReadMethod.exec(Collections.singletonList(new SimpleNumber(0))))
+                    ((TemplateScalarModel) indexedReadMethod.execute(Collections.singletonList(new SimpleNumber(0))))
                             .getAsString());
         }        
         {
-            TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(
+            TemplateMethodModel action = (TemplateMethodModel) wrappedBean.get(
                     Java8DefaultMethodsBean.NORMAL_ACTION);
             assertNotNull(action);
             assertEquals(
                     Java8DefaultMethodsBean.NORMAL_ACTION_RETURN_VALUE,
-                    ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
+                    ((TemplateScalarModel) action.execute(Collections.emptyList())).getAsString());
         }
         
         {
-            TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(
+            TemplateMethodModel action = (TemplateMethodModel) wrappedBean.get(
                     Java8DefaultMethodsBean.NORMAL_ACTION);
             assertNotNull(action);
             assertEquals(
                     Java8DefaultMethodsBean.NORMAL_ACTION_RETURN_VALUE,
-                    ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
+                    ((TemplateScalarModel) action.execute(Collections.emptyList())).getAsString());
         }
         {
-            TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(
+            TemplateMethodModel action = (TemplateMethodModel) wrappedBean.get(
                     Java8DefaultMethodsBean.DEFAULT_METHOD_ACTION);
             assertNotNull(action);
             assertEquals(
                     Java8DefaultMethodsBean.DEFAULT_METHOD_ACTION_RETURN_VALUE,
-                    ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
+                    ((TemplateScalarModel) action.execute(Collections.emptyList())).getAsString());
         }
         {
-            TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(
+            TemplateMethodModel action = (TemplateMethodModel) wrappedBean.get(
                     Java8DefaultMethodsBean.OVERRIDDEN_DEFAULT_METHOD_ACTION);
             assertNotNull(action);
             assertEquals(
                     Java8DefaultMethodsBean.OVERRIDDEN_DEFAULT_METHOD_ACTION_RETURN_VALUE,
-                    ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
+                    ((TemplateScalarModel) action.execute(Collections.emptyList())).getAsString());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/AbstractParallelIntrospectionTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/AbstractParallelIntrospectionTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/AbstractParallelIntrospectionTest.java
index bdb9a56..aac56b3 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/AbstractParallelIntrospectionTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/AbstractParallelIntrospectionTest.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.core.model.impl;
 
 import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.TemplateHashModel;
 import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModelException;
@@ -111,12 +112,12 @@ public abstract class AbstractParallelIntrospectionTest extends TestCase {
         }
 
         private void testMethod(TemplateHashModel h, int objIdx, int mIdx)
-                throws TemplateModelException, AssertionError {
+                throws TemplateException, AssertionError {
             TemplateMethodModel pv = (TemplateMethodModel) h.get("m" + mIdx);
             final int expected = objIdx * 1000 + mIdx;
-            final int got = ((TemplateNumberModel) pv.exec(null)).getAsNumber().intValue();
+            final int got = ((TemplateNumberModel) pv.execute(null)).getAsNumber().intValue();
             if (got != expected) {
-                throw new AssertionError("Method assertation failed; " +
+                throw new AssertionError("Method assertion failed; " +
                         "expected " + expected + ", but got " + got);
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
index 41acce3..dd1c841 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
@@ -52,7 +52,7 @@ import org.apache.freemarker.core.model.TemplateCollectionModel;
 import org.apache.freemarker.core.model.TemplateCollectionModelEx;
 import org.apache.freemarker.core.model.TemplateHashModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateModelIterator;
@@ -167,7 +167,7 @@ public class DefaultObjectWrapperTest {
     
     
     @Test
-    public void testCustomization() throws TemplateModelException {
+    public void testCustomization() throws TemplateException {
         CustomizedDefaultObjectWrapper ow = new CustomizedDefaultObjectWrapper(Configuration.VERSION_3_0_0);
         assertEquals(Configuration.VERSION_3_0_0, ow.getIncompatibleImprovements());
 
@@ -191,16 +191,15 @@ public class DefaultObjectWrapperTest {
         assertEquals(1, ow.unwrap(bean.get("x")));
         {
             // Check method calls, and also if the return value is wrapped with the overidden "wrap".
-            final TemplateModel mr = (TemplateModel) ((TemplateMethodModelEx) bean.get("m")).exec(Collections.emptyList());
-            assertEquals(
-                    Collections.singletonList(1),
-                    ow.unwrap(mr));
+            final TemplateModel mr = ((TemplateMethodModel) bean.get("m")).execute(
+                    Collections.<TemplateModel>emptyList());
+            assertEquals(Collections.singletonList(1), ow.unwrap(mr));
             assertTrue(DefaultListAdapter.class.isInstance(mr));
         }
         {
             // Check custom TM usage and round trip:
-            final TemplateModel mr = (TemplateModel) ((TemplateMethodModelEx) bean.get("incTupple"))
-                    .exec(Collections.singletonList(ow.wrap(new Tupple<>(1, 2))));
+            final TemplateModel mr = ((TemplateMethodModel) bean.get("incTupple"))
+                    .execute(Collections.singletonList(ow.wrap(new Tupple<>(1, 2))));
             assertEquals(new Tupple<>(2, 3), ow.unwrap(mr));
             assertTrue(TuppleAdapter.class.isInstance(mr));
         }
@@ -208,7 +207,7 @@ public class DefaultObjectWrapperTest {
 
     @SuppressWarnings("boxing")
     @Test
-    public void testCompositeValueWrapping() throws TemplateModelException, ClassNotFoundException {
+    public void testCompositeValueWrapping() throws TemplateException, ClassNotFoundException {
         DefaultObjectWrapper ow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
 
         final Map hashMap = new HashMap();
@@ -246,7 +245,7 @@ public class DefaultObjectWrapperTest {
 
     @SuppressWarnings("boxing")
     @Test
-    public void testMapAdapter() throws TemplateModelException {
+    public void testMapAdapter() throws TemplateException {
         HashMap<String, Object> testMap = new LinkedHashMap<>();
         testMap.put("a", 1);
         testMap.put("b", null);
@@ -303,7 +302,7 @@ public class DefaultObjectWrapperTest {
 
     @SuppressWarnings("boxing")
     @Test
-    public void testListAdapter() throws TemplateModelException {
+    public void testListAdapter() throws TemplateException {
         {
             List testList = new ArrayList<>();
             testList.add(1);
@@ -326,7 +325,7 @@ public class DefaultObjectWrapperTest {
         }
 
         {
-            List testList = new LinkedList<>();
+            List<Object> testList = new LinkedList<>();
             testList.add(1);
             testList.add(null);
             testList.add("c");
@@ -442,29 +441,29 @@ public class DefaultObjectWrapperTest {
     private void assertRoundtrip(DefaultObjectWrapper dow, Object obj, Class expectedTMClass,
             Class expectedPojoClass,
             String expectedPojoToString)
-            throws TemplateModelException {
+            throws TemplateException {
         final TemplateModel objTM = dow.wrap(obj);
         assertThat(objTM.getClass(), typeCompatibleWith(expectedTMClass));
 
         final TemplateHashModel testBeanTM = (TemplateHashModel) dow.wrap(new RoundtripTesterBean());
 
         {
-            TemplateMethodModelEx getClassM = (TemplateMethodModelEx) testBeanTM.get("getClass");
-            Object r = getClassM.exec(Collections.singletonList(objTM));
+            TemplateMethodModel getClassM = (TemplateMethodModel) testBeanTM.get("getClass");
+            TemplateModel r = getClassM.execute(Collections.singletonList(objTM));
             final Class rClass = (Class) ((WrapperTemplateModel) r).getWrappedObject();
             assertThat(rClass, typeCompatibleWith(expectedPojoClass));
         }
 
         if (expectedPojoToString != null) {
-            TemplateMethodModelEx getToStringM = (TemplateMethodModelEx) testBeanTM.get("toString");
-            Object r = getToStringM.exec(Collections.singletonList(objTM));
+            TemplateMethodModel getToStringM = (TemplateMethodModel) testBeanTM.get("toString");
+            TemplateModel r = getToStringM.execute(Collections.singletonList(objTM));
             assertEquals(expectedPojoToString, ((TemplateScalarModel) r).getAsString());
         }
     }
 
     @SuppressWarnings("boxing")
     @Test
-    public void testCollectionAdapterBasics() throws TemplateModelException {
+    public void testCollectionAdapterBasics() throws TemplateException {
         {
             Set set = new TreeSet();
             set.add("a");
@@ -538,7 +537,7 @@ public class DefaultObjectWrapperTest {
     }
 
     @Test
-    public void testIteratorWrapping() throws TemplateModelException, ClassNotFoundException {
+    public void testIteratorWrapping() throws TemplateException, ClassNotFoundException {
         final List<String> list = ImmutableList.of("a", "b", "c");
         Iterator<String> it = list.iterator();
         TemplateCollectionModel coll = (TemplateCollectionModel) OW.wrap(it);
@@ -578,14 +577,14 @@ public class DefaultObjectWrapperTest {
     }
 
     @Test
-    public void testIteratorApiSupport() throws TemplateModelException {
+    public void testIteratorApiSupport() throws TemplateException {
         TemplateModel wrappedIterator = OW.wrap(Collections.emptyIterator());
         assertThat(wrappedIterator, instanceOf(DefaultIteratorAdapter.class));
         DefaultIteratorAdapter iteratorAdapter = (DefaultIteratorAdapter) wrappedIterator;
 
         TemplateHashModel api = (TemplateHashModel) iteratorAdapter.getAPI();
-        assertFalse(((TemplateBooleanModel) ((TemplateMethodModelEx)
-                api.get("hasNext")).exec(Collections.emptyList())).getAsBoolean());
+        assertFalse(((TemplateBooleanModel) ((TemplateMethodModel)
+                api.get("hasNext")).execute(Collections.<TemplateModel>emptyList())).getAsBoolean());
     }
 
     @SuppressWarnings("boxing")
@@ -651,7 +650,7 @@ public class DefaultObjectWrapperTest {
     }
 
     @Test
-    public void testEnumerationAdapter() throws TemplateModelException {
+    public void testEnumerationAdapter() throws TemplateException {
         Vector<String> vector = new Vector<String>();
         vector.add("a");
         vector.add("b");
@@ -674,8 +673,8 @@ public class DefaultObjectWrapperTest {
         }
 
         TemplateHashModel api = (TemplateHashModel) enumAdapter.getAPI();
-        assertFalse(((TemplateBooleanModel) ((TemplateMethodModelEx)
-                api.get("hasMoreElements")).exec(Collections.emptyList())).getAsBoolean());
+        assertFalse(((TemplateBooleanModel) ((TemplateMethodModel) api.get("hasMoreElements"))
+                .execute(Collections.<TemplateModel>emptyList())).getAsBoolean());
     }
 
     @Test
@@ -725,13 +724,13 @@ public class DefaultObjectWrapperTest {
                 .wrap(bean);
     }
 
-    private void assertSizeThroughAPIModel(int expectedSize, TemplateModel normalModel) throws TemplateModelException {
+    private void assertSizeThroughAPIModel(int expectedSize, TemplateModel normalModel) throws TemplateException {
         if (!(normalModel instanceof TemplateModelWithAPISupport)) {
             fail(); 
         }
         TemplateHashModel apiModel = (TemplateHashModel) ((TemplateModelWithAPISupport) normalModel).getAPI();
-        TemplateMethodModelEx sizeMethod = (TemplateMethodModelEx) apiModel.get("size");
-        TemplateNumberModel r = (TemplateNumberModel) sizeMethod.exec(Collections.emptyList());
+        TemplateMethodModel sizeMethod = (TemplateMethodModel) apiModel.get("size");
+        TemplateNumberModel r = (TemplateNumberModel) sizeMethod.execute(Collections.<TemplateModel>emptyList());
         assertEquals(expectedSize, r.getAsNumber().intValue());
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/EnumModelsTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/EnumModelsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/EnumModelsTest.java
index fc19bb7..9373cf5 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/EnumModelsTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/EnumModelsTest.java
@@ -25,7 +25,7 @@ import java.util.ArrayList;
 
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
@@ -58,8 +58,8 @@ public class EnumModelsTest {
         assertTrue(a instanceof TemplateScalarModel);
         assertTrue(a instanceof TemplateHashModel);
         assertEquals(((TemplateScalarModel) a).getAsString(), "ts:A");
-        TemplateMethodModelEx nameMethod = (TemplateMethodModelEx) ((TemplateHashModel) a).get("name");
-        assertEquals(((TemplateScalarModel) nameMethod.exec(new ArrayList())).getAsString(), "A");
+        TemplateMethodModel nameMethod = (TemplateMethodModel) ((TemplateHashModel) a).get("name");
+        assertEquals(((TemplateScalarModel) nameMethod.execute(new ArrayList())).getAsString(), "A");
         
         assertSame(e, enums.get(E.class.getName()));
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/ErrorMessagesTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/ErrorMessagesTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/ErrorMessagesTest.java
index 29e8b9b..dcb8cf6 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/ErrorMessagesTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/ErrorMessagesTest.java
@@ -27,7 +27,7 @@ import java.util.Date;
 
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
@@ -60,9 +60,9 @@ public class ErrorMessagesTest {
         TemplateHashModel thm = (TemplateHashModel) ow.wrap(new TestBean());
         
         {
-            TemplateMethodModelEx m = (TemplateMethodModelEx) thm.get("m1");
+            TemplateMethodModel m = (TemplateMethodModel) thm.get("m1");
             try {
-                m.exec(Collections.singletonList(html));
+                m.execute(Collections.singletonList(html));
                 fail();
             } catch (TemplateModelException e) {
                 assertThat(e.getMessage(), allOf(
@@ -72,9 +72,9 @@ public class ErrorMessagesTest {
         }
         
         {
-            TemplateMethodModelEx m = (TemplateMethodModelEx) thm.get("m2");
+            TemplateMethodModel m = (TemplateMethodModel) thm.get("m2");
             try {
-                m.exec(Collections.singletonList(html));
+                m.execute(Collections.singletonList(html));
                 fail();
             } catch (TemplateModelException e) {
                 assertThat(e.getMessage(), allOf(
@@ -84,9 +84,9 @@ public class ErrorMessagesTest {
         }
         
         for (String methodName : new String[] { "mOverloaded", "mOverloaded3" }) {
-            TemplateMethodModelEx m = (TemplateMethodModelEx) thm.get(methodName);
+            TemplateMethodModel m = (TemplateMethodModel) thm.get(methodName);
             try {
-                m.exec(Collections.singletonList(html));
+                m.execute(Collections.singletonList(html));
                 fail();
             } catch (TemplateModelException e) {
                 assertThat(e.getMessage(), allOf(
@@ -97,9 +97,9 @@ public class ErrorMessagesTest {
         }
         
         {
-            TemplateMethodModelEx m = (TemplateMethodModelEx) thm.get("mOverloaded2");
+            TemplateMethodModel m = (TemplateMethodModel) thm.get("mOverloaded2");
             try {
-                m.exec(Collections.singletonList(html));
+                m.execute(Collections.singletonList(html));
                 fail();
             } catch (TemplateModelException e) {
                 assertThat(e.getMessage(), allOf(
@@ -110,8 +110,8 @@ public class ErrorMessagesTest {
         }
         
         {
-            TemplateMethodModelEx m = (TemplateMethodModelEx) thm.get("mOverloaded4");
-            Object r = m.exec(Collections.singletonList(html));
+            TemplateMethodModel m = (TemplateMethodModel) thm.get("mOverloaded4");
+            Object r = m.execute(Collections.singletonList(html));
             if (r instanceof TemplateScalarModel) {
                 r = ((TemplateScalarModel) r).getAsString();
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/FineTuneMethodAppearanceTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/FineTuneMethodAppearanceTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/FineTuneMethodAppearanceTest.java
index 92f59fb..eb4d807 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/FineTuneMethodAppearanceTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/FineTuneMethodAppearanceTest.java
@@ -23,7 +23,7 @@ import static org.junit.Assert.*;
 
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
@@ -48,7 +48,7 @@ public class FineTuneMethodAppearanceTest {
         assertEquals("v1", ((TemplateScalarModel) thm.get("v1")).getAsString());
         assertEquals("v2()", ((TemplateScalarModel) thm.get("v2")).getAsString());
         assertEquals("getV3()", ((TemplateScalarModel) thm.get("v3")).getAsString());
-        assertTrue(thm.get("getV3") instanceof TemplateMethodModelEx);
+        assertTrue(thm.get("getV3") instanceof TemplateMethodModel);
     }
     
     static public class C {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java
index 609d632..44da42a 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java
@@ -26,7 +26,7 @@ import java.util.ArrayList;
 
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
@@ -65,8 +65,8 @@ public class StaticModelsTest {
         assertEquals(((TemplateScalarModel) f).getAsString(), "F OK");
         
         TemplateModel m = s.get("m");
-        assertTrue(m instanceof TemplateMethodModelEx);
-        assertEquals(((TemplateScalarModel) ((TemplateMethodModelEx) m).exec(new ArrayList())).getAsString(), "m OK");
+        assertTrue(m instanceof TemplateMethodModel);
+        assertEquals(((TemplateScalarModel) ((TemplateMethodModel) m).execute(new ArrayList())).getAsString(), "m OK");
         
         assertSame(s, statics.get(S.class.getName()));
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/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
index e264936..3223652 100644
--- 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
@@ -19,10 +19,12 @@
 
 package org.apache.freemarker.core.templatesuite.models;
 
-import java.util.Iterator;
 import java.util.List;
 
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core._CallableUtils;
 import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
 
@@ -44,18 +46,17 @@ public class MultiModel2 implements TemplateScalarModel, TemplateMethodModel {
     /**
      * Executes a method call.
      *
-     * @param arguments a <tt>List</tt> of <tt>String</tt> objects containing the values
+     * @param args 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) {
+    public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateException {
         StringBuilder  aResults = new StringBuilder( "Arguments are:<br />" );
-        Iterator    iList = arguments.iterator();
-
-        while ( iList.hasNext() ) {
-            aResults.append( (String) iList.next() );
-            aResults.append( "<br />" );
+        for (int i = 0; i < args.size(); i++) {
+            TemplateModel arg = args.get(i);
+            aResults.append(_CallableUtils.castArgToString(arg, i));
+            aResults.append("<br />");
         }
 
         return new SimpleScalar( aResults.toString() );

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/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
index 21fc5c0..48352a0 100644
--- 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
@@ -22,6 +22,7 @@ package org.apache.freemarker.core.templatesuite.models;
 import java.util.List;
 
 import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
 
 /**
@@ -32,18 +33,18 @@ public class SimpleTestMethod implements TemplateMethodModel {
     /**
      * Executes a method call.
      *
-     * @param arguments a <tt>List</tt> of <tt>String</tt> objects containing
+     * @param args 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 ) {
+    public TemplateModel execute(List<? extends TemplateModel> args) {
+        if ( args.size() == 0 ) {
             return new SimpleScalar( "Empty list provided" );
-        } else if ( arguments.size() > 1 ) {
-            return new SimpleScalar( "Argument size is: " + arguments.size() );
+        } else if ( args.size() > 1 ) {
+            return new SimpleScalar( "Argument size is: " + args.size() );
         } else {
-            return new SimpleScalar( "Single argument value is: " + arguments.get(0) );
+            return new SimpleScalar( "Single argument value is: " + args.get(0) );
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/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
index d9087a3..ed97f9e 100644
--- 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
@@ -3,10 +3,14 @@ package org.apache.freemarker.core.templatesuite.models;
 import java.util.List;
 
 import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
 
 public class TestMethod implements TemplateMethodModel {
+
     @Override
-    public Object exec(List arguments) {
-        return "x";
+    public TemplateModel execute(List<? extends TemplateModel> args) {
+        return new SimpleScalar("x");
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java
index 3509b78..d9bb394 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java
@@ -19,19 +19,18 @@
 
 package org.apache.freemarker.core.userpkg;
 
-import static org.apache.freemarker.core._TemplateCallableModelUtils.*;
+import static org.apache.freemarker.core._CallableUtils.*;
 
 import java.io.IOException;
 import java.io.Writer;
 
+import org.apache.freemarker.core.CallPlace;
 import org.apache.freemarker.core.Environment;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.ArgumentArrayLayout;
-import org.apache.freemarker.core.CallPlace;
 import org.apache.freemarker.core.model.TemplateDirectiveModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx2;
 import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateNumberModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
 import org.apache.freemarker.core.util.StringToIndexMap;
@@ -79,17 +78,17 @@ public class AllFeaturesDirective extends TestTemplateCallableModel implements T
     @Override
     public void execute(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env)
             throws TemplateException, IOException {
-        execute(castArgumentToNumber(args, P1_ARG_IDX, p1AllowNull, env),
-                castArgumentToNumber(args, P2_ARG_IDX, p2AllowNull, env),
+        execute(castArgToNumber(args, P1_ARG_IDX, p1AllowNull),
+                castArgToNumber(args, P2_ARG_IDX, p2AllowNull),
                 (TemplateSequenceModel) args[P_VARARGS_ARG_IDX],
-                castArgumentToNumber(args[N1_ARG_IDX], N1_ARG_NAME, n1AllowNull, env),
-                castArgumentToNumber(args[N2_ARG_IDX], N2_ARG_NAME, n2AllowNull, env),
+                castArgToNumber(args[N1_ARG_IDX], N1_ARG_NAME, n1AllowNull),
+                castArgToNumber(args[N2_ARG_IDX], N2_ARG_NAME, n2AllowNull),
                 (TemplateHashModelEx2) args[N_VARARGS_ARG_IDX],
                 out, env, callPlace);
     }
 
-    private void execute(TemplateNumberModel p1, TemplateNumberModel p2, TemplateSequenceModel pOthers,
-            TemplateNumberModel n1, TemplateNumberModel n2, TemplateHashModelEx2 nOthers,
+    private void execute(Number p1, Number p2, TemplateSequenceModel pOthers,
+            Number n1, Number n2, TemplateHashModelEx2 nOthers,
             Writer out, Environment env, CallPlace callPlace) throws IOException, TemplateException {
         out.write("#a(");
         printParam("p1", p1, out, true);
@@ -107,7 +106,7 @@ public class AllFeaturesDirective extends TestTemplateCallableModel implements T
         if (callPlace.hasNestedContent()) {
             out.write(" {");
             if (p1 != null) {
-                int intP1 = p1.getAsNumber().intValue();
+                int intP1 = p1.intValue();
                 for (int i = 0; i < intP1; i++) {
                     // We dynamically set as many nested content parameters as many the caller has declared; this is
                     // unusual, and is for testing purposes only.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java
index 7f1f6c1..5825745 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core.userpkg;
 
-import static org.apache.freemarker.core._TemplateCallableModelUtils.*;
+import static org.apache.freemarker.core._CallableUtils.*;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -31,7 +31,6 @@ import org.apache.freemarker.core.model.ArgumentArrayLayout;
 import org.apache.freemarker.core.model.TemplateFunctionModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx2;
 import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateNumberModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
 import org.apache.freemarker.core.util.StringToIndexMap;
@@ -78,18 +77,17 @@ public class AllFeaturesFunction extends TestTemplateCallableModel implements Te
 
     @Override
     public TemplateModel execute(TemplateModel[] args, CallPlace callPlace, Environment env) throws TemplateException {
-        return execute(castArgumentToNumber(args, P1_ARG_IDX, p1AllowNull, env),
-                castArgumentToNumber(args, P2_ARG_IDX, p2AllowNull, env),
+        return execute(
+                castArgToNumber(args, P1_ARG_IDX, p1AllowNull),
+                castArgToNumber(args, P2_ARG_IDX, p2AllowNull),
                 (TemplateSequenceModel) args[P_VARARGS_ARG_IDX],
-                castArgumentToNumber(args[N1_ARG_IDX], N1_ARG_NAME, n1AllowNull, env),
-                castArgumentToNumber(args[N2_ARG_IDX], N2_ARG_NAME, n2AllowNull, env),
-                (TemplateHashModelEx2) args[N_VARARGS_ARG_IDX],
-                env);
+                castArgToNumber(args[N1_ARG_IDX], N1_ARG_NAME, n1AllowNull),
+                castArgToNumber(args[N2_ARG_IDX], N2_ARG_NAME, n2AllowNull),
+                (TemplateHashModelEx2) args[N_VARARGS_ARG_IDX]);
     }
 
-    private TemplateModel execute(TemplateNumberModel p1, TemplateNumberModel p2, TemplateSequenceModel pOthers,
-            TemplateNumberModel n1, TemplateNumberModel n2, TemplateHashModelEx2 nOthers,
-            Environment env) throws TemplateException {
+    private TemplateModel execute(Number p1, Number p2, TemplateSequenceModel pOthers,
+            Number n1, Number n2, TemplateHashModelEx2 nOthers) throws TemplateException {
         StringWriter out = new StringWriter();
         try {
             out.write("fa(");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java
index 9dd34ba..f0a15d7 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java
@@ -24,20 +24,20 @@ import java.io.Writer;
 
 import org.apache.freemarker.core.model.TemplateCallableModel;
 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.TemplateNumberModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.util.FTLUtil;
+import org.apache.freemarker.core.util._StringUtil;
 
 public abstract class TestTemplateCallableModel implements TemplateCallableModel {
 
-    protected void printParam(String name, TemplateModel value, Writer out) throws IOException, TemplateModelException {
+    protected void printParam(String name, Object value, Writer out) throws IOException, TemplateModelException {
         printParam(name, value, out, false);
     }
 
-    protected void printParam(String name, TemplateModel value, Writer out, boolean first)
+    protected void printParam(String name, Object value, Writer out, boolean first)
             throws IOException, TemplateModelException {
         if (!first) {
             out.write(", ");
@@ -47,7 +47,7 @@ public abstract class TestTemplateCallableModel implements TemplateCallableModel
         printValue(value, out);
     }
 
-    private void printValue(TemplateModel value, Writer out) throws IOException, TemplateModelException {
+    private void printValue(Object value, Writer out) throws IOException, TemplateModelException {
         if (value == null) {
             out.write("null");
         } else if (value instanceof TemplateNumberModel) {
@@ -79,6 +79,12 @@ public abstract class TestTemplateCallableModel implements TemplateCallableModel
                 }
             }
             out.write('}');
+        } else if (value instanceof String) {
+            out.write(_StringUtil.jQuote(value));
+        } else if (value instanceof Number) {
+            out.write(value.toString());
+        } else if (value instanceof Boolean) {
+            out.write(value.toString());
         } else {
             throw new IllegalArgumentException("Unsupported value class: " + value.getClass().getName());
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/stringbimethods.txt
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/stringbimethods.txt b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/stringbimethods.txt
index 8ef415d..1d4a314 100644
--- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/stringbimethods.txt
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/stringbimethods.txt
@@ -25,5 +25,3 @@ de
 true false
 yes no
 igen nem
-0.0 1.0
-true true
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/stringbimethods.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/stringbimethods.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/stringbimethods.ftl
index 94954f9..c3bd460 100644
--- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/stringbimethods.ftl
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/stringbimethods.ftl
@@ -30,7 +30,3 @@ ${a?string} ${b?string}
 ${a?string("yes", "no")} ${b?string("yes", "no")}
 <#setting booleanFormat="igen,nem"/>
 ${a?string} ${b?string}
-<#setting numberFormat="0.0">
-${a?string(0, 1)} ${b?string(0, 1)}
-<#setting booleanFormat="true,false"/>
-${a?string(0, 1)?isString?string} ${b?string(0, 1)?isString?string}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
index e5dc679..0fc27da 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.ListIterator;
 
 import org.apache.freemarker.core.model.TemplateMethodModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 
@@ -55,31 +54,7 @@ final class ASTExpListLiteral extends ASTExpression {
     }
 
     /**
-     * For {@link TemplateMethodModel} calls, but not for {@link TemplateMethodModelEx}-es, returns the list of
-     * arguments as {@link String}-s.
-     */
-    List/*<String>*/ getValueList(Environment env) throws TemplateException {
-        int size = items.size();
-        switch(size) {
-            case 0: {
-                return Collections.EMPTY_LIST;
-            }
-            case 1: {
-                return Collections.singletonList(((ASTExpression) items.get(0)).evalAndCoerceToPlainText(env));
-            }
-            default: {
-                List result = new ArrayList(items.size());
-                for (ListIterator iterator = items.listIterator(); iterator.hasNext(); ) {
-                    ASTExpression exp = (ASTExpression) iterator.next();
-                    result.add(exp.evalAndCoerceToPlainText(env));
-                }
-                return result;
-            }
-        }
-    }
-
-    /**
-     * For {@link TemplateMethodModelEx} calls, returns the list of arguments as {@link TemplateModel}-s.
+     * For {@link TemplateMethodModel} calls, returns the list of arguments as {@link TemplateModel}-s.
      */
     List<TemplateModel> getModelList(Environment env) throws TemplateException {
         int size = items.size();

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpMethodCall.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpMethodCall.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpMethodCall.java
index dc8f3ff..581726e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpMethodCall.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpMethodCall.java
@@ -32,7 +32,6 @@ import org.apache.freemarker.core.model.ArgumentArrayLayout;
 import org.apache.freemarker.core.model.Constants;
 import org.apache.freemarker.core.model.TemplateFunctionModel;
 import org.apache.freemarker.core.model.TemplateMethodModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.util.CommonSupplier;
@@ -61,11 +60,8 @@ final class ASTExpMethodCall extends ASTExpression implements CallPlace {
         TemplateModel targetModel = target.eval(env);
         if (targetModel instanceof TemplateMethodModel) {
             TemplateMethodModel targetMethod = (TemplateMethodModel) targetModel;
-            List argumentStrings = 
-            targetMethod instanceof TemplateMethodModelEx
-            ? arguments.getModelList(env)
-            : arguments.getValueList(env);
-            Object result = targetMethod.exec(argumentStrings);
+            List<TemplateModel> argumentStrings = arguments.getModelList(env);
+            Object result = targetMethod.execute(argumentStrings);
             return env.getObjectWrapper().wrap(result);
         } else if (targetModel instanceof TemplateFunctionModel) {
             TemplateFunctionModel func = (TemplateFunctionModel) targetModel;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForDates.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForDates.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForDates.java
index ad11b37..434578d 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForDates.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForDates.java
@@ -25,7 +25,7 @@ import java.util.TimeZone;
 
 import org.apache.freemarker.core.model.AdapterTemplateModel;
 import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
@@ -63,11 +63,6 @@ class BuiltInsForDates {
             }
         }
 
-        protected TemplateModel calculateResult(Date date, int dateType, Environment env) throws TemplateException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-        
     }
     
     /**
@@ -75,7 +70,7 @@ class BuiltInsForDates {
      */
     static class iso_BI extends AbstractISOBI {
         
-        class Result implements TemplateMethodModelEx {
+        class Result implements TemplateMethodModel {
             private final Date date;
             private final int dateType;
             private final Environment env;
@@ -87,10 +82,10 @@ class BuiltInsForDates {
             }
 
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateModelException {
                 checkMethodArgCount(args, 1);
                 
-                TemplateModel tzArgTM = (TemplateModel) args.get(0);
+                TemplateModel tzArgTM = args.get(0);
                 TimeZone tzArg; 
                 Object adaptedObj;
                 if (tzArgTM instanceof AdapterTemplateModel
@@ -178,15 +173,15 @@ class BuiltInsForDates {
     private BuiltInsForDates() { }
 
     static abstract class AbstractISOBI extends BuiltInForDate {
-        protected final Boolean showOffset;
-        protected final int accuracy;
+        final Boolean showOffset;
+        final int accuracy;
     
-        protected AbstractISOBI(Boolean showOffset, int accuracy) {
+        AbstractISOBI(Boolean showOffset, int accuracy) {
             this.showOffset = showOffset;
             this.accuracy = accuracy;
         }
         
-        protected void checkDateTypeNotUnknown(int dateType)
+        void checkDateTypeNotUnknown(int dateType)
         throws TemplateException {
             if (dateType == TemplateDateModel.UNKNOWN) {
                 throw new _MiscTemplateException(new _ErrorDescriptionBuilder(
@@ -196,11 +191,11 @@ class BuiltInsForDates {
             }
         }
     
-        protected boolean shouldShowOffset(Date date, int dateType, Environment env) {
+        boolean shouldShowOffset(Date date, int dateType, Environment env) {
             if (dateType == TemplateDateModel.DATE) {
                 return false;  // ISO 8061 doesn't allow zone for date-only values
             } else if (showOffset != null) {
-                return showOffset.booleanValue();
+                return showOffset;
             } else {
                 // java.sql.Time values meant to carry calendar field values only, so we don't show offset for them.
                 return !(date instanceof java.sql.Time);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForExistenceHandling.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForExistenceHandling.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForExistenceHandling.java
index 6e7cce0..c0d6164 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForExistenceHandling.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForExistenceHandling.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core;
 import java.util.List;
 
 import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 
@@ -63,7 +63,7 @@ class BuiltInsForExistenceHandling {
             return model == null ? FIRST_NON_NULL_METHOD : new ConstantMethod(model);
         }
 
-        private static class ConstantMethod implements TemplateMethodModelEx {
+        private static class ConstantMethod implements TemplateMethodModel {
             private final TemplateModel constant;
 
             ConstantMethod(TemplateModel constant) {
@@ -71,7 +71,7 @@ class BuiltInsForExistenceHandling {
             }
 
             @Override
-            public Object exec(List args) {
+            public TemplateModel execute(List<? extends TemplateModel> args) {
                 return constant;
             }
         }
@@ -80,14 +80,14 @@ class BuiltInsForExistenceHandling {
          * A method that goes through the arguments one by one and returns
          * the first one that is non-null. If all args are null, returns null.
          */
-        private static final TemplateMethodModelEx FIRST_NON_NULL_METHOD =
-            new TemplateMethodModelEx() {
+        private static final TemplateMethodModel FIRST_NON_NULL_METHOD =
+            new TemplateMethodModel() {
                 @Override
-                public Object exec(List args) throws TemplateModelException {
+                public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateModelException {
                     int argCnt = args.size();
                     if (argCnt == 0) throw MessageUtil.newArgCntError("?default", argCnt, 1, Integer.MAX_VALUE);
                     for (int i = 0; i < argCnt; i++ ) {
-                        TemplateModel result = (TemplateModel) args.get(i);
+                        TemplateModel result = args.get(i);
                         if (result != null) return result;
                     }
                     return null;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
index 74f7c15..5e85262 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
@@ -19,6 +19,7 @@
 
 package org.apache.freemarker.core;
 
+import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 
@@ -110,7 +111,7 @@ class BuiltInsForMultipleTypes {
         private class DateParser
         implements
             TemplateDateModel,
-            TemplateMethodModel,
+                TemplateMethodModel,
             TemplateHashModel {
             private final String text;
             private final Environment env;
@@ -125,9 +126,9 @@ class BuiltInsForMultipleTypes {
             }
             
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateException {
                 checkMethodArgCount(args, 0, 1);
-                return args.size() == 0 ? getAsDateModel() : get((String) args.get(0));
+                return args.size() == 0 ? getAsDateModel() : get(_CallableUtils.castArgToString(args, 0));
             }
             
             @Override
@@ -470,8 +471,8 @@ class BuiltInsForMultipleTypes {
         
         private class BooleanFormatter
         implements 
-            TemplateScalarModel, 
-            TemplateMethodModel {
+            TemplateScalarModel,
+                TemplateMethodModel {
             private final TemplateBooleanModel bool;
             private final Environment env;
             
@@ -481,9 +482,14 @@ class BuiltInsForMultipleTypes {
             }
     
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateException {
                 checkMethodArgCount(args, 2);
-                return new SimpleScalar((String) args.get(bool.getAsBoolean() ? 0 : 1));
+                int argIdx = bool.getAsBoolean() ? 0 : 1;
+                TemplateModel result = args.get(argIdx);
+                if (!(result instanceof TemplateScalarModel)) {
+                    throw new NonStringException((Serializable) argIdx, result, null, null);
+                }
+                return result;
             }
     
             @Override
@@ -505,7 +511,7 @@ class BuiltInsForMultipleTypes {
         implements
             TemplateScalarModel,
             TemplateHashModel,
-            TemplateMethodModel {
+                TemplateMethodModel {
             private final TemplateDateModel dateModel;
             private final Environment env;
             private final TemplateDateFormat defaultFormat;
@@ -524,9 +530,9 @@ class BuiltInsForMultipleTypes {
             }
     
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateException {
                 checkMethodArgCount(args, 1);
-                return formatWith((String) args.get(0));
+                return formatWith(_CallableUtils.castArgToString(args, 0));
             }
 
             @Override
@@ -580,7 +586,7 @@ class BuiltInsForMultipleTypes {
         implements
             TemplateScalarModel,
             TemplateHashModel,
-            TemplateMethodModel {
+                TemplateMethodModel {
             private final TemplateNumberModel numberModel;
             private final Number number;
             private final Environment env;
@@ -602,9 +608,9 @@ class BuiltInsForMultipleTypes {
             }
     
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateException {
                 checkMethodArgCount(args, 1);
-                return get((String) args.get(0));
+                return get(_CallableUtils.castArgToString(args, 0));
             }
     
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNestedContentParameters.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNestedContentParameters.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNestedContentParameters.java
index a4c4d8f..89593cd 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNestedContentParameters.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNestedContentParameters.java
@@ -22,7 +22,7 @@ import java.util.List;
 
 import org.apache.freemarker.core.ASTDirList.IterationContext;
 import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
@@ -131,7 +131,7 @@ class BuiltInsForNestedContentParameters {
 
     static class item_cycleBI extends BuiltInForNestedContentParameter {
 
-        private class BIMethod implements TemplateMethodModelEx {
+        private class BIMethod implements TemplateMethodModel {
             
             private final IterationContext iterCtx;
     
@@ -140,7 +140,7 @@ class BuiltInsForNestedContentParameters {
             }
     
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateModelException {
                 checkMethodArgCount(args, 1, Integer.MAX_VALUE);
                 return args.get(iterCtx.getIndex() % args.size());
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
index 39bc546..d5dfe93 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
@@ -126,7 +126,7 @@ class BuiltInsForNodes {
         }
         
         @Override
-        public Object exec(List names) throws TemplateModelException {
+        public TemplateModel execute(List<? extends TemplateModel> names) throws TemplateException {
             if (names == null || names.isEmpty()) {
                 return this;
             }
@@ -141,7 +141,7 @@ class BuiltInsForNodes {
                     }
                 } else {
                     for (int j = 0; j < names.size(); j++) {
-                        if (_StringUtil.matchesQName((String) names.get(j), nodeName, nsURI, env)) {
+                        if (_StringUtil.matchesQName(_CallableUtils.castArgToString(names, j), nodeName, nsURI, env)) {
                             result.add(tnm);
                             break;
                         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1333a715/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForSequences.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForSequences.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForSequences.java
index e131406..9406d33 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForSequences.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForSequences.java
@@ -33,7 +33,7 @@ import org.apache.freemarker.core.model.TemplateBooleanModel;
 import org.apache.freemarker.core.model.TemplateCollectionModel;
 import org.apache.freemarker.core.model.TemplateDateModel;
 import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateModelIterator;
@@ -54,7 +54,7 @@ class BuiltInsForSequences {
     
     static class chunkBI extends BuiltInForSequence {
 
-        private class BIMethod implements TemplateMethodModelEx {
+        private class BIMethod implements TemplateMethodModel {
             
             private final TemplateSequenceModel tsm;
 
@@ -63,7 +63,7 @@ class BuiltInsForSequences {
             }
 
             @Override
-            public Object exec(List args) throws TemplateModelException {
+            public TemplateModel execute(List<? extends TemplateModel> args) throws TemplateModelException {
                 checkMethodArgCount(args, 1, 2);
                 int chunkSize = getNumberMethodArg(args, 0).intValue();
                 
@@ -182,7 +182,7 @@ class BuiltInsForSequences {
 
     static class joinBI extends ASTExpBuiltIn {
         
-        private class BIMethodForCollection implements TemplateMethodModelEx {
+        private class BIMethodForCollection implements TemplateMethodModel {
             
             private final Environment env;
             private final TemplateCollectionModel coll;
@@ -193,7 +193,7 @@ class BuiltInsForSequences {
             }
 
             @Override
-            public Object exec(List args)
+            public TemplateModel execute(List<? extends TemplateModel> args)
                     throws TemplateModelException {
                 checkMethodArgCount(args, 1, 3);
                 final String separator = getStringMethodArg(args, 0);
@@ -218,7 +218,7 @@ class BuiltInsForSequences {
                             sb.append(_EvalUtil.coerceModelToStringOrUnsupportedMarkup(item, null, null, env));
                         } catch (TemplateException e) {
                             throw new _TemplateModelException(e,
-                                    "\"?", key, "\" failed at index ", Integer.valueOf(idx), " with this error:\n\n",
+                                    "\"?", key, "\" failed at index ", idx, " with this error:\n\n",
                                     MessageUtil.EMBEDDED_MESSAGE_BEGIN,
                                     new _DelayedGetMessageWithoutStackTop(e),
                                     MessageUtil.EMBEDDED_MESSAGE_END);
@@ -295,7 +295,7 @@ class BuiltInsForSequences {
     }
 
     static class seq_containsBI extends ASTExpBuiltIn {
-        private class BIMethodForCollection implements TemplateMethodModelEx {
+        private class BIMethodForCollection implements TemplateMethodModel {
             private TemplateCollectionModel m_coll;
             private Environment m_env;
 
@@ -305,10 +305,10 @@ class BuiltInsForSequences {
             }
 
             @Override
-            public Object exec(List args)
+            public TemplateModel execute(List<? extends TemplateModel> args)
                     throws TemplateModelException {
                 checkMethodArgCount(args, 1);
-                TemplateModel arg = (TemplateModel) args.get(0);
+                TemplateModel arg = args.get(0);
                 TemplateModelIterator it = m_coll.iterator();
                 int idx = 0;
                 while (it.hasNext()) {
@@ -321,7 +321,7 @@ class BuiltInsForSequences {
 
         }
 
-        private class BIMethodForSequence implements TemplateMethodModelEx {
+        private class BIMethodForSequence implements TemplateMethodModel {
             private TemplateSequenceModel m_seq;
             private Environment m_env;
 
@@ -331,10 +331,10 @@ class BuiltInsForSequences {
             }
 
             @Override
-            public Object exec(List args)
+            public TemplateModel execute(List<? extends TemplateModel> args)
                     throws TemplateModelException {
                 checkMethodArgCount(args, 1);
-                TemplateModel arg = (TemplateModel) args.get(0);
+                TemplateModel arg = args.get(0);
                 int size = m_seq.size();
                 for (int i = 0; i < size; i++) {
                     if (modelsEqual(i, m_seq.get(i), arg, m_env))
@@ -364,11 +364,11 @@ class BuiltInsForSequences {
     
     static class seq_index_ofBI extends ASTExpBuiltIn {
         
-        private class BIMethod implements TemplateMethodModelEx {
+        private class BIMethod implements TemplateMethodModel {
             
-            protected final TemplateSequenceModel m_seq;
-            protected final TemplateCollectionModel m_col;
-            protected final Environment m_env;
+            final TemplateSequenceModel m_seq;
+            final TemplateCollectionModel m_col;
+            final Environment m_env;
 
             private BIMethod(Environment env)
                     throws TemplateException {
@@ -395,12 +395,12 @@ class BuiltInsForSequences {
             }
 
             @Override
-            public final Object exec(List args)
+            public final TemplateModel execute(List<? extends TemplateModel> args)
                     throws TemplateModelException {
                 int argCnt = args.size();
                 checkMethodArgCount(argCnt, 1, 2);
                 
-                TemplateModel target = (TemplateModel) args.get(0);
+                TemplateModel target = args.get(0);
                 int foundAtIdx;
                 if (argCnt > 1) {
                     int startIndex = getNumberMethodArg(args, 1).intValue();
@@ -423,7 +423,7 @@ class BuiltInsForSequences {
                 return findInCol(target, 0, Integer.MAX_VALUE);
             }
             
-            protected int findInCol(TemplateModel target, int startIndex)
+            int findInCol(TemplateModel target, int startIndex)
                     throws TemplateModelException {
                 if (m_dir == 1) {
                     return findInCol(target, startIndex, Integer.MAX_VALUE);
@@ -432,7 +432,7 @@ class BuiltInsForSequences {
                 }
             }
         
-            protected int findInCol(TemplateModel target,
+            int findInCol(TemplateModel target,
                     final int allowedRangeStart, final int allowedRangeEnd)
                     throws TemplateModelException {
                 if (allowedRangeEnd < 0) return -1;
@@ -525,7 +525,7 @@ class BuiltInsForSequences {
     }
 
     static class sort_byBI extends sortBI {
-        class BIMethod implements TemplateMethodModelEx {
+        class BIMethod implements TemplateMethodModel {
             TemplateSequenceModel seq;
             
             BIMethod(TemplateSequenceModel seq) {
@@ -533,7 +533,7 @@ class BuiltInsForSequences {
             }
             
             @Override
-            public Object exec(List args)
+            public TemplateModel execute(List<? extends TemplateModel> args)
                     throws TemplateModelException {
                 // Should be:
                 // checkMethodArgCount(args, 1);
@@ -549,18 +549,14 @@ class BuiltInsForSequences {
                     int ln = seq.size();
                     subvars = new String[ln];
                     for (int i = 0; i < ln; i++) {
-                        Object item = seq.get(i);
-                        try {
-                            subvars[i] = ((TemplateScalarModel) item)
-                                    .getAsString();
-                        } catch (ClassCastException e) {
-                            if (!(item instanceof TemplateScalarModel)) {
-                                throw new _TemplateModelException(
-                                        "The argument to ?", key, "(key), when it's a sequence, must be a "
-                                        + "sequence of strings, but the item at index ", Integer.valueOf(i),
-                                        " is not a string.");
-                            }
+                        TemplateModel item = seq.get(i);
+                        if (!(item instanceof  TemplateScalarModel)) {
+                            throw new _TemplateModelException(
+                                    "The argument to ?", key, "(key), when it's a sequence, must be a "
+                                    + "sequence of strings, but the item at index ", i,
+                                    " is not a string.");
                         }
+                        subvars[i] = ((TemplateScalarModel) item).getAsString();
                     }
                 } else {
                     throw new _TemplateModelException(