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/03/01 10:26:43 UTC

incubator-freemarker git commit: Java methods (when using DefaultObjectWrapper) won't be accessible as sequences anyore. That is, earlier, instead of obj.m(1), you could write obj.m[1]. This strange feature has led to some tricky cases, while almost nobo

Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 780b76a6e -> 5932e29b4


Java methods (when using DefaultObjectWrapper) won't be accessible as sequences anyore. That is, earlier, instead of obj.m(1), you could write obj.m[1]. This strange feature has led to some tricky cases, while almost nobody has utilized it.


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

Branch: refs/heads/3
Commit: 5932e29b414f477827fd22debde5ee2af448990b
Parents: 780b76a
Author: ddekany <dd...@apache.org>
Authored: Wed Mar 1 11:26:27 2017 +0100
Committer: ddekany <dd...@apache.org>
Committed: Wed Mar 1 11:26:27 2017 +0100

----------------------------------------------------------------------
 .../core/BuiltInsForMultipleTypes.java          |   4 -
 .../freemarker/core/model/impl/BeanModel.java   |   4 +-
 .../core/model/impl/DefaultObjectWrapper.java   |   2 +-
 .../core/model/impl/JavaMethodModel.java        | 105 +++++++++++++++
 .../core/model/impl/OverloadedMethods.java      |   2 +-
 .../core/model/impl/OverloadedMethodsModel.java |  16 +--
 .../core/model/impl/SimpleMethodModel.java      | 133 -------------------
 .../freemarker/core/model/impl/StaticModel.java |   2 +-
 .../apache/freemarker/core/util/FTLUtil.java    |   5 -
 .../jsp/CustomTagAndELFunctionCombiner.java     |  44 ++----
 src/manual/en_US/FM3-CHANGE-LOG.txt             |   5 +-
 .../expected/default-object-wrapper.txt         |   1 -
 .../templatesuite/expected/type-builtins.txt    |   4 +-
 .../templates/default-object-wrapper.ftl        |   3 +-
 14 files changed, 129 insertions(+), 201 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
index d7f0249..53286b3 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
@@ -42,8 +42,6 @@ import org.apache.freemarker.core.model.TemplateTransformModel;
 import org.apache.freemarker.core.model.impl.SimpleDate;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.OverloadedMethodsModel;
-import org.apache.freemarker.core.model.impl.SimpleMethodModel;
 import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.valueformat.TemplateDateFormat;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormat;
@@ -327,7 +325,6 @@ class BuiltInsForMultipleTypes {
             TemplateModel tm = target.eval(env);
             target.assertNonNull(tm, env);
             return (tm instanceof TemplateSequenceModel || tm instanceof TemplateCollectionModel)
-                    && !(tm instanceof SimpleMethodModel || tm instanceof OverloadedMethodsModel)
                     ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
         }
     }
