You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/05/14 10:53:09 UTC

[26/51] [partial] incubator-freemarker git commit: Migrated from Ant to Gradle, and modularized the project. This is an incomplete migration; there are some TODO-s in the build scripts, and release related tasks are still missing. What works: Building th

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperAndUnwrapper.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperAndUnwrapper.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperAndUnwrapper.java
new file mode 100644
index 0000000..3494eb7
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperAndUnwrapper.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+/**
+ * <b>Experimental - subject to change:</b> Adds functionality to {@link ObjectWrapper} that creates a plain Java object
+ * from a {@link TemplateModel}. This is usually implemented by {@link ObjectWrapper}-s and reverses
+ * {@link ObjectWrapper#wrap(Object)}. However, an implementation of this interface should make a reasonable effort to
+ * "unwrap" {@link TemplateModel}-s that wasn't the result of object wrapping (such as those created directly in FTL),
+ * or which was created by another {@link ObjectWrapper}. The author of an {@link ObjectWrapperAndUnwrapper} should be
+ * aware of the {@link TemplateModelAdapter} and {@link WrapperTemplateModel} interfaces, which should be used for
+ * unwrapping if the {@link TemplateModel} implements them.
+ * 
+ * <p>
+ * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it
+ * shouldn't be implemented outside FreeMarker yet.
+ * 
+ * @since 2.3.22
+ */
+public interface ObjectWrapperAndUnwrapper extends ObjectWrapper {
+
+    /**
+     * Indicates that while the unwrapping is <em>maybe</em> possible, the result surely can't be the instance of the
+     * desired class, nor it can be {@code null}.
+     * 
+     * @see #tryUnwrapTo(TemplateModel, Class)
+     * 
+     * @since 2.3.22
+     */
+    Object CANT_UNWRAP_TO_TARGET_CLASS = new Object();
+
+    /**
+     * Unwraps a {@link TemplateModel} to a plain Java object.
+     * 
+     * @return The plain Java object. Can be {@code null}, if {@code null} is the appropriate Java value to represent
+     *         the template model. {@code null} must not be used to indicate an unwrapping failure. It must NOT be
+     *         {@link #CANT_UNWRAP_TO_TARGET_CLASS}.
+     * 
+     * @throws TemplateModelException
+     *             If the unwrapping fails from any reason.
+     * 
+     * @see #tryUnwrapTo(TemplateModel, Class)
+     * 
+     * @since 2.3.22
+     */
+    Object unwrap(TemplateModel tm) throws TemplateModelException;
+
+    /**
+     * Attempts to unwrap a {@link TemplateModel} to a plain Java object that's the instance of the given class (or is
+     * {@code null}).
+     * 
+     * @param targetClass
+     *            The class that the return value must be an instance of (except when the return value is {@code null}).
+     *            Can't be {@code null}; if the caller doesn't care, it should either use {#unwrap(TemplateModel)}, or
+     *            {@code Object.class} as the parameter value.
+     *
+     * @return The unwrapped value that's either an instance of {@code targetClass}, or is {@code null} (if {@code null}
+     *         is the appropriate Java value to represent the template model), or is
+     *         {@link #CANT_UNWRAP_TO_TARGET_CLASS} if the unwrapping can't satisfy the {@code targetClass} (nor the
+     *         result can be {@code null}). However, {@link #CANT_UNWRAP_TO_TARGET_CLASS} must not be returned if the
+     *         {@code targetClass} parameter was {@code Object.class}.
+     * 
+     * @throws TemplateModelException
+     *             If the unwrapping fails for a reason than doesn't fit the meaning of the
+     *             {@link #CANT_UNWRAP_TO_TARGET_CLASS} return value.
+     * 
+     * @see #unwrap(TemplateModel)
+     * 
+     * @since 2.3.22
+     */
+    Object tryUnwrapTo(TemplateModel tm, Class<?> targetClass) throws TemplateModelException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperWithAPISupport.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperWithAPISupport.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperWithAPISupport.java
new file mode 100644
index 0000000..102a2f0
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/ObjectWrapperWithAPISupport.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+/**
+ * <b>Experimental - subject to change:</b> Implemented by {@link ObjectWrapper}-s to help {@link TemplateModel}-s to
+ * implement the {@code someValue?api} operation.
+ * 
+ * <p>
+ * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it
+ * shouldn't be implemented outside FreeMarker yet.
+ * 
+ * @since 2.3.22
+ */
+public interface ObjectWrapperWithAPISupport extends ObjectWrapper {
+
+    /**
+     * Wraps an object to a {@link TemplateModel} that exposes the object's "native" (usually, Java) API.
+     * 
+     * @param obj
+     *            The object for which the API model has to be returned. Shouldn't be {@code null}.
+     * 
+     * @return The {@link TemplateModel} through which the API of the object can be accessed. Can't be {@code null}.
+     * 
+     * @since 2.3.22
+     */
+    TemplateHashModel wrapAsAPI(Object obj) throws TemplateModelException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/RichObjectWrapper.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/RichObjectWrapper.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/RichObjectWrapper.java
new file mode 100644
index 0000000..5dfa3be
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/RichObjectWrapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * <b>Experimental - subject to change:</b> Union of the interfaces that a typical feature rich {@link ObjectWrapper} is
+ * expected to implement.
+ * 
+ * <p>
+ * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it
+ * shouldn't be implemented outside FreeMarker yet.
+ * 
+ * @since 2.3.22
+ */
+public interface RichObjectWrapper extends ObjectWrapperAndUnwrapper, ObjectWrapperWithAPISupport {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/SerializableTemplateBooleanModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/SerializableTemplateBooleanModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/SerializableTemplateBooleanModel.java
new file mode 100644
index 0000000..b01e7df
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/SerializableTemplateBooleanModel.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+interface SerializableTemplateBooleanModel extends TemplateBooleanModel, Serializable {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateBooleanModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateBooleanModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateBooleanModel.java
new file mode 100644
index 0000000..555e619
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateBooleanModel.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+/**
+ * "boolean" template language data type; same as in Java; either {@code true} or {@code false}.
+ * 
+ * <p>
+ * Objects of this type should be immutable, that is, calling {@link #getAsBoolean()} should always return the same
+ * value as for the first time.
+ */
+public interface TemplateBooleanModel extends TemplateModel, Serializable {
+
+    /**
+     * @return whether to interpret this object as true or false in a boolean context
+     */
+    boolean getAsBoolean() throws TemplateModelException;
+    
+    /**
+     * A singleton object to represent boolean false
+     */
+    TemplateBooleanModel FALSE = new FalseTemplateBooleanModel();
+
+    /**
+     * A singleton object to represent boolean true
+     */
+    TemplateBooleanModel TRUE = new TrueTemplateBooleanModel();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModel.java
new file mode 100644
index 0000000..e870c2f
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModel.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+import java.util.Collection;
+
+/**
+ * "collection" template language data type: a collection of values that can be enumerated, but can't be or not meant to
+ * be accessed by index or key. As such, this is not a super-interface of {@link TemplateSequenceModel}, and
+ * implementations of that interface needn't also implement this interface just because they can. They should though, if
+ * enumeration with this interface is significantly faster than enumeration by index. The {@code #list} directive will
+ * enumerate using this interface if it's available.
+ * 
+ * <p>
+ * The enumeration should be repeatable if that's possible with reasonable effort, otherwise a second enumeration
+ * attempt is allowed to throw an {@link TemplateModelException}. Generally, the interface user Java code need not
+ * handle that kind of exception, as in practice only the template author can handle it, by not listing such collections
+ * twice.
+ * 
+ * <p>
+ * Note that to wrap Java's {@link Collection}, you should implement {@link TemplateCollectionModelEx}, not just this
+ * interface.
+ */
+public interface TemplateCollectionModel extends TemplateModel {
+
+    /**
+     * Retrieves a template model iterator that is used to iterate over the elements in this collection.
+     */
+    TemplateModelIterator iterator() throws TemplateModelException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
new file mode 100644
index 0000000..92f0e3a
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+import java.util.Collection;
+
+/**
+ * "extended collection" template language data type: Adds size/emptiness querybility and "contains" test to
+ * {@link TemplateCollectionModel}. The added extra operations is provided by all Java {@link Collection}-s, and
+ * this interface was added to make that accessible for templates too.
+ *
+ * @since 2.3.22
+ */
+public interface TemplateCollectionModelEx extends TemplateCollectionModel {
+
+    /**
+     * Returns the number items in this collection, or {@link Integer#MAX_VALUE}, if there are more than
+     * {@link Integer#MAX_VALUE} items.
+     */
+    int size() throws TemplateModelException;
+
+    /**
+     * Returns if the collection contains any elements. This differs from {@code size() != 0} only in that the exact
+     * number of items need not be calculated.
+     */
+    boolean isEmpty() throws TemplateModelException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDateModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDateModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDateModel.java
new file mode 100644
index 0000000..ab85e97
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDateModel.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * "date", "time" and "date-time" template language data types: corresponds to {@link java.util.Date}. Contrary to Java,
+ * FreeMarker distinguishes date (no time part), time and date-time values.
+ * 
+ * <p>
+ * Objects of this type should be immutable, that is, calling {@link #getAsDate()} and {@link #getDateType()} should
+ * always return the same value as for the first time.
+ */
+public interface TemplateDateModel extends TemplateModel {
+    
+    /**
+     * It is not known whether the date represents a date, a time, or a date-time value.
+     * This often leads to exceptions in templates due to ambiguities it causes, so avoid it if possible.
+     */
+    int UNKNOWN = 0;
+
+    /**
+     * The date model represents a time value (no date part).
+     */
+    int TIME = 1;
+
+    /**
+     * The date model represents a date value (no time part).
+     */
+    int DATE = 2;
+
+    /**
+     * The date model represents a date-time value (also known as timestamp).
+     */
+    int DATETIME = 3;
+    
+    List TYPE_NAMES =
+        Collections.unmodifiableList(
+            Arrays.asList(
+                    "UNKNOWN", "TIME", "DATE", "DATETIME"));
+    /**
+     * Returns the date value. The return value must not be {@code null}.
+     */
+    Date getAsDate() throws TemplateModelException;
+
+    /**
+     * Returns the type of the date. It can be any of {@link #TIME}, 
+     * {@link #DATE}, or {@link #DATETIME}.
+     */
+    int getDateType();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveBody.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveBody.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveBody.java
new file mode 100644
index 0000000..bb54eb4
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveBody.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.freemarker.core.TemplateException;
+
+/**
+ * Represents the nested content of a directive ({@link TemplateDirectiveModel}) invocation. An implementation of this 
+ * class is passed to {@link TemplateDirectiveModel#execute(org.apache.freemarker.core.Environment, 
+ * java.util.Map, TemplateModel[], TemplateDirectiveBody)}. The implementation of the method is 
+ * free to invoke it for any number of times, with any writer.
+ *
+ * @since 2.3.11
+ */
+public interface TemplateDirectiveBody {
+    /**
+     * Renders the body of the directive body to the specified writer. The 
+     * writer is not flushed after the rendering. If you pass the environment's
+     * writer, there is no need to flush it. If you supply your own writer, you
+     * are responsible to flush/close it when you're done with using it (which
+     * might be after multiple renderings).
+     * @param out the writer to write the output to.
+     */
+    void render(Writer out) throws TemplateException, IOException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveModel.java
new file mode 100644
index 0000000..c4020c9
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateDirectiveModel.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.util.DeepUnwrap;
+
+/**
+ * "directive" template language data type: used as user-defined directives 
+ * (much like macros) in templates. They can do arbitrary actions, write arbitrary
+ * text to the template output, and trigger rendering of their nested content for
+ * any number of times.
+ * 
+ * <p>They are used in templates like {@code <@myDirective foo=1 bar="wombat">...</...@myDirective>} (or as
+ * {@code <@myDirective foo=1 bar="wombat" />} - the nested content is optional).
+ *
+ * @since 2.3.11
+ */
+public interface TemplateDirectiveModel extends TemplateModel {
+    /**
+     * Executes this user-defined directive; called by FreeMarker when the user-defined
+     * directive is called in the template.
+     *
+     * @param env the current processing environment. Note that you can access
+     * the output {@link java.io.Writer Writer} by {@link Environment#getOut()}.
+     * @param params the parameters (if any) passed to the directive as a 
+     * map of key/value pairs where the keys are {@link String}-s and the 
+     * values are {@link TemplateModel} instances. This is never 
+     * <code>null</code>. If you need to convert the template models to POJOs,
+     * you can use the utility methods in the {@link DeepUnwrap} class.
+     * @param loopVars an array that corresponds to the "loop variables", in
+     * the order as they appear in the directive call. ("Loop variables" are out-parameters
+     * that are available to the nested body of the directive; see in the Manual.)
+     * You set the loop variables by writing this array. The length of the array gives the
+     * number of loop-variables that the caller has specified.
+     * Never <code>null</code>, but can be a zero-length array.
+     * @param body an object that can be used to render the nested content (body) of
+     * the directive call. If the directive call has no nested content (i.e., it's like
+     * &lt;@myDirective /&gt; or &lt;@myDirective&gt;&lt;/@myDirective&gt;), then this will be
+     * <code>null</code>.
+     *
+     * @throws TemplateException If any problem occurs that's not an {@link IOException} during writing the template
+     *          output.
+     * @throws IOException When writing the template output fails.
+     */
+    void execute(Environment env, Map params, TemplateModel[] loopVars,
+                 TemplateDirectiveBody body) throws TemplateException, IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModel.java
new file mode 100644
index 0000000..647055a
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModel.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+/**
+ * "hash" template language data type: an object that contains other objects accessible through string keys
+ * (sub-variable names).
+ * 
+ * <p>In templates they are used like {@code myHash.myKey} or {@code myHash[myDynamicKey]}. 
+ */
+public interface TemplateHashModel extends TemplateModel {
+    
+    /**
+     * Gets a <tt>TemplateModel</tt> from the hash.
+     *
+     * @param key the name by which the <tt>TemplateModel</tt>
+     * is identified in the template.
+     * @return the <tt>TemplateModel</tt> referred to by the key,
+     * or null if not found.
+     */
+    TemplateModel get(String key) throws TemplateModelException;
+
+    boolean isEmpty() throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx.java
new file mode 100644
index 0000000..c95a21d
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import org.apache.freemarker.core.model.impl.SimpleHash;
+
+/**
+ * "extended hash" template language data type; extends {@link TemplateHashModel} by allowing
+ * iterating through its keys and values.
+ * 
+ * <p>In templates they are used like hashes, but these will also work (among others):
+ * {@code myExtHash?size}, {@code myExtHash?keys}, {@code myExtHash?values}.
+ * @see SimpleHash
+ */
+public interface TemplateHashModelEx extends TemplateHashModel {
+
+    /**
+     * @return the number of key/value mappings in the hash.
+     */
+    int size() throws TemplateModelException;
+
+    /**
+     * @return a collection containing the keys in the hash. Every element of 
+     *      the returned collection must implement the {@link TemplateScalarModel}
+     *      (as the keys of hashes are always strings).
+     */
+    TemplateCollectionModel keys() throws TemplateModelException;
+
+    /**
+     * @return a collection containing the values in the hash. The elements of the
+     * returned collection can be any kind of {@link TemplateModel}-s.
+     */
+    TemplateCollectionModel values() throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx2.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx2.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx2.java
new file mode 100644
index 0000000..86a72b1
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateHashModelEx2.java
@@ -0,0 +1,80 @@
+/*
+ * 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;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Adds key-value pair listing capability to {@link TemplateHashModelEx}. While in many cases that can also be achieved
+ * with {@link #keys()} and then {@link #get(String)}, that has some problems. One is that {@link #get(String)} only
+ * accepts string keys, while {@link #keys()} can return non-string keys too. The other is that calling {@link #keys()}
+ * and then {@link #get(String)} for each key can be slower than listing the key-value pairs in one go.
+ * 
+ * @since 2.3.25
+ */
+public interface TemplateHashModelEx2 extends TemplateHashModelEx {
+
+    /**
+     * @return The iterator that walks through the key-value pairs in the hash. Not {@code null}. 
+     */
+    KeyValuePairIterator keyValuePairIterator() throws TemplateModelException;
+    
+    /**
+     * A key-value pair in a hash; used for {@link KeyValuePairIterator}.
+     *  
+     * @since 2.3.25
+     */
+    interface KeyValuePair {
+        
+        /**
+         * @return Any type of {@link TemplateModel}, maybe {@code null} (if the hash entry key is {@code null}).
+         */
+        TemplateModel getKey() throws TemplateModelException;
+        
+        /**
+         * @return Any type of {@link TemplateModel}, maybe {@code null} (if the hash entry value is {@code null}).
+         */
+        TemplateModel getValue() throws TemplateModelException;
+    }
+    
+    /**
+     * Iterates over the key-value pairs in a hash. This is very similar to an {@link Iterator}, but has a oms item
+     * type, can throw {@link TemplateModelException}-s, and has no {@code remove()} method. 
+     *
+     * @since 2.3.25
+     */
+    interface KeyValuePairIterator {
+        
+        /**
+         * Similar to {@link Iterator#hasNext()}.
+         */
+        boolean hasNext() throws TemplateModelException;
+        
+        /**
+         * Similar to {@link Iterator#next()}.
+         * 
+         * @return Not {@code null}
+         * 
+         * @throws NoSuchElementException
+         */
+        KeyValuePair next() throws TemplateModelException;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMarkupOutputModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMarkupOutputModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMarkupOutputModel.java
new file mode 100644
index 0000000..2215926
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMarkupOutputModel.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.freemarker.core.model;
+
+import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
+import org.apache.freemarker.core.outputformat.OutputFormat;
+
+/**
+ * "markup output" template language data-type; stores markup (some kind of "rich text" / structured format, as opposed
+ * to plain text) that meant to be printed as template output. This type is related to the {@link OutputFormat}
+ * mechanism. Values of this kind are exempt from {@link OutputFormat}-based automatic escaping.
+ * 
+ * <p>
+ * Each implementation of this type has a {@link OutputFormat} subclass pair, whose singleton instance is returned by
+ * {@link #getOutputFormat()}. See more about how markup output values work at {@link OutputFormat}.
+ * 
+ * <p>
+ * Note that {@link TemplateMarkupOutputModel}-s are by design not treated like {@link TemplateScalarModel}-s, and so
+ * the implementations of this interface usually shouldn't implement {@link TemplateScalarModel}. (Because, operations
+ * applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.) If the template
+ * author wants to pass in the "source" of the markup as string somewhere, he should use {@code ?markup_string}.
+ * 
+ * @param <MO>
+ *            Refers to the interface's own type, which is useful in interfaces that extend
+ *            {@link TemplateMarkupOutputModel} (Java Generics trick).
+ * 
+ * @since 2.3.24
+ */
+public interface TemplateMarkupOutputModel<MO extends TemplateMarkupOutputModel<MO>> extends TemplateModel {
+
+    /**
+     * Returns the singleton {@link OutputFormat} object that implements the operations for the "markup output" value.
+     */
+    MarkupOutputFormat<MO> getOutputFormat();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModel.java
new file mode 100644
index 0000000..5bfe7e3
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModel.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * 22 October 1999: This class added by Holger Arendt.
+ */
+
+package org.apache.freemarker.core.model;
+
+import java.util.List;
+
+import org.apache.freemarker.core.Environment;
+
+/**
+ * "method" template language data type: Objects that act like functions. The name comes from that their original
+ * application was calling Java methods via {@link org.apache.freemarker.core.model.impl.DefaultObjectWrapper}.
+ * 
+ * <p>In templates they are used like {@code myMethod("foo", "bar")} or {@code myJavaObject.myJavaMethod("foo", "bar")}. 
+ * 
+ * @deprecated Use {@link TemplateMethodModelEx} instead. This interface is from the old times when the only kind of
+ *    value you could pass in was string.
+ */
+@Deprecated
+public interface TemplateMethodModel extends TemplateModel {
+
+    /**
+     * Executes the method call. All arguments passed to the method call are 
+     * coerced to strings before being passed, if the FreeMarker rules allow
+     * the coercion. If some of the passed arguments can not be coerced to a
+     * string, an exception will be raised in the engine and the method will 
+     * not be called. If your method would like to act on actual data model 
+     * objects instead of on their string representations, implement the 
+     * {@link TemplateMethodModelEx} instead.
+     * 
+     * @param arguments a <tt>List</tt> of <tt>String</tt> objects
+     *     containing the values of the arguments passed to the method.
+     *  
+     * @return the return value of the method, or {@code null}. If the returned value
+     *     does not implement {@link TemplateModel}, it will be automatically 
+     *     wrapped using the {@link Environment#getObjectWrapper() environment 
+     *     object wrapper}.
+     */
+    Object exec(List arguments) throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModelEx.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModelEx.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModelEx.java
new file mode 100644
index 0000000..2517d22
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateMethodModelEx.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.util.DeepUnwrap;
+
+/**
+ * "extended method" template language data type: Objects that act like functions. Their main application is calling
+ * Java methods via {@link org.apache.freemarker.core.model.impl.DefaultObjectWrapper}, but you can implement this interface to invoke
+ * top-level functions too. They are "extended" compared to the deprecated {@link TemplateMethodModel}, which could only
+ * accept string parameters.
+ * 
+ * <p>In templates they are used like {@code myMethod(1, "foo")} or {@code myJavaObject.myJavaMethod(1, "foo")}.
+ */
+public interface TemplateMethodModelEx extends TemplateMethodModel {
+
+    /**
+     * Executes the method call.
+     *  
+     * @param arguments a {@link List} of {@link TemplateModel}-s,
+     *     containing the arguments passed to the method. If the implementation absolutely wants 
+     *     to operate on POJOs, it can use the static utility methods in the {@link DeepUnwrap} 
+     *     class to easily obtain them. However, unwrapping is not always possible (or not perfectly), and isn't always
+     *     efficient, so it's recommended to use the original {@link TemplateModel} value as much as possible.
+     *      
+     * @return the return value of the method, or {@code null}. If the returned value
+     *     does not implement {@link TemplateModel}, it will be automatically 
+     *     wrapped using the {@link Environment#getObjectWrapper() environment's 
+     *     object wrapper}.
+     */
+    @Override
+    Object exec(List arguments) throws TemplateModelException;
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModel.java
new file mode 100644
index 0000000..bbe3c03
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModel.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.util.FTLUtil;
+
+/**
+ * The common super-interface of the interfaces that stand for the FreeMarker Template Language (FTL) data types.
+ * The template language only deals with {@link TemplateModel}-s, not directly with plain Java objects. (For example,
+ * it doesn't understand {@link java.lang.Number}, but {@link TemplateNumberModel}.) This is why the
+ * data-model (aka. the "template context" in other languages) is (automatically) mapped to a tree of
+ * {@link TemplateModel}-s.
+ * 
+ * <p>Mapping the plain Java objects to {@link TemplateModel}-s (or the other way around sometimes) is the
+ * responsibility of the {@link ObjectWrapper} (see the {@link Configuration#getObjectWrapper objectWrapper} setting).
+ * But not all {@link TemplateModel}-s are for wrapping a plain object. For example, a value created within a template
+ * is not made to wrap an earlier existing object; it's a value that has always existed in the template language's
+ * domain. Users can also write {@link TemplateModel} implementations and put them directly into the data-model for
+ * full control over how that object is seen from the template. Certain {@link TemplateModel} interfaces doesn't
+ * even have equivalent in Java. For example the directive type ({@link TemplateDirectiveModel}) is like that.
+ * 
+ * <p>Because {@link TemplateModel} "subclasses" are all interfaces, a value in the template language can have multiple
+ * types. However, to prevent ambiguous situations, it's not recommended to make values that implement more than one of
+ * these types: string, number, boolean, date. The intended applications are like string+hash, string+method,
+ * hash+sequence, etc.
+ * 
+ * @see FTLUtil#getTypeDescription(TemplateModel)
+ */
+public interface TemplateModel {
+    
+    /**
+     * A general-purpose object to represent nothing. It acts as
+     * an empty string, false, empty sequence, empty hash, and
+     * null-returning method model.
+     */
+    TemplateModel NOTHING = GeneralPurposeNothing.INSTANCE;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelAdapter.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelAdapter.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelAdapter.java
new file mode 100644
index 0000000..a48c065
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelAdapter.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Implemented by classes that serve as adapters for template model objects in
+ * some other object model. Actually a functional inverse of 
+ * {@link AdapterTemplateModel}. You will rarely implement this interface 
+ * directly. It is usually implemented by unwrapping adapter classes of various 
+ * object wrapper implementations.
+ */
+public interface TemplateModelAdapter {
+    /**
+     * @return the template model this object is wrapping.
+     */
+    TemplateModel getTemplateModel();
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelException.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelException.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelException.java
new file mode 100644
index 0000000..d38faa4
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelException.java
@@ -0,0 +1,111 @@
+/*
+ * 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;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core._ErrorDescriptionBuilder;
+
+/**
+ * {@link TemplateModel} methods throw this exception if the requested data can't be retrieved.  
+ */
+public class TemplateModelException extends TemplateException {
+
+    /**
+     * Constructs a <tt>TemplateModelException</tt> with no
+     * specified detail message.
+     */
+    public TemplateModelException() {
+        this(null, null);
+    }
+
+    /**
+     * Constructs a <tt>TemplateModelException</tt> with the
+     * specified detail message.
+     *
+     * @param description the detail message.
+     */
+    public TemplateModelException(String description) {
+        this(description, null);
+    }
+
+    /**
+     * The same as {@link #TemplateModelException(Throwable)}; it's exists only for binary
+     * backward-compatibility.
+     */
+    public TemplateModelException(Exception cause) {
+        this(null, cause);
+    }
+
+    /**
+     * Constructs a <tt>TemplateModelException</tt> with the given underlying
+     * Exception, but no detail message.
+     *
+     * @param cause the underlying {@link Exception} that caused this
+     * exception to be raised
+     */
+    public TemplateModelException(Throwable cause) {
+        this(null, cause);
+    }
+
+    
+    /**
+     * The same as {@link #TemplateModelException(String, Throwable)}; it's exists only for binary
+     * backward-compatibility.
+     */
+    public TemplateModelException(String description, Exception cause) {
+        super(description, cause, null);
+    }
+
+    /**
+     * Constructs a TemplateModelException with both a description of the error
+     * that occurred and the underlying Exception that caused this exception
+     * to be raised.
+     *
+     * @param description the description of the error that occurred
+     * @param cause the underlying {@link Exception} that caused this
+     * exception to be raised
+     */
+    public TemplateModelException(String description, Throwable cause) {
+        super(description, cause, null);
+    }
+
+    /**
+     * Don't use this; this is to be used internally by FreeMarker.
+     * @param preventAmbiguity its value is ignored; it's only to prevent constructor selection ambiguities for
+     *     backward-compatibility
+     */
+    protected TemplateModelException(Throwable cause, Environment env, String description,
+            boolean preventAmbiguity) {
+        super(description, cause, env);
+    }
+    
+    /**
+     * Don't use this; this is to be used internally by FreeMarker.
+     * @param preventAmbiguity its value is ignored; it's only to prevent constructor selection ambiguities for
+     *     backward-compatibility
+     */
+    protected TemplateModelException(
+            Throwable cause, Environment env, _ErrorDescriptionBuilder descriptionBuilder,
+            boolean preventAmbiguity) {
+        super(cause, env, null, descriptionBuilder);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelIterator.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelIterator.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelIterator.java
new file mode 100644
index 0000000..9d1e241
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelIterator.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * Used to iterate over a set of template models <em>once</em>; usually returned from
+ * {@link TemplateCollectionModel#iterator()}. Note that it's not a {@link TemplateModel}.
+ */
+public interface TemplateModelIterator {
+
+    /**
+     * Returns the next model.
+     * @throws TemplateModelException if the next model can not be retrieved
+     *   (i.e. because the iterator is exhausted).
+     */
+    TemplateModel next() throws TemplateModelException;
+
+    /**
+     * @return whether there are any more items to iterate over.
+     */
+    boolean hasNext() throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelWithAPISupport.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelWithAPISupport.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelWithAPISupport.java
new file mode 100644
index 0000000..c1a01fe
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateModelWithAPISupport.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * <b>Experimental - subject to change:</b> A {@link TemplateModel} on which the {@code ?api} operation can be applied.
+ * 
+ * <p>
+ * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it
+ * shouldn't be implemented outside FreeMarker yet.
+ * 
+ * @since 2.3.22
+ */
+public interface TemplateModelWithAPISupport extends TemplateModel {
+
+    /**
+     * Returns the model that exposes the (Java) API of the value. This is usually implemented by delegating to
+     * {@link ObjectWrapperWithAPISupport#wrapAsAPI(Object)}.
+     */
+    TemplateModel getAPI() throws TemplateModelException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModel.java
new file mode 100644
index 0000000..afa9da6
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModel.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+/**
+ * "node" template language data type: an object that is a node in a tree.
+ * A tree of nodes can be recursively <em>visited</em> using the &lt;#visit...&gt; and &lt;#recurse...&gt;
+ * directives. This API is largely based on the W3C Document Object Model
+ * (DOM_WRAPPER) API. However, it's meant to be generally useful for describing
+ * any tree of objects that you wish to navigate using a recursive visitor
+ * design pattern (or simply through being able to get the parent
+ * and child nodes).
+ * 
+ * <p>See the <a href="http://freemarker.org/docs/xgui.html" target="_blank">XML
+ * Processing Guide</a> for a concrete application.
+ *
+ * @since FreeMarker 2.3
+ */
+public interface TemplateNodeModel extends TemplateModel {
+    
+    /**
+     * @return the parent of this node or null, in which case
+     * this node is the root of the tree.
+     */
+    TemplateNodeModel getParentNode() throws TemplateModelException;
+    
+    /**
+     * @return a sequence containing this node's children.
+     * If the returned value is null or empty, this is essentially 
+     * a leaf node.
+     */
+    TemplateSequenceModel getChildNodes() throws TemplateModelException;
+
+    /**
+     * @return a String that is used to determine the processing
+     * routine to use. In the XML implementation, if the node 
+     * is an element, it returns the element's tag name.  If it
+     * is an attribute, it returns the attribute's name. It 
+     * returns "@text" for text nodes, "@pi" for processing instructions,
+     * and so on.
+     */    
+    String getNodeName() throws TemplateModelException;
+    
+    /**
+     * @return a String describing the <em>type</em> of node this is.
+     * In the W3C DOM_WRAPPER, this should be "element", "text", "attribute", etc.
+     * A TemplateNodeModel implementation that models other kinds of
+     * trees could return whatever it appropriate for that application. It
+     * can be null, if you don't want to use node-types.
+     */
+    String getNodeType() throws TemplateModelException;
+    
+    
+    /**
+     * @return the XML namespace URI with which this node is 
+     * associated. If this TemplateNodeModel implementation is 
+     * not XML-related, it will almost certainly be null. Even 
+     * for XML nodes, this will often be null.
+     */
+    String getNodeNamespace() throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
new file mode 100644
index 0000000..acf43df
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNodeModelEx.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import org.apache.freemarker.dom.NodeModel;
+
+/**
+ * A {@link NodeModel} that supports navigating to the previous and next sibling nodes.
+ * 
+ * @since 2.3.26
+ */
+public interface TemplateNodeModelEx extends TemplateNodeModel {
+
+    /**
+     * @return The immediate previous sibling of this node, or {@code null} if there's no such node.
+     */
+    TemplateNodeModelEx getPreviousSibling() throws TemplateModelException;
+
+    /**
+     * @return The immediate next sibling of this node, or {@code null} if there's no such node.
+     */
+    TemplateNodeModelEx getNextSibling() throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNumberModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNumberModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNumberModel.java
new file mode 100644
index 0000000..ba1240d
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateNumberModel.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
+
+/**
+ * "number" template language data type; an object that stores a number. There's only one numerical type as far as the
+ * template language is concerned, but it can store its value using whatever Java number type. Making operations between
+ * numbers (and so the coercion rules) is up to the {@link ArithmeticEngine}.
+ * 
+ * <p>
+ * Objects of this type should be immutable, that is, calling {@link #getAsNumber()} should always return the same value
+ * as for the first time.
+ */
+public interface TemplateNumberModel extends TemplateModel {
+
+    /**
+     * Returns the numeric value. The return value must not be {@code null}.
+     *
+     * @return the {@link Number} instance associated with this number model.
+     */
+    Number getAsNumber() throws TemplateModelException;
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateScalarModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateScalarModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateScalarModel.java
new file mode 100644
index 0000000..b76a097
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateScalarModel.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * "string" template language data-type; like in Java, an unmodifiable UNICODE character sequence.
+ * (The name of this interface should be {@code TemplateStringModel}. The misnomer is inherited from the
+ * old times, when this was the only single-value type in FreeMarker.)
+ */
+public interface TemplateScalarModel extends TemplateModel {
+
+    /**
+     * A constant value to use as the empty string.
+     */
+    TemplateModel EMPTY_STRING = new SimpleScalar("");
+
+    /**
+     * Returns the string representation of this model. Don't return {@code null}, as that will cause exception.
+     * 
+     * <p>
+     * Objects of this type should be immutable, that is, calling {@link #getAsString()} should always return the same
+     * value as for the first time.
+     */
+    String getAsString() throws TemplateModelException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateSequenceModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateSequenceModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateSequenceModel.java
new file mode 100644
index 0000000..8ca3944
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateSequenceModel.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+/**
+ * "sequence" template language data type; an object that contains other objects accessible through an integer 0-based
+ * index.
+ * 
+ * <p>
+ * Used in templates like: {@code mySeq[index]}, {@code <#list mySeq as i>...</#list>}, {@code mySeq?size}, etc.
+ * 
+ * @see TemplateCollectionModel
+ */
+public interface TemplateSequenceModel extends TemplateModel {
+
+    /**
+     * Retrieves the i-th template model in this sequence.
+     * 
+     * @return the item at the specified index, or <code>null</code> if the index is out of bounds. Note that a
+     *         <code>null</code> value is interpreted by FreeMarker as "variable does not exist", and accessing a
+     *         missing variables is usually considered as an error in the FreeMarker Template Language, so the usage of
+     *         a bad index will not remain hidden, unless the default value for that case was also specified in the
+     *         template.
+     */
+    TemplateModel get(int index) throws TemplateModelException;
+
+    /**
+     * @return the number of items in the list.
+     */
+    int size() throws TemplateModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateTransformModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateTransformModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateTransformModel.java
new file mode 100644
index 0000000..789d9bb
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TemplateTransformModel.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.freemarker.core.util.DeepUnwrap;
+
+/**
+ * "transform" template language data type: user-defined directives 
+ * (much like macros) specialized on filtering output; you should rather use the newer {@link TemplateDirectiveModel}
+ * instead. This certainly will be deprecated in FreeMarker 2.4.
+ */
+public interface TemplateTransformModel extends TemplateModel {
+
+     /**
+      * Returns a writer that will be used by the engine to feed the
+      * transformation input to the transform. Each call to this method
+      * must return a new instance of the writer so that the transformation
+      * is thread-safe.
+      * @param out the character stream to which to write the transformed output
+      * @param args the arguments (if any) passed to the transformation as a 
+      * map of key/value pairs where the keys are strings and the arguments are
+      * TemplateModel instances. This is never null. If you need to convert the
+      * template models to POJOs, you can use the utility methods in the 
+      * {@link DeepUnwrap} class.
+      * @return a writer to which the engine will feed the transformation 
+      * input, or null if the transform does not support nested content (body).
+      * The returned writer can implement the {@link TransformControl}
+      * interface if it needs advanced control over the evaluation of the 
+      * transformation body.
+      */
+     Writer getWriter(Writer out, Map args) 
+         throws TemplateModelException, IOException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TransformControl.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TransformControl.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TransformControl.java
new file mode 100644
index 0000000..cd3965c
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TransformControl.java
@@ -0,0 +1,101 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import org.apache.freemarker.core.TemplateException;
+
+/**
+ * An interface that can be implemented by writers returned from
+ * {@link TemplateTransformModel#getWriter(java.io.Writer, java.util.Map)}. The
+ * methods on this
+ * interfaces are callbacks that will be called by the template engine and that
+ * give the writer a chance to better control the evaluation of the transform
+ * body. The writer can instruct the engine to skip or to repeat body 
+ * evaluation, and gets notified about exceptions that are thrown during the
+ * body evaluation.
+ */
+public interface TransformControl {
+    /**
+     * Constant returned from {@link #afterBody()} that tells the
+     * template engine to repeat transform body evaluation and feed
+     * it again to the transform.
+     */
+    int REPEAT_EVALUATION = 0;
+
+    /**
+     * Constant returned from {@link #afterBody()} that tells the
+     * template engine to end the transform and close the writer.
+     */
+    int END_EVALUATION = 1;
+ 
+    /**
+     * Constant returned from {@link #onStart()} that tells the
+     * template engine to skip evaluation of the body.
+     */
+    int SKIP_BODY = 0;
+    
+    /**
+     * Constant returned from {@link #onStart()} that tells the
+     * template engine to evaluate the body.
+     */
+    int EVALUATE_BODY = 1;
+
+    /**
+     * Called before the body is evaluated for the first time.
+     * @return 
+     * <ul>
+     * <li><tt>SKIP_BODY</tt> if the transform wants to ignore the body. In this
+     * case, only {@link java.io.Writer#close()} is called next and processing ends.</li>
+     * <li><tt>EVALUATE_BODY</tt> to normally evaluate the body of the transform
+     * and feed it to the writer</li>
+     * </ul>
+     */
+    int onStart() throws TemplateModelException, IOException;
+    
+    /**
+     * Called after the body has been evaluated.
+     * @return
+     * <ul>
+     * <li><tt>END_EVALUATION</tt> if the transformation should be ended.</li>
+     * <li><tt>REPEAT_EVALUATION</tt> to have the engine re-evaluate the 
+     * transform body and feed it again to the writer.</li>
+     * </ul>
+     */
+    int afterBody() throws TemplateModelException, IOException;
+    
+    /**
+     * Called if any exception occurs during the transform between the
+     * {@link TemplateTransformModel#getWriter(java.io.Writer, java.util.Map)} call
+     * and the {@link java.io.Writer#close()} call.
+     * @param t the throwable that represents the exception. It can be any 
+     * non-checked throwable, as well as {@link TemplateException} and 
+     * {@link java.io.IOException}.
+     * 
+     * @throws Throwable is recommended that the methods rethrow the received 
+     * throwable. If the method wants to throw another throwable, it should
+     * either throw a non-checked throwable, or an instance of 
+     * {@link TemplateException} and {@link java.io.IOException}. Throwing any
+     * other checked exception will cause the engine to rethrow it as
+     * a {@link java.lang.reflect.UndeclaredThrowableException}.
+     */
+    void onError(Throwable t) throws Throwable;
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/TrueTemplateBooleanModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/TrueTemplateBooleanModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TrueTemplateBooleanModel.java
new file mode 100644
index 0000000..f10ae71
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/TrueTemplateBooleanModel.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core.model;
+
+/**
+ * Used for the {@link TemplateBooleanModel#FALSE} singleton. 
+ */
+final class TrueTemplateBooleanModel implements SerializableTemplateBooleanModel {
+
+    @Override
+    public boolean getAsBoolean() {
+        return true;
+    }
+
+    private Object readResolve() {
+        return TRUE;
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrapperTemplateModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrapperTemplateModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrapperTemplateModel.java
new file mode 100644
index 0000000..1a30bf1
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrapperTemplateModel.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * A generic interface for template models that wrap some underlying
+ * object, and wish to provide access to that wrapped object.
+ * 
+ * <p>You may also want to implement {@link org.apache.freemarker.core.model.AdapterTemplateModel}.
+ */
+public interface WrapperTemplateModel extends TemplateModel {
+    /**
+     * Retrieves the original object wrapped by this model.
+     */
+    Object getWrappedObject();
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
new file mode 100644
index 0000000..206d9d4
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import org.apache.freemarker.core.util._NullArgumentException;
+
+/**
+ * Convenience base-class for containers that wrap their contained arbitrary Java objects into {@link TemplateModel}
+ * instances.
+ */
+abstract public class WrappingTemplateModel {
+
+    private final ObjectWrapper objectWrapper;
+
+    /**
+     * Protected constructor that creates a new wrapping template model using the specified object wrapper.
+     * 
+     * @param objectWrapper the wrapper to use. Passing {@code null} to it
+     *     is allowed but deprecated. Not {@code null}.
+     */
+    protected WrappingTemplateModel(ObjectWrapper objectWrapper) {
+        _NullArgumentException.check("objectWrapper", objectWrapper);
+        this.objectWrapper = objectWrapper;
+    }
+    
+    /**
+     * Returns the object wrapper instance used by this wrapping template model.
+     */
+    public ObjectWrapper getObjectWrapper() {
+        return objectWrapper;
+    }
+
+    /**
+     * Wraps the passed object into a template model using this object's object
+     * wrapper.
+     * @param obj the object to wrap
+     * @return the template model that wraps the object
+     * @throws TemplateModelException if the wrapper does not know how to
+     * wrap the passed object.
+     */
+    protected final TemplateModel wrap(Object obj) throws TemplateModelException {
+            return objectWrapper.wrap(obj);
+    }
+    
+}