@@ -416,7 +413,6 @@ class BuiltInsForMultipleTypes {
             TemplateModel tm = target.eval(env);
             target.assertNonNull(tm, env);
             return tm instanceof TemplateSequenceModel
-                    && !(tm instanceof OverloadedMethodsModel || tm instanceof SimpleMethodModel) // [FM3] Until BW fixed
                     ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java b/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
index b0201b6..11b0175 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
@@ -213,7 +213,7 @@ public class BeanModel
         if (desc instanceof IndexedPropertyDescriptor) {
             Method readMethod = ((IndexedPropertyDescriptor) desc).getIndexedReadMethod(); 
             resultModel = cachedModel = 
-                new SimpleMethodModel(object, readMethod, 
+                new JavaMethodModel(object, readMethod,
                         ClassIntrospector.getArgTypes(classInfo, readMethod), wrapper);
         } else if (desc instanceof PropertyDescriptor) {
             PropertyDescriptor pd = (PropertyDescriptor) desc;
@@ -224,7 +224,7 @@ public class BeanModel
             // cachedModel remains null, as we don't cache these
         } else if (desc instanceof Method) {
             Method method = (Method) desc;
-            resultModel = cachedModel = new SimpleMethodModel(
+            resultModel = cachedModel = new JavaMethodModel(
                     object, method, ClassIntrospector.getArgTypes(classInfo, method), wrapper);
         } else if (desc instanceof OverloadedMethods) {
             resultModel = cachedModel = new OverloadedMethodsModel(

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
index 66aa016..8478892 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
@@ -740,7 +740,7 @@ public class DefaultObjectWrapper implements RichObjectWrapper, WriteProtectable
      * @since 2.3.22
      */
     public TemplateMethodModelEx wrap(Object object, Method method) {
-        return new SimpleMethodModel(object, method, method.getParameterTypes(), this);
+        return new JavaMethodModel(object, method, method.getParameterTypes(), this);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/JavaMethodModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/JavaMethodModel.java b/src/main/java/org/apache/freemarker/core/model/impl/JavaMethodModel.java
new file mode 100644
index 0000000..03fea54
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/model/impl/JavaMethodModel.java
@@ -0,0 +1,105 @@
+/*
+ * 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.model.impl;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel;
+import org.apache.freemarker.core.model.TemplateMethodModelEx;
+import org.apache.freemarker.core.model.TemplateModelException;
+
+/**
+ * Wraps a {@link Method} into the {@link TemplateMethodModelEx} interface. It is used by {@link BeanModel} to wrap
+ * non-overloaded methods.
+ */
+public final class JavaMethodModel extends SimpleMethod implements TemplateMethodModelEx,
+        _UnexpectedTypeErrorExplainerTemplateModel {
+    private final Object object;
+    private final DefaultObjectWrapper wrapper;
+
+    /**
+     * Creates a model for a specific method on a specific object.
+     * @param object the object to call the method on, or {@code null} for a static method.
+     * @param method the method that will be invoked.
+     * @param argTypes Either pass in {@code Method#getParameterTypes() method.getParameterTypes()} here,
+     *          or reuse an earlier result of that call (for speed). Not {@code null}.
+     */
+    JavaMethodModel(Object object, Method method, Class[] argTypes, DefaultObjectWrapper wrapper) {
+        super(method, argTypes);
+        this.object = object;
+        this.wrapper = wrapper;
+    }
+
+    /**
+     * Invokes the method, passing it the arguments from the list.
+     */
+    @Override
+    public Object exec(List arguments) throws TemplateModelException {
+        try {
+            return wrapper.invokeMethod(object, (Method) getMember(), 
+                    unwrapArguments(arguments, wrapper));
+        } catch (TemplateModelException e) {
+            throw e;
+        } catch (Exception e) {
+            throw _MethodUtil.newInvocationTemplateModelException(object, getMember(), e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getMember().toString();
+    }
+
+    /**
+     * Implementation of experimental interface; don't use it, no backward compatibility guarantee!
+     */
+    @Override
+    public Object[] explainTypeError(Class[] expectedClasses) {
+        final Member member = getMember();
+        if (!(member instanceof Method)) {
+            return null;  // This shouldn't occur
+        }
+        Method m = (Method) member;
+        
+        final Class returnType = m.getReturnType();
+        if (returnType == null || returnType == void.class || returnType == Void.class) {
+            return null;  // Calling it won't help
+        }
+        
+        String mName = m.getName();
+        if (mName.startsWith("get") && mName.length() > 3 && Character.isUpperCase(mName.charAt(3))
+                && (m.getParameterTypes().length == 0)) {
+            return new Object[] {
+                    "Maybe using obj.something instead of obj.getSomething will yield the desired value." };
+        } else if (mName.startsWith("is") && mName.length() > 2 && Character.isUpperCase(mName.charAt(2))
+                && (m.getParameterTypes().length == 0)) {
+            return new Object[] {
+                    "Maybe using obj.something instead of obj.isSomething will yield the desired value." };
+        } else {
+            return new Object[] {
+                    "Maybe using obj.something(",
+                    (m.getParameterTypes().length != 0 ? "params" : ""),
+                    ") instead of obj.something will yield the desired value" };
+        }
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethods.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethods.java b/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethods.java
index e352bcf..83bac83 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethods.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethods.java
@@ -201,7 +201,7 @@ final class OverloadedMethods {
                     }
                     if (paramType != null) {
                         if (paramType.isAssignableFrom(String.class) && !paramType.isAssignableFrom(tmArg.getClass())) {
-                            edb.tip(SimpleMethodModel.MARKUP_OUTPUT_TO_STRING_TIP);
+                            edb.tip(JavaMethodModel.MARKUP_OUTPUT_TO_STRING_TIP);
                             return;
                         }
                     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethodsModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethodsModel.java b/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethodsModel.java
index c8b3681..a96aadf 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethodsModel.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/OverloadedMethodsModel.java
@@ -20,20 +20,17 @@
 package org.apache.freemarker.core.model.impl;
 
 
-import java.util.Collections;
 import java.util.List;
 
 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.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
 
 /**
  * Wraps a set of same-name overloaded methods behind {@link TemplateMethodModel} interface,
  * like if it was a single method, chooses among them behind the scenes on call-time based on the argument values.
  */
-public class OverloadedMethodsModel implements TemplateMethodModelEx, TemplateSequenceModel {
+class OverloadedMethodsModel implements TemplateMethodModelEx {
     private final Object object;
     private final OverloadedMethods overloadedMethods;
     private final DefaultObjectWrapper wrapper;
@@ -65,15 +62,4 @@ public class OverloadedMethodsModel implements TemplateMethodModelEx, TemplateSe
                     e);
         }
     }
-
-    @Override
-    public TemplateModel get(int index) throws TemplateModelException {
-        return (TemplateModel) exec(Collections.singletonList(
-                new SimpleNumber(Integer.valueOf(index))));
-    }
-
-    @Override
-    public int size() throws TemplateModelException {
-        throw new TemplateModelException("?size is unsupported for " + getClass().getName());
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/SimpleMethodModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/SimpleMethodModel.java b/src/main/java/org/apache/freemarker/core/model/impl/SimpleMethodModel.java
deleted file mode 100644
index 943d8f0..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/SimpleMethodModel.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.model.impl;
-
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
-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.util.FTLUtil;
-
-/**
- * A class that will wrap a reflected method call into a
- * {@link org.apache.freemarker.core.model.TemplateMethodModel} interface. 
- * It is used by {@link BeanModel} to wrap reflected method calls
- * for non-overloaded methods.
- */
-public final class SimpleMethodModel extends SimpleMethod
-    implements
-    TemplateMethodModelEx,
-    TemplateSequenceModel,
-    _UnexpectedTypeErrorExplainerTemplateModel {
-    private final Object object;
-    private final DefaultObjectWrapper wrapper;
-
-    /**
-     * Creates a model for a specific method on a specific object.
-     * @param object the object to call the method on, or {@code null} for a static method.
-     * @param method the method that will be invoked.
-     * @param argTypes Either pass in {@code Method#getParameterTypes() method.getParameterTypes()} here,
-     *          or reuse an earlier result of that call (for speed). Not {@code null}.
-     */
-    SimpleMethodModel(Object object, Method method, Class[] argTypes, 
-            DefaultObjectWrapper wrapper) {
-        super(method, argTypes);
-        this.object = object;
-        this.wrapper = wrapper;
-    }
-
-    /**
-     * Invokes the method, passing it the arguments from the list.
-     */
-    @Override
-    public Object exec(List arguments)
-        throws TemplateModelException {
-        try {
-            return wrapper.invokeMethod(object, (Method) getMember(), 
-                    unwrapArguments(arguments, wrapper));
-        } catch (TemplateModelException e) {
-            throw e;
-        } catch (Exception e) {
-            throw _MethodUtil.newInvocationTemplateModelException(object, getMember(), e);
-        }
-    }
-    
-    @Override
-    public TemplateModel get(int index) throws TemplateModelException {
-        return (TemplateModel) exec(Collections.singletonList(
-                new SimpleNumber(Integer.valueOf(index))));
-    }
-
-    @Override
-    public int size() throws TemplateModelException {
-        throw new TemplateModelException(
-                "Getting the number of items or enumerating the items is not supported on this "
-                + FTLUtil.getTypeDescription(this) + " value.\n"
-                + "("
-                + "Hint 1: Maybe you wanted to call this method first and then do something with its return value. "
-                + "Hint 2: Getting items by intex possibly works, hence it's a \"+sequence\"."
-                + ")");
-    }
-    
-    @Override
-    public String toString() {
-        return getMember().toString();
-    }
-
-    /**
-     * Implementation of experimental interface; don't use it, no backward compatibility guarantee!
-     */
-    @Override
-    public Object[] explainTypeError(Class[] expectedClasses) {
-        final Member member = getMember();
-        if (!(member instanceof Method)) {
-            return null;  // This shouldn't occur
-        }
-        Method m = (Method) member;
-        
-        final Class returnType = m.getReturnType();
-        if (returnType == null || returnType == void.class || returnType == Void.class) {
-            return null;  // Calling it won't help
-        }
-        
-        String mName = m.getName();
-        if (mName.startsWith("get") && mName.length() > 3 && Character.isUpperCase(mName.charAt(3))
-                && (m.getParameterTypes().length == 0)) {
-            return new Object[] {
-                    "Maybe using obj.something instead of obj.getSomething will yield the desired value." };
-        } else if (mName.startsWith("is") && mName.length() > 2 && Character.isUpperCase(mName.charAt(2))
-                && (m.getParameterTypes().length == 0)) {
-            return new Object[] {
-                    "Maybe using obj.something instead of obj.isSomething will yield the desired value." };
-        } else {
-            return new Object[] {
-                    "Maybe using obj.something(",
-                    (m.getParameterTypes().length != 0 ? "params" : ""),
-                    ") instead of obj.something will yield the desired value" };
-        }
-    }
-    
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/model/impl/StaticModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/StaticModel.java b/src/main/java/org/apache/freemarker/core/model/impl/StaticModel.java
index 1a6263c..533173b 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/StaticModel.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/StaticModel.java
@@ -166,7 +166,7 @@ final class StaticModel implements TemplateHashModelEx {
                 Object value = entry.getValue();
                 if (value instanceof Method) {
                     Method method = (Method) value;
-                    entry.setValue(new SimpleMethodModel(null, method, 
+                    entry.setValue(new JavaMethodModel(null, method,
                             method.getParameterTypes(), wrapper));
                 } else if (value instanceof OverloadedMethods) {
                     entry.setValue(new OverloadedMethodsModel(null, (OverloadedMethods) value, wrapper));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/FTLUtil.java b/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
index 619eb48..c03c9ca 100644
--- a/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
+++ b/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
@@ -33,7 +33,6 @@ import org.apache.freemarker.core.model.TemplateHashModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx;
 import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 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.TemplateModelIterator;
 import org.apache.freemarker.core.model.TemplateNodeModel;
@@ -45,8 +44,6 @@ import org.apache.freemarker.core.model.TemplateTransformModel;
 import org.apache.freemarker.core.model.WrapperTemplateModel;
 import org.apache.freemarker.core.model.impl.BeanAndStringModel;
 import org.apache.freemarker.core.model.impl.BeanModel;
-import org.apache.freemarker.core.model.impl.OverloadedMethodsModel;
-import org.apache.freemarker.core.model.impl.SimpleMethodModel;
 
 /**
  * Static utility methods that perform tasks specific to the FreeMarker Template Language (FTL).
@@ -716,8 +713,6 @@ public final class FTLUtil {
             } else {
                 return null;
             }
-        } else if (tm instanceof SimpleMethodModel || tm instanceof OverloadedMethodsModel) {
-            return TemplateMethodModelEx.class;
         } else {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/main/java/org/apache/freemarker/servlet/jsp/CustomTagAndELFunctionCombiner.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/servlet/jsp/CustomTagAndELFunctionCombiner.java b/src/main/java/org/apache/freemarker/servlet/jsp/CustomTagAndELFunctionCombiner.java
index e9e9bf4..cb692d7 100644
--- a/src/main/java/org/apache/freemarker/servlet/jsp/CustomTagAndELFunctionCombiner.java
+++ b/src/main/java/org/apache/freemarker/servlet/jsp/CustomTagAndELFunctionCombiner.java
@@ -31,9 +31,8 @@ import org.apache.freemarker.core.model.TemplateDirectiveModel;
 import org.apache.freemarker.core.model.TemplateMethodModelEx;
 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.TemplateTransformModel;
-import org.apache.freemarker.core.model.impl.SimpleMethodModel;
+import org.apache.freemarker.core.model.impl.JavaMethodModel;
 import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.util._ClassUtil;
 
@@ -53,15 +52,15 @@ class CustomTagAndELFunctionCombiner {
      */
     static TemplateModel combine(TemplateModel customTag, TemplateMethodModelEx elFunction) {
         if (customTag instanceof TemplateDirectiveModel) {
-            return elFunction instanceof SimpleMethodModel //
+            return elFunction instanceof JavaMethodModel //
                     ? new TemplateDirectiveModelAndSimpleMethodModel( //
-                            (TemplateDirectiveModel) customTag, (SimpleMethodModel) elFunction) //
+                            (TemplateDirectiveModel) customTag, (JavaMethodModel) elFunction) //
                     : new TemplateDirectiveModelAndTemplateMethodModelEx( //
                             (TemplateDirectiveModel) customTag, elFunction);
         } else if (customTag instanceof TemplateTransformModel) {
-            return (elFunction instanceof SimpleMethodModel)
+            return (elFunction instanceof JavaMethodModel)
                     ? new TemplateTransformModelAndSimpleMethodModel( //
-                            (TemplateTransformModel) customTag, (SimpleMethodModel) elFunction) //
+                            (TemplateTransformModel) customTag, (JavaMethodModel) elFunction) //
                     : new TemplateTransformModelAndTemplateMethodModelEx( //
                             (TemplateTransformModel) customTag, elFunction);
         } else {
@@ -92,14 +91,14 @@ class CustomTagAndELFunctionCombiner {
     }
 
     private static class TemplateDirectiveModelAndSimpleMethodModel extends CombinedTemplateModel
-            implements TemplateDirectiveModel, TemplateMethodModelEx, TemplateSequenceModel,
+            implements TemplateDirectiveModel, TemplateMethodModelEx,
             _UnexpectedTypeErrorExplainerTemplateModel {
 
         private final TemplateDirectiveModel templateDirectiveModel;
-        private final SimpleMethodModel simpleMethodModel;
+        private final JavaMethodModel simpleMethodModel;
 
         public TemplateDirectiveModelAndSimpleMethodModel( //
-                TemplateDirectiveModel templateDirectiveModel, SimpleMethodModel simpleMethodModel) {
+                TemplateDirectiveModel templateDirectiveModel, JavaMethodModel simpleMethodModel) {
             this.templateDirectiveModel = templateDirectiveModel;
             this.simpleMethodModel = simpleMethodModel;
         }
@@ -120,16 +119,6 @@ class CustomTagAndELFunctionCombiner {
             return simpleMethodModel.explainTypeError(expectedClasses);
         }
 
-        @Override
-        public TemplateModel get(int index) throws TemplateModelException {
-            return simpleMethodModel.get(index);
-        }
-
-        @Override
-        public int size() throws TemplateModelException {
-            return simpleMethodModel.size();
-        }
-
     }
 
     private static class TemplateDirectiveModelAndTemplateMethodModelEx extends CombinedTemplateModel
@@ -182,14 +171,13 @@ class CustomTagAndELFunctionCombiner {
     }
 
     private static class TemplateTransformModelAndSimpleMethodModel extends CombinedTemplateModel
-            implements TemplateTransformModel, TemplateMethodModelEx, TemplateSequenceModel,
-            _UnexpectedTypeErrorExplainerTemplateModel {
+            implements TemplateTransformModel, TemplateMethodModelEx, _UnexpectedTypeErrorExplainerTemplateModel {
 
         private final TemplateTransformModel templateTransformModel;
-        private final SimpleMethodModel simpleMethodModel;
+        private final JavaMethodModel simpleMethodModel;
 
         public TemplateTransformModelAndSimpleMethodModel( //
-                TemplateTransformModel templateTransformModel, SimpleMethodModel simpleMethodModel) {
+                TemplateTransformModel templateTransformModel, JavaMethodModel simpleMethodModel) {
             this.templateTransformModel = templateTransformModel;
             this.simpleMethodModel = simpleMethodModel;
         }
@@ -205,16 +193,6 @@ class CustomTagAndELFunctionCombiner {
         }
 
         @Override
-        public TemplateModel get(int index) throws TemplateModelException {
-            return simpleMethodModel.get(index);
-        }
-
-        @Override
-        public int size() throws TemplateModelException {
-            return simpleMethodModel.size();
-        }
-
-        @Override
         public Writer getWriter(Writer out, Map args) throws TemplateModelException, IOException {
             return templateTransformModel.getWriter(out, args);
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/manual/en_US/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/src/manual/en_US/FM3-CHANGE-LOG.txt b/src/manual/en_US/FM3-CHANGE-LOG.txt
index 04e1d94..a13f336 100644
--- a/src/manual/en_US/FM3-CHANGE-LOG.txt
+++ b/src/manual/en_US/FM3-CHANGE-LOG.txt
@@ -121,4 +121,7 @@ the FreeMarer 3 changelog here:
 - Removed BeansWrapper, which was the superclass of DefaultObjectWrapper, but wasn't recommended to be used as is.
   Removed many BeansWrapper-related classes that DefaultObjectWrapper doesn't use. This includes ModelCache and
   related classes, because DefaultObjectWrapper has only used the cache for "generic" classes (because that's where it
-  has fallen back to BeansWrapper.wrap), which is inconsistent and doesn't worth the caching overhead and complexity.
\ No newline at end of file
+  has fallen back to BeansWrapper.wrap), which is inconsistent and doesn't worth the caching overhead and complexity.
+- Java methods (when using DefaultObjectWrapper) won't be accessible as sequences anyore. That is, earlier, instead of
+  obj.m(1), you could write obj.m[1]. This strange feature has led to some tricky cases, while almost nobody has
+  utilized it.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/default-object-wrapper.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/expected/default-object-wrapper.txt b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/default-object-wrapper.txt
index ab41e26..4066e12 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/expected/default-object-wrapper.txt
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/default-object-wrapper.txt
@@ -33,7 +33,6 @@ foo-value
 hasfoo
 nobaz
 bar-value-0
-bar-value-0
 foo-value
 overloaded-int-1
 overloaded-String-String

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/type-builtins.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/expected/type-builtins.txt b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/type-builtins.txt
index 924bbe8..89fa676 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/expected/type-builtins.txt
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/type-builtins.txt
@@ -29,5 +29,5 @@ StNuBoMeTaMaHaHxSeCoCxEnInDiNo
 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0
-0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
-0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
+0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 1 0 0 0 0 0 0 0 0 0 0 0

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5932e29b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/default-object-wrapper.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/default-object-wrapper.ftl b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/default-object-wrapper.ftl
index d44f26e..1915998 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/default-object-wrapper.ftl
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/default-object-wrapper.ftl
@@ -33,7 +33,6 @@ ${map?api.get(objKey)}
 ${obj.foo}
 <#if obj.foo?exists>hasfoo<#else>nofoo</#if>
 <#if obj.baz?exists>hasbaz<#else>nobaz</#if>
-${obj.bar[0]}
 ${obj.bar(0)}
 ${obj.getFoo()}
 ${obj.overloaded(1?int)}
@@ -42,7 +41,7 @@ ${resourceBundle.message}
 ${resourceBundle("format", date)}
 <#assign static = statics["org.apache.freemarker.test.templatesuite.models.BeanTestClass"]>
 ${static.staticMethod()}
-${static.staticOverloaded[1]}
+${static.staticOverloaded(1)}
 ${static.staticOverloaded("String")}
 ${static.STATIC_FINAL_FIELD}
 ${static.STATIC_FIELD}