freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [1/3] incubator-freemarker git commit: Renamed ParserConfiguration to ParsingConfiguration, so that the name is more consistent with the new ProcessingConfiguration.
Date Fri, 14 Apr 2017 22:02:22 GMT
Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 0356b30b0 -> 18a4ace82


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
deleted file mode 100644
index 87bab74..0000000
--- a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
+++ /dev/null
@@ -1,154 +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;
-
-import java.io.Writer;
-import java.nio.charset.Charset;
-
-import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
-import org.apache.freemarker.core.outputformat.OutputFormat;
-
-/**
- * <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is implemented by
- * classes that hold settings that affect template parsing (as opposed to {@linkplain Template#process(Object, Writer)
- * template processing}). New parser settings can be added in new FreeMarker versions, which will break your
- * implementation.
- *
- * @see ProcessingConfiguration
- */
-public interface ParserConfiguration {
-
-    TemplateLanguage getTemplateLanguage();
-
-    boolean isTemplateLanguageSet();
-
-    /**
-     * See {@link Configuration#getTagSyntax()}.
-     */
-    int getTagSyntax();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isTagSyntaxSet();
-
-    /**
-     * See {@link Configuration#getNamingConvention()}.
-     */
-    int getNamingConvention();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isNamingConventionSet();
-
-    /**
-     * See {@link Configuration#getWhitespaceStripping()}.
-     */
-    boolean getWhitespaceStripping();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isWhitespaceStrippingSet();
-
-    /**
-     * Overlaps with {@link MutableProcessingConfiguration#getArithmeticEngine()}; the parser needs this for creating numerical literals.
-     */
-    ArithmeticEngine getArithmeticEngine();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isArithmeticEngineSet();
-
-    /**
-     * See {@link Configuration#getAutoEscapingPolicy()}.
-     */
-    int getAutoEscapingPolicy();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isAutoEscapingPolicySet();
-
-    /**
-     * See {@link Configuration#getOutputEncoding()}.
-     */
-    OutputFormat getOutputFormat();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isOutputFormatSet();
-
-    /**
-     * See {@link Configuration#getRecognizeStandardFileExtensions()}.
-     */
-    boolean getRecognizeStandardFileExtensions();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isRecognizeStandardFileExtensionsSet();
-
-    /**
-     * See {@link Configuration#getIncompatibleImprovements()}; as this is normally directly delegates to
-     * {@link Configuration#getIncompatibleImprovements()}, it's always set.
-     */
-    Version getIncompatibleImprovements();
-
-    /**
-     * See {@link Configuration#getTabSize()}.
-     * 
-     * @since 2.3.25
-     */
-    int getTabSize();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link SettingValueNotSetException}.
-     */
-    boolean isTabSizeSet();
-
-    /**
-     * Gets the default encoding for converting bytes to characters when
-     * reading template files in a locale for which no explicit encoding
-     * was specified. Defaults to the default system encoding.
-     */
-    Charset getSourceEncoding();
-
-    boolean isSourceEncodingSet();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/ParsingAndProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParsingAndProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ParsingAndProcessingConfiguration.java
new file mode 100644
index 0000000..719af93
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/ParsingAndProcessingConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is the union of
+ * {@link ProcessingConfiguration} and {@link ParsingConfiguration}, which is useful for declaring types for values
+ * that must implement both interfaces.
+ */
+public interface ParsingAndProcessingConfiguration extends ParsingConfiguration, ProcessingConfiguration {
+    // No additional method
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/ParsingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParsingConfiguration.java b/src/main/java/org/apache/freemarker/core/ParsingConfiguration.java
new file mode 100644
index 0000000..b62daac
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/ParsingConfiguration.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import java.nio.charset.Charset;
+
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
+import org.apache.freemarker.core.outputformat.OutputFormat;
+
+/**
+ * Implemented by FreeMarker core classes (not by you) that provide configuration settings that affect template parsing
+ * (as opposed to {@linkplain Template#process (Object, Writer) template processing}). <b>New methods may be added
+ * anytime in future FreeMarker versions, so don't try to implement this interface yourself!</b>
+ *
+ * @see ProcessingConfiguration
+ */
+// TODO Clean up API docs like in ProcessingConfiguration, when Configuration is done
+public interface ParsingConfiguration {
+
+    TemplateLanguage getTemplateLanguage();
+
+    boolean isTemplateLanguageSet();
+
+    /**
+     * See {@link Configuration#getTagSyntax()}.
+     */
+    int getTagSyntax();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isTagSyntaxSet();
+
+    /**
+     * See {@link Configuration#getNamingConvention()}.
+     */
+    int getNamingConvention();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isNamingConventionSet();
+
+    /**
+     * See {@link Configuration#getWhitespaceStripping()}.
+     */
+    boolean getWhitespaceStripping();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isWhitespaceStrippingSet();
+
+    /**
+     * Overlaps with {@link ProcessingConfiguration#getArithmeticEngine()}; the parser needs this for creating numerical
+     * literals.
+     */
+    ArithmeticEngine getArithmeticEngine();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isArithmeticEngineSet();
+
+    /**
+     * See {@link Configuration#getAutoEscapingPolicy()}.
+     */
+    int getAutoEscapingPolicy();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isAutoEscapingPolicySet();
+
+    /**
+     * See {@link Configuration#getOutputEncoding()}.
+     */
+    OutputFormat getOutputFormat();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isOutputFormatSet();
+
+    /**
+     * See {@link Configuration#getRecognizeStandardFileExtensions()}.
+     */
+    boolean getRecognizeStandardFileExtensions();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isRecognizeStandardFileExtensionsSet();
+
+    /**
+     * See {@link Configuration#getIncompatibleImprovements()}; as this is normally directly delegates to
+     * {@link Configuration#getIncompatibleImprovements()}, it's always set.
+     */
+    Version getIncompatibleImprovements();
+
+    /**
+     * See {@link Configuration#getTabSize()}.
+     * 
+     * @since 2.3.25
+     */
+    int getTabSize();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting might returns a default value, or returns the value of the setting from a parent parsing
+     * configuration or throws a {@link SettingValueNotSetException}.
+     */
+    boolean isTabSizeSet();
+
+    /**
+     * Gets the default encoding for converting bytes to characters when
+     * reading template files in a locale for which no explicit encoding
+     * was specified. Defaults to the default system encoding.
+     */
+    Charset getSourceEncoding();
+
+    boolean isSourceEncodingSet();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
index b224a01..9dd8dc9 100644
--- a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
@@ -21,29 +21,36 @@ package org.apache.freemarker.core;
 
 import java.io.Writer;
 import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.TimeZone;
 
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
+import org.apache.freemarker.core.arithmetic.impl.BigDecimalArithmeticEngine;
 import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
+import org.apache.freemarker.core.valueformat.TemplateNumberFormat;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
 
 /**
- * <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is implemented by
- * classes that hold settings that affect {@linkplain Template#process(Object, Writer) template processing} (as opposed
- * to template parsing). New parser settings can be added in new FreeMarker versions, which will break your
- * implementation.
+ * Implemented by FreeMarker core classes (not by you) that provide configuration settings that affect {@linkplain
+ * Template#process(Object, Writer) template processing} (as opposed to template parsing). <b>New methods may be added
+ * anytime in future FreeMarker versions, so don't try to implement this interface yourself!</b>
  *
- * @see ParserConfiguration
+ * @see ParsingConfiguration
  */
-// TODO [FM3] JavaDoc
 public interface ProcessingConfiguration {
 
-     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setLocale(Locale)}.
+    /**
+     * The locale used for number and date formatting (among others), also the locale used for searching localized
+     * template variations when no locale was explicitly specified where the template is requested.
+     *
+     * @see Configuration#getTemplate(String, Locale)
      */
     Locale getLocale();
 
@@ -55,7 +62,15 @@ public interface ProcessingConfiguration {
     boolean isLocaleSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setTimeZone(TimeZone)}.
+     * The time zone to use when formatting date/time values. It {@link Configuration}-level default
+     * is the system time zone ({@link TimeZone#getDefault()}), regardless of the "locale" FreeMarker setting,
+     * so in a server application you probably want to set it explicitly in the {@link Environment} to match the
+     * preferred time zone of the target audience (like the Web page visitor).
+     *
+     * <p>If you or the templates set the time zone, you should probably also set
+     * {@link #getSQLDateAndTimeTimeZone()}!
+     *
+     * @see #getSQLDateAndTimeTimeZone()
      */
     TimeZone getTimeZone();
 
@@ -67,11 +82,58 @@ public interface ProcessingConfiguration {
     boolean isTimeZoneSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setSQLDateAndTimeTimeZone(TimeZone)}.
+     * The time zone used when dealing with {@link java.sql.Date java.sql.Date} and
+     * {@link java.sql.Time java.sql.Time} values. Its {@link Configuration}-level defaults is {@code null} for
+     * backward compatibility, but in most applications this should be set to the JVM default time zone (server
+     * default time zone), because that's what most JDBC drivers will use when constructing the
+     * {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} values. If this setting is {@code
+     * null} FreeMarker will use the value of ({@link #getTimeZone()}) for {@link java.sql.Date java.sql.Date} and
+     * {@link java.sql.Time java.sql.Time} values, which often gives bad results.
+     *
+     * <p>This setting doesn't influence the formatting of other kind of values (like of
+     * {@link java.sql.Timestamp java.sql.Timestamp} or plain {@link java.util.Date java.util.Date} values).
+     *
+     * <p>To decide what value you need, a few things has to be understood:
+     * <ul>
+     *   <li>Date-only and time-only values in SQL-oriented databases are usually store calendar and clock field
+     *   values directly (year, month, day, or hour, minute, seconds (with decimals)), as opposed to a set of points
+     *   on the physical time line. Thus, unlike SQL timestamps, these values usually aren't meant to be shown
+     *   differently depending on the time zone of the audience.
+     *
+     *   <li>When a JDBC query has to return a date-only or time-only value, it has to convert it to a point on the
+     *   physical time line, because that's what {@link java.util.Date} and its subclasses store (milliseconds since
+     *   the epoch). Obviously, this is impossible to do. So JDBC just chooses a physical time which, when rendered
+     *   <em>with the JVM default time zone</em>, will give the same field values as those stored
+     *   in the database. (Actually, you can give JDBC a calendar, and so it can use other time zones too, but most
+     *   application won't care using those overloads.) For example, assume that the system time zone is GMT+02:00.
+     *   Then, 2014-07-12 in the database will be translated to physical time 2014-07-11 22:00:00 UTC, because that
+     *   rendered in GMT+02:00 gives 2014-07-12 00:00:00. Similarly, 11:57:00 in the database will be translated to
+     *   physical time 1970-01-01 09:57:00 UTC. Thus, the physical time stored in the returned value depends on the
+     *   default system time zone of the JDBC client, not just on the content of the database. (This used to be the
+     *   default behavior of ORM-s, like Hibernate, too.)
      *
-     * @return {@code null} if the value of {@link #getTimeZone()} should be used for formatting {@link java.sql.Date
-     * java.sql.Date} and {@link java.sql.Time java.sql.Time} values, otherwise the time zone that should be used to
-     * format the values of those two types.
+     *   <li>The value of the {@code time_zone} FreeMarker configuration setting sets the time zone used for the
+     *   template output. For example, when a web page visitor has a preferred time zone, the web application framework
+     *   may calls {@link Environment#setTimeZone(TimeZone)} with that time zone. Thus, the visitor will
+     *   see {@link java.sql.Timestamp java.sql.Timestamp} and plain {@link java.util.Date java.util.Date} values as
+     *   they look in his own time zone. While
+     *   this is desirable for those types, as they meant to represent physical points on the time line, this is not
+     *   necessarily desirable for date-only and time-only values. When {@code sql_date_and_time_time_zone} is
+     *   {@code null}, {@code time_zone} is used for rendering all kind of date/time/dateTime values, including
+     *   {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time}, and then if, for example,
+     *   {@code time_zone} is GMT+00:00, the
+     *   values from the earlier examples will be shown as 2014-07-11 (one day off) and 09:57:00 (2 hours off). While
+     *   those are the time zone correct renderings, those values are probably meant to be shown "as is".
+     *
+     *   <li>You may wonder why this setting isn't simply "SQL time zone", that is, why's this time zone not applied to
+     *   {@link java.sql.Timestamp java.sql.Timestamp} values as well. Timestamps in databases refer to a point on
+     *   the physical time line, and thus doesn't have the inherent problem of date-only and time-only values.
+     *   FreeMarker assumes that the JDBC driver converts time stamps coming from the database so that they store
+     *   the distance from the epoch (1970-01-01 00:00:00 UTC), as requested by the {@link java.util.Date} API.
+     *   Then time stamps can be safely rendered in different time zones, and thus need no special treatment.
+     * </ul>
+     *
+     * @see #getTimeZone()
      */
     TimeZone getSQLDateAndTimeTimeZone();
 
@@ -83,7 +145,26 @@ public interface ProcessingConfiguration {
     boolean isSQLDateAndTimeTimeZoneSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setNumberFormat(String)}.
+     * The number format used to convert numbers to strings (where no number format is explicitly given). Its
+     * {@link Configuration}-level default is {@code "number"}. The possible values are:
+     * <ul>
+     *   <li>{@code "number"}: The number format returned by {@link NumberFormat#getNumberInstance(Locale)}</li>
+     *   <li>{@code "currency"}: The number format returned by {@link NumberFormat#getCurrencyInstance(Locale)}</li>
+     *   <li>{@code "percent"}: The number format returned by {@link NumberFormat#getPercentInstance(Locale)}</li>
+     *   <li>{@code "computer"}: The number format used by FTL's {@code c} built-in (like in {@code someNumber?c}).</li>
+     *   <li>A {@link java.text.DecimalFormat} pattern (like {@code "0.##"}). This syntax is extended by FreeMarker
+     *       so that you can specify options like the rounding mode and the symbols used after a 2nd semicolon. For
+     *       example, {@code ",000;; roundingMode=halfUp groupingSeparator=_"} will format numbers like {@code ",000"}
+     *       would, but with half-up rounding mode, and {@code _} as the group separator. See more about "extended Java
+     *       decimal format" in the FreeMarker Manual.
+     *       </li>
+     *   <li>If the string starts with {@code @} character followed by a letter then it's interpreted as a custom number
+     *       format. The format of a such string is <code>"@<i>name</i>"</code> or <code>"@<i>name</i>
+     *       <i>parameters</i>"</code>, where <code><i>name</i></code> is the key in the {@link Map} set by
+     *       {@link MutableProcessingConfiguration#setCustomNumberFormats(Map)}, and <code><i>parameters</i></code> is
+     *       parsed by the custom {@link TemplateNumberFormat}.
+     *   </li>
+     * </ul>
      */
     String getNumberFormat();
 
@@ -95,10 +176,31 @@ public interface ProcessingConfiguration {
     boolean isNumberFormatSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setCustomNumberFormats(Map)}.
+     * A {@link Map} that associates {@link TemplateNumberFormatFactory}-es to names, which then can be referred by the
+     * {@link #getNumberFormat() number_format} setting with values starting with <code>@<i>name</i></code>. The keys in
+     * the {@link Map} should start with an UNICODE letter, and should only contain UNICODE letters and digits (not
+     * {@code _}), otherwise accessing the custom format from templates can be difficult or impossible. The
+     * {@link Configuration}-level default of this setting is an empty  {@link Map}.
+     * <p>
+     * When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
+     * settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
+     * {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
+     * inheritance. Thus, to get a custom format you shouldn't use this {@link Map} directly, but
+     * {@link #getCustomNumberFormat(String)}, which will search the format in the inheritance chain.
+     *
+     * @return Never {@code null}. Unless the method was called on a builder class, the returned {@link Map} shouldn't
+     * be modified.
      */
     Map<String, TemplateNumberFormatFactory> getCustomNumberFormats();
 
+    /**
+     * Gets the custom number format registered for the name. This differs from calling {@link #getCustomNumberFormats()
+     * getCustomNumberFormats().get(name)}, because if there's {@link ProcessingConfiguration} from which setting values
+     * are inherited then this method will search the custom format there as well if it isn't found here. For example,
+     * {@link Environment#getCustomNumberFormat(String)} will check if the {@link Environment} contains the custom
+     * format with the name, and if not, it will try {@link Template#getCustomNumberFormat(String)} on the main
+     * template, which in turn might falls back to calling {@link Configuration#getCustomNumberFormat(String)}.
+     */
     TemplateNumberFormatFactory getCustomNumberFormat(String name);
 
     /**
@@ -108,10 +210,21 @@ public interface ProcessingConfiguration {
      */
     boolean isCustomNumberFormatsSet();
 
+    /**
+     * Tells if {@link #getCustomNumberFormat(String)} or {@link #getCustomDateFormat(String)} (or any other future
+     * method that returns custom formats) will return a custom format for some name. (Knowing that it's not the case
+     * allows certain optimizations.)
+     */
     boolean hasCustomFormats();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setBooleanFormat(String)}.
+     * The string value for the boolean {@code true} and {@code false} values, intended for human audience (not for a
+     * computer language), separated with comma. For example, {@code "yes,no"}. Note that white-space is significant,
+     * so {@code "yes, no"} is WRONG (unless you want that leading space before "no").
+     *
+     * <p>For backward compatibility the default is {@code "true,false"}, but using that value is denied for automatic
+     * boolean-to-string conversion (like <code>${myBoolean}</code> will fail with it), only {@code myBool?string} will
+     * allow it, which is deprecated since FreeMarker 2.3.20.
      */
     String getBooleanFormat();
 
@@ -123,7 +236,12 @@ public interface ProcessingConfiguration {
     boolean isBooleanFormatSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setTimeFormat(String)}.
+     * The format used to convert {@link java.util.Date}-s that are time (no date part) values to string-s, also the
+     * format that {@code someString?time} will use to parse strings.
+     *
+     * <p>For the possible values see {@link #getDateTimeFormat()}.
+     *
+     * <p>Its {@link Configuration}-level default is {@code ""}, which is equivalent to {@code "medium"}.
      */
     String getTimeFormat();
 
@@ -135,7 +253,12 @@ public interface ProcessingConfiguration {
     boolean isTimeFormatSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setDateFormat(String)}.
+     * The format used to convert {@link java.util.Date}-s that are date-only (no time part) values to string-s,
+     * also the format that {@code someString?date} will use to parse strings.
+     *
+     * <p>For the possible values see {@link #getDateTimeFormat()}.
+     *
+     * <p>Its {@link Configuration}-level default is {@code ""} which is equivalent to {@code "medium"}.
      */
     String getDateFormat();
 
@@ -147,7 +270,90 @@ public interface ProcessingConfiguration {
     boolean isDateFormatSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setDateTimeFormat(String)}.
+     * The format used to convert {@link java.util.Date}-s that are date-time (timestamp) values to string-s,
+     * also the format that {@code someString?datetime} will use to parse strings.
+     *
+     * <p>The possible setting values are (the quotation marks aren't part of the value itself):
+     *
+     * <ul>
+     *   <li><p>Patterns accepted by Java's {@link SimpleDateFormat}, for example {@code "dd.MM.yyyy HH:mm:ss"} (where
+     *       {@code HH} means 24 hours format) or {@code "MM/dd/yyyy hh:mm:ss a"} (where {@code a} prints AM or PM, if
+     *       the current language is English).
+     *
+     *   <li><p>{@code "xs"} for XML Schema format, or {@code "iso"} for ISO 8601:2004 format.
+     *       These formats allow various additional options, separated with space, like in
+     *       {@code "iso m nz"} (or with {@code _}, like in {@code "iso_m_nz"}; this is useful in a case like
+     *       {@code lastModified?string.iso_m_nz}). The options and their meanings are:
+     *
+     *       <ul>
+     *         <li><p>Accuracy options:<br>
+     *             {@code ms} = Milliseconds, always shown with all 3 digits, even if it's all 0-s.
+     *                     Example: {@code 13:45:05.800}<br>
+     *             {@code s} = Seconds (fraction seconds are dropped even if non-0), like {@code 13:45:05}<br>
+     *             {@code m} = Minutes, like {@code 13:45}. This isn't allowed for "xs".<br>
+     *             {@code h} = Hours, like {@code 13}. This isn't allowed for "xs".<br>
+     *             Neither = Up to millisecond accuracy, but trailing millisecond 0-s are removed, also the whole
+     *                     milliseconds part if it would be 0 otherwise. Example: {@code 13:45:05.8}
+     *
+     *         <li><p>Time zone offset visibility options:<br>
+     *             {@code fz} = "Force Zone", always show time zone offset (even for for
+     *                     {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} values).
+     *                     But, because ISO 8601 doesn't allow for dates (means date without time of the day) to
+     *                     show the zone offset, this option will have no effect in the case of {@code "iso"} with
+     *                     dates.<br>
+     *             {@code nz} = "No Zone", never show time zone offset<br>
+     *             Neither = always show time zone offset, except for {@link java.sql.Date java.sql.Date}
+     *                     and {@link java.sql.Time java.sql.Time}, and for {@code "iso"} date values.
+     *
+     *         <li><p>Time zone options:<br>
+     *             {@code u} = Use UTC instead of what the {@code time_zone} setting suggests. However,
+     *                     {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} aren't affected
+     *                     by this (see {@link #getSQLDateAndTimeTimeZone()} to understand why)<br>
+     *             {@code fu} = "Force UTC", that is, use UTC instead of what the {@code time_zone} or the
+     *                     {@code sql_date_and_time_time_zone} setting suggests. This also effects
+     *                     {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} values<br>
+     *             Neither = Use the time zone suggested by the {@code time_zone} or the
+     *                     {@code sql_date_and_time_time_zone} configuration setting ({@link #getTimeZone()} and
+     *                     {@link #getSQLDateAndTimeTimeZone()}).
+     *       </ul>
+     *
+     *       <p>The options can be specified in any order.</p>
+     *
+     *       <p>Options from the same category are mutually exclusive, like using {@code m} and {@code s}
+     *       together is an error.
+     *
+     *       <p>The accuracy and time zone offset visibility options don't influence parsing, only formatting.
+     *       For example, even if you use "iso m nz", "2012-01-01T15:30:05.125+01" will be parsed successfully and with
+     *       milliseconds accuracy.
+     *       The time zone options (like "u") influence what time zone is chosen only when parsing a string that doesn't
+     *       contain time zone offset.
+     *
+     *       <p>Parsing with {@code "iso"} understands both extend format and basic format, like
+     *       {@code 20141225T235018}. It doesn't, however, support the parsing of all kind of ISO 8601 strings: if
+     *       there's a date part, it must use year, month and day of the month values (not week of the year), and the
+     *       day can't be omitted.
+     *
+     *       <p>The output of {@code "iso"} is deliberately so that it's also a good representation of the value with
+     *       XML Schema format, except for 0 and negative years, where it's impossible. Also note that the time zone
+     *       offset is omitted for date values in the {@code "iso"} format, while it's preserved for the {@code "xs"}
+     *       format.
+     *
+     *   <li><p>{@code "short"}, {@code "medium"}, {@code "long"}, or {@code "full"}, which that has locale-dependent
+     *       meaning defined by the Java platform (see in the documentation of {@link java.text.DateFormat}).
+     *       For date-time values, you can specify the length of the date and time part independently, be separating
+     *       them with {@code _}, like {@code "short_medium"}. ({@code "medium"} means
+     *       {@code "medium_medium"} for date-time values.)
+     *
+     *   <li><p>Anything that starts with {@code "@"} followed by a letter is interpreted as a custom
+     *       date/time/dateTime format, but only if either {@link Configuration#getIncompatibleImprovements()}
+     *       is at least 2.3.24, or there's any custom formats defined (even if custom number format). The format of
+     *       such string is <code>"@<i>name</i>"</code> or <code>"@<i>name</i> <i>parameters</i>"</code>, where
+     *       <code><i>name</i></code> is the name parameter to {@link #getCustomDateFormat(String)}, and
+     *       <code><i>parameters</i></code> is parsed by the custom number format.
+     *
+     * </ul>
+     *
+     * <p>Its {@link Configuration}-level default is {@code ""}, which is equivalent to {@code "medium_medium"}.
      */
     String getDateTimeFormat();
 
@@ -159,10 +365,32 @@ public interface ProcessingConfiguration {
     boolean isDateTimeFormatSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setCustomDateFormats(Map)}.
+     * A {@link Map} that associates {@link TemplateDateFormatFactory}-es to names, which then can be referred by the
+     * {@link #getDateFormat() date_format}/{@link #getDateFormat() date_format }/{@link #getDateTimeFormat()
+     * datetime_format} settings with values starting with <code>@<i>name</i></code>. The keys in the {@link Map} should
+     * start with an UNICODE letter, and should only contain UNICODE letters and digits (not {@code _}), otherwise
+     * accessing the custom format from templates can be difficult or impossible. The {@link Configuration}-level
+     * default of this setting is an empty {@link Map}.
+     * <p>
+     * When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
+     * settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
+     * {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
+     * inheritance. Thus, to get a custom format you shouldn't use this {@link Map} directly, but {@link
+     * #getCustomDateFormat(String)}, which will search the format in the inheritance chain.
+     *
+     * @return Never {@code null}. Unless the method was called on a builder class, the returned {@link Map} shouldn't
+     * be modified.
      */
     Map<String, TemplateDateFormatFactory> getCustomDateFormats();
 
+    /**
+     * Gets the custom date or time or date-time format registered for the name. This differs from calling {@link
+     * #getCustomDateFormats() getCustomDateFormats.get(name)}, because if there's {@link ProcessingConfiguration} from
+     * which setting values are inherited then this method will search the custom format there as well if it isn't found
+     * here. For example, {@link Environment#getCustomNumberFormat(String)} will check if the {@link Environment}
+     * contains the custom format with the name, and if not, it will try {@link Template#getCustomDateFormat(String)} on
+     * the main template, which in turn might falls back to calling {@link Configuration#getCustomDateFormat(String)}.
+     */
     TemplateDateFormatFactory getCustomDateFormat(String name);
 
     /**
@@ -173,7 +401,25 @@ public interface ProcessingConfiguration {
     boolean isCustomDateFormatsSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setTemplateExceptionHandler(TemplateExceptionHandler)}.
+     * The exception handler used to handle exceptions occurring inside templates.
+     * Its {@link Configuration}-level default is {@link TemplateExceptionHandler#DEBUG_HANDLER}. The recommended
+     * values are:
+     *
+     * <ul>
+     *   <li>In production systems: {@link TemplateExceptionHandler#RETHROW_HANDLER}
+     *   <li>During development of HTML templates: {@link TemplateExceptionHandler#HTML_DEBUG_HANDLER}
+     *   <li>During development of non-HTML templates: {@link TemplateExceptionHandler#DEBUG_HANDLER}
+     * </ul>
+     *
+     * <p>All of these will let the exception propagate further, so that you can catch it around
+     * {@link Template#process(Object, Writer)} for example. The difference is in what they print on the output before
+     * they do that.
+     *
+     * <p>Note that the {@link TemplateExceptionHandler} is not meant to be used for generating HTTP error pages.
+     * Neither is it meant to be used to roll back the printed output. These should be solved outside template
+     * processing when the exception raises from {@link Template#process(Object, Writer) Template.process}.
+     * {@link TemplateExceptionHandler} meant to be used if you want to include special content <em>in</em> the template
+     * output, or if you want to suppress certain exceptions.
      */
     TemplateExceptionHandler getTemplateExceptionHandler();
 
@@ -185,7 +431,9 @@ public interface ProcessingConfiguration {
     boolean isTemplateExceptionHandlerSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setArithmeticEngine(ArithmeticEngine)}.
+     * The arithmetic engine used to perform arithmetic operations.
+     * Its {@link Configuration}-level default is {@link BigDecimalArithmeticEngine#INSTANCE}.
+     * Note that this setting overlaps with {@link ParsingConfiguration#getArithmeticEngine()}.
      */
     ArithmeticEngine getArithmeticEngine();
 
@@ -197,7 +445,9 @@ public interface ProcessingConfiguration {
     boolean isArithmeticEngineSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setObjectWrapper(ObjectWrapper)}.
+     * The object wrapper used to wrap objects to {@link TemplateModel}-s.
+     * Its {@link Configuration}-level default is a {@link DefaultObjectWrapper} with all its setting on default
+     * values, and {@code incompatibleImprovements} set to {@link Configuration#getIncompatibleImprovements()}.
      */
     ObjectWrapper getObjectWrapper();
 
@@ -209,7 +459,12 @@ public interface ProcessingConfiguration {
     boolean isObjectWrapperSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setOutputEncoding(Charset)}.
+     * Informs FreeMarker about the charset used for the output. As FreeMarker outputs character stream (not
+     * byte stream), it's not aware of the output charset unless the software that encloses it tells it
+     * with this setting. Some templates may use FreeMarker features that require this information.
+     * Setting this to {@code null} means that the output encoding is not known.
+     *
+     * <p>Its {@link Configuration}-level default is {@code null}.
      */
     Charset getOutputEncoding();
 
@@ -221,7 +476,8 @@ public interface ProcessingConfiguration {
     boolean isOutputEncodingSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setURLEscapingCharset(Charset)}.
+     * The URL escaping (URL encoding, percentage encoding) charset. If ({@code null}), the output encoding
+     * ({@link #getOutputEncoding()}) will be used. Its {@link Configuration}-level default is {@code null}.
      */
     Charset getURLEscapingCharset();
 
@@ -233,7 +489,11 @@ public interface ProcessingConfiguration {
     boolean isURLEscapingCharsetSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setNewBuiltinClassResolver(TemplateClassResolver)}.
+     * The {@link TemplateClassResolver} that is used when the <code>new</code> built-in is called in a template. That
+     * is, when a template contains the <code>"com.example.SomeClassName"?new</code> expression, this object will be
+     * called to resolve the <code>"com.example.SomeClassName"</code> string to a class. The default value is {@link
+     * TemplateClassResolver#UNRESTRICTED_RESOLVER}. If you allow users to upload templates, it's important to use a
+     * custom restrictive {@link TemplateClassResolver} or {@link TemplateClassResolver#ALLOWS_NOTHING_RESOLVER}.
      */
     TemplateClassResolver getNewBuiltinClassResolver();
 
@@ -244,12 +504,28 @@ public interface ProcessingConfiguration {
      */
     boolean isNewBuiltinClassResolverSet();
 
+    /**
+     * Specifies if {@code ?api} can be used in templates. Its {@link Configuration}-level is {@code false} (which
+     * is the safest option).
+     */
     boolean getAPIBuiltinEnabled();
 
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+     * an {@link SettingValueNotSetException}.
+     */
     boolean isAPIBuiltinEnabledSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setAutoFlush(boolean)}.
+     * Whether the output {@link Writer} is automatically flushed at the end of {@link Template#process(Object, Writer)}
+     * (and its overloads). Its {@link Configuration}-level default is {@code true}.
+     * <p>
+     * Using {@code false} is needed for example when a Web page is composed from several boxes (like portlets, GUI
+     * panels, etc.) that aren't inserted with <tt>#include</tt> (or with similar directives) into a master FreeMarker
+     * template, rather they are all processed with a separate {@link Template#process(Object, Writer)} call. In a such
+     * scenario the automatic flushes would commit the HTTP response after each box, hence interfering with full-page
+     * buffering, and also possibly decreasing performance with too frequent and too early response buffer flushes.
      */
     boolean getAutoFlush();
 
@@ -261,7 +537,8 @@ public interface ProcessingConfiguration {
     boolean isAutoFlushSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setShowErrorTips(boolean)}.
+     * Whether tips should be shown in error messages of errors arising during template processing.
+     * Its {@link Configuration}-level default is {@code true}.
      */
     boolean getShowErrorTips();
 
@@ -273,7 +550,13 @@ public interface ProcessingConfiguration {
     boolean isShowErrorTipsSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setLogTemplateExceptions(boolean)}.
+     * Specifies if {@link TemplateException}-s thrown by template processing are logged by FreeMarker or not. The
+     * default is {@code true} for backward compatibility, but that results in logging the exception twice in properly
+     * written applications, because there the {@link TemplateException} thrown by the public FreeMarker API is also
+     * logged by the caller (even if only as the cause exception of a higher level exception). Hence, in modern
+     * applications it should be set to {@code false}. Note that this setting has no effect on the logging of exceptions
+     * caught by {@code #attempt}; those are always logged, no mater what (because those exceptions won't bubble up
+     * until the API caller).
      */
     boolean getLogTemplateExceptions();
 
@@ -285,7 +568,22 @@ public interface ProcessingConfiguration {
     boolean isLogTemplateExceptionsSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setLazyImports(boolean)}.
+     * Specifies if {@code <#import ...>} (and {@link Environment#importLib(String, String)}) should delay the loading
+     * and processing of the imported templates until the content of the imported namespace is actually accessed. This
+     * makes the overhead of <em>unused</em> imports negligible. A drawback is that importing a missing or otherwise
+     * broken template will be successful, and the problem will remain hidden until (and if) the namespace content is
+     * actually used. Also, you lose the strict control over when the namespace initializing code in the imported
+     * template will be executed, though it shouldn't mater for well written imported templates anyway. Note that the
+     * namespace initializing code will run with the same {@linkplain #getLocale() locale} as it was at the
+     * point of the {@code <#import ...>} call (other settings won't be handled specially like that).
+     * <p>
+     * The default is {@code false} (and thus imports are eager) for backward compatibility, which can cause
+     * perceivable overhead if you have many imports and only a few of them is used.
+     * <p>
+     * This setting also affects {@linkplain #getAutoImports() auto-imports}, unless you have set a non-{@code null}
+     * value with {@link #getLazyAutoImports()}.
+     *
+     * @see #getLazyAutoImports()
      */
     boolean getLazyImports();
 
@@ -297,7 +595,10 @@ public interface ProcessingConfiguration {
     boolean isLazyImportsSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setLazyAutoImports(Boolean)}.
+     * Specifies if {@linkplain #getAutoImports() auto-imports} will be
+     * {@link #getLazyImports() lazy imports}. This is useful to make the overhead of <em>unused</em>
+     * auto-imports negligible. If this is set to {@code null}, {@link #getLazyImports()} specifies the behavior of
+     * auto-imports too. The default value is {@code null}.
      */
     Boolean getLazyAutoImports();
 
@@ -309,7 +610,31 @@ public interface ProcessingConfiguration {
     boolean isLazyAutoImportsSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setAutoImports(Map)}.
+     * Adds invisible <code>#import <i>templateName</i> as <i>namespaceVarName</i></code> statements at the beginning of
+     * the main template (that's the top-level template that wasn't included/imported from another template). While
+     * it only affects the main template directly, as the imports will create a global variable there, the imports
+     * will be visible from the further imported templates too.
+     * <p>
+     * It's recommended to set the {@code lazy_auto_imports} setting ({@link Configuration#setLazyAutoImports(Boolean)})
+     * to {@code true} when using this, so that auto-imports that are unused in a template won't degrade performance by
+     * unnecessary loading and initializing the imported library.
+     * <p>
+     * If the imports aren't lazy, the order of the imports will be the same as the order in which the {@link Map}
+     * iterates through its entries.
+     * <p>
+     * When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
+     * settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
+     * {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
+     * inheritance. But FreeMarker will walk the whole inheritance chain, executing all auto-imports starting
+     * from the ancestors. If, however, the same auto-import <code><i>namespaceVarName</i></code> occurs in multiple
+     * {@link ProcessingConfiguration}-s of the chain, only the one in the last (child)
+     * {@link ProcessingConfiguration} will be executed.
+     * <p>
+     * If there are also auto-includes (see {@link #getAutoIncludes()}), those will be executed after the auto-imports.
+     * <p>
+     * The {@link Configuration}-level default of this setting is an empty {@link Map}.
+     *
+     * @return Never {@code null}
      */
     Map<String, String> getAutoImports();
 
@@ -321,7 +646,21 @@ public interface ProcessingConfiguration {
     boolean isAutoImportsSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setAutoIncludes(List)}.
+     * Adds an invisible <code>#include <i>templateName</i></code> at the beginning of the main template (that's the
+     * top-level template that wasn't included/imported from another template).
+     * <p>
+     * The order of the inclusions will be the same as the order in this {@link List}.
+     * <p>
+     * When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
+     * settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
+     * {@link List} from the closest {@link ProcessingConfiguration} where it was set, not a {@link List} that respects
+     * inheritance. But FreeMarker will walk the whole inheritance chain, executing all auto-imports starting
+     * from the ancestors. If, however, the same auto-included template name occurs in multiple
+     * {@link ProcessingConfiguration}-s of the chain, only the one in the last (child)
+     * {@link ProcessingConfiguration} will be executed.
+     * <p>
+     * If there are also auto-imports ({@link #getAutoImports()}), those imports will be executed before
+     * the auto-includes, hence the namespace variables are alrady accessible for the auto-included templates.
      */
     List<String> getAutoIncludes();
 
@@ -332,6 +671,19 @@ public interface ProcessingConfiguration {
      */
     boolean isAutoIncludesSet();
 
+    /**
+     * The {@code Map} of custom attributes. Custom attributes are key-value pairs associated to a
+     * {@link ProcessingConfiguration} objects, which meant to be used for storing application or framework specific
+     * configuration settings. The FreeMarker core doesn't define any attributes. Note that to store
+     * {@link ProcessingConfiguration}-scoped state (such as application or framework specific caches) you should use
+     * the methods provided by the {@link CustomStateScope} instead.
+     * <p>
+     * When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
+     * settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
+     * {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
+     * inheritance. Thus to get attributes, you shouldn't use this {@link Map} directly, but
+     * {@link #getCustomAttribute(Object)} that will search the custom attribute in the whole inheritance chain.
+     */
     Map<Object, Object> getCustomAttributes();
 
     /**
@@ -341,6 +693,18 @@ public interface ProcessingConfiguration {
      */
     boolean isCustomAttributesSet();
 
-    Object getCustomAttribute(Object name);
+    /**
+     * Retrieves a custom attribute for this {@link ProcessingConfiguration}. If the attribute is not present in the
+     * {@link ProcessingConfiguration}, but it inherits from another {@link ProcessingConfiguration}, then the attribute
+     * is searched the as well.
+     *
+     * @param key
+     *         the identifier (usually a name) of the custom attribute
+     *
+     * @return the value of the custom attribute. Note that if the custom attribute was created with
+     * <tt>&lt;#ftl&nbsp;attributes={...}&gt;</tt>, then this value is already unwrapped (i.e. it's a
+     * <code>String</code>, or a <code>List</code>, or a <code>Map</code>, ...etc., not a FreeMarker specific class).
+     */
+    Object getCustomAttribute(Object key);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/Template.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Template.java b/src/main/java/org/apache/freemarker/core/Template.java
index 8671dc1..726cd52 100644
--- a/src/main/java/org/apache/freemarker/core/Template.java
+++ b/src/main/java/org/apache/freemarker/core/Template.java
@@ -102,7 +102,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
     // Inherited settings:
     private final transient Configuration cfg;
     private final transient TemplateConfiguration tCfg;
-    private final transient ParserConfiguration parserConfiguration;
+    private final transient ParsingConfiguration parsingConfiguration;
 
     // Values from the template content (#ftl header parameters usually), as opposed to from the TemplateConfiguration:
     private transient OutputFormat outputFormat; // TODO Deserialization: use the name of the output format
@@ -281,7 +281,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
         _NullArgumentException.check("configuration", configuration);
         this.cfg = configuration;
         this.tCfg = templateConfiguration;
-        this.parserConfiguration = tCfg != null ? new TemplateParserConfigurationWithFallback(cfg, tCfg) : cfg;
+        this.parsingConfiguration = tCfg != null ? new TemplateParsingConfigurationWithFallback(cfg, tCfg) : cfg;
         this.name = name;
         this.sourceName = sourceName;
 
@@ -294,13 +294,13 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
                 reader = new BufferedReader(reader, READER_BUFFER_SIZE);
             }
             
-            ltbReader = new LineTableBuilder(reader, parserConfiguration);
+            ltbReader = new LineTableBuilder(reader, parsingConfiguration);
             reader = ltbReader;
             
             try {
                 FMParser parser = new FMParser(
                         this, reader,
-                        parserConfiguration, contextOutputFormat, contextAutoEscapingPolicy,
+                        parsingConfiguration, contextOutputFormat, contextAutoEscapingPolicy,
                         streamToUnmarkWhenEncEstabd);
                 try {
                     rootElement = parser.Root();
@@ -599,8 +599,8 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
         return tCfg;
     }
 
-    public ParserConfiguration getParserConfiguration() {
-        return parserConfiguration;
+    public ParsingConfiguration getParsingConfiguration() {
+        return parsingConfiguration;
     }
 
 
@@ -672,7 +672,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
     /**
      * Returns the output format (see {@link Configuration#setOutputFormat(OutputFormat)}) used for this template.
      * The output format of a template can come from various places, in order of increasing priority:
-     * {@link Configuration#getOutputFormat()}, {@link ParserConfiguration#getOutputFormat()} (which is usually
+     * {@link Configuration#getOutputFormat()}, {@link ParsingConfiguration#getOutputFormat()} (which is usually
      * provided by {@link Configuration#getTemplateConfigurations()}) and the {@code #ftl} header's
      * {@code output_format} option in the template.
      * 
@@ -692,7 +692,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
     /**
      * Returns if the auto-escaping policy (see {@link Configuration#setAutoEscapingPolicy(int)}) that this template
      * uses. This is decided from these, in increasing priority:
-     * {@link Configuration#getAutoEscapingPolicy()}, {@link ParserConfiguration#getAutoEscapingPolicy()},
+     * {@link Configuration#getAutoEscapingPolicy()}, {@link ParsingConfiguration#getAutoEscapingPolicy()},
      * {@code #ftl} header's {@code auto_esc} option in the template.
      */
     public int getAutoEscapingPolicy() {
@@ -733,7 +733,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
     /**
      * Returns the template source at the location specified by the coordinates given, or {@code null} if unavailable.
      * A strange legacy in the behavior of this method is that it replaces tab characters with spaces according the
-     * value of {@link Template#getParserConfiguration()}/{@link ParserConfiguration#getTabSize()} (which usually
+     * value of {@link Template#getParsingConfiguration()}/{@link ParsingConfiguration#getTabSize()} (which usually
      * comes from {@link Configuration#getTabSize()}), because tab characters move the column number with more than
      * 1 in error messages. However, if you set the tab size to 1, this method leaves the tab characters as is.
      * 
@@ -1128,7 +1128,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
         /**
          * @param r the character stream to wrap
          */
-        LineTableBuilder(Reader r, ParserConfiguration parserConfiguration) {
+        LineTableBuilder(Reader r, ParsingConfiguration parserConfiguration) {
             super(r);
             tabSize = parserConfiguration.getTabSize();
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
index f2a5fc6..efb8152 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
@@ -51,7 +51,7 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
  *
  * @see Template#Template(String, String, Reader, Configuration, TemplateConfiguration, Charset)
  */
-public final class TemplateConfiguration implements ParserAndProcessingConfiguration {
+public final class TemplateConfiguration implements ParsingAndProcessingConfiguration {
 
     private final Locale locale;
     private final String numberFormat;
@@ -669,7 +669,7 @@ public final class TemplateConfiguration implements ParserAndProcessingConfigura
         return null;
     }
 
-    public static final class Builder extends MutableProcessingAndParseConfiguration<Builder>
+    public static final class Builder extends MutableParsingAndProcessingConfiguration<Builder>
             implements CommonBuilder<TemplateConfiguration> {
 
         public Builder() {
@@ -826,7 +826,7 @@ public final class TemplateConfiguration implements ParserAndProcessingConfigura
          * {@link TemplateConfiguration}, possibly overwriting the earlier value in this object. (A setting is said to be
          * set in a {@link TemplateConfiguration} if it was explicitly set via a setter method, as opposed to be inherited.)
          */
-        public void merge(ParserAndProcessingConfiguration tc) {
+        public void merge(ParsingAndProcessingConfiguration tc) {
             if (tc.isAPIBuiltinEnabledSet()) {
                 setAPIBuiltinEnabled(tc.getAPIBuiltinEnabled());
             }
@@ -935,7 +935,7 @@ public final class TemplateConfiguration implements ParserAndProcessingConfigura
             }
 
             if (tc.isCustomAttributesSet()) {
-                setCustomAttributes(mergeMaps(
+                setCustomAttributesWithoutCopying(mergeMaps(
                         isCustomAttributesSet() ? getCustomAttributes() : null,
                         tc.isCustomAttributesSet() ? tc.getCustomAttributes() : null,
                         true));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/TemplateParserConfigurationWithFallback.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateParserConfigurationWithFallback.java b/src/main/java/org/apache/freemarker/core/TemplateParserConfigurationWithFallback.java
deleted file mode 100644
index e9758cf..0000000
--- a/src/main/java/org/apache/freemarker/core/TemplateParserConfigurationWithFallback.java
+++ /dev/null
@@ -1,146 +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;
-
-import java.nio.charset.Charset;
-
-import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
-import org.apache.freemarker.core.outputformat.OutputFormat;
-
-/**
- * Adds {@link Configuration} fallback to the {@link ParserConfiguration} part of a {@link TemplateConfiguration}.
- */
-final class TemplateParserConfigurationWithFallback implements ParserConfiguration {
-
-    private final Configuration cfg;
-    private final TemplateConfiguration tCfg;
-
-    TemplateParserConfigurationWithFallback(Configuration cfg, TemplateConfiguration tCfg) {
-        this.cfg = cfg;
-        this.tCfg = tCfg;
-    }
-
-    @Override
-    public TemplateLanguage getTemplateLanguage() {
-        return tCfg.isTemplateLanguageSet() ? tCfg.getTemplateLanguage() : cfg.getTemplateLanguage();
-    }
-
-    @Override
-    public boolean isTemplateLanguageSet() {
-        return true;
-    }
-
-    @Override
-    public int getTagSyntax() {
-        return tCfg.isTagSyntaxSet() ? tCfg.getTagSyntax() : cfg.getTagSyntax();
-    }
-
-    @Override
-    public boolean isTagSyntaxSet() {
-        return true;
-    }
-
-    @Override
-    public int getNamingConvention() {
-        return tCfg.isNamingConventionSet() ? tCfg.getNamingConvention() : cfg.getNamingConvention();
-    }
-
-    @Override
-    public boolean isNamingConventionSet() {
-        return true;
-    }
-
-    @Override
-    public boolean getWhitespaceStripping() {
-        return tCfg.isWhitespaceStrippingSet() ? tCfg.getWhitespaceStripping() : cfg.getWhitespaceStripping();
-    }
-
-    @Override
-    public boolean isWhitespaceStrippingSet() {
-        return true;
-    }
-
-    @Override
-    public ArithmeticEngine getArithmeticEngine() {
-        return tCfg.isArithmeticEngineSet() ? tCfg.getArithmeticEngine() : cfg.getArithmeticEngine();
-    }
-
-    @Override
-    public boolean isArithmeticEngineSet() {
-        return true;
-    }
-
-    @Override
-    public int getAutoEscapingPolicy() {
-        return tCfg.isAutoEscapingPolicySet() ? tCfg.getAutoEscapingPolicy() : cfg.getAutoEscapingPolicy();
-    }
-
-    @Override
-    public boolean isAutoEscapingPolicySet() {
-        return true;
-    }
-
-    @Override
-    public OutputFormat getOutputFormat() {
-        return tCfg.isOutputFormatSet() ? tCfg.getOutputFormat() : cfg.getOutputFormat();
-    }
-
-    @Override
-    public boolean isOutputFormatSet() {
-        return true;
-    }
-
-    @Override
-    public boolean getRecognizeStandardFileExtensions() {
-        return tCfg.isRecognizeStandardFileExtensionsSet() ? tCfg.getRecognizeStandardFileExtensions()
-                : cfg.getRecognizeStandardFileExtensions();
-    }
-
-    @Override
-    public boolean isRecognizeStandardFileExtensionsSet() {
-        return true;
-    }
-
-    @Override
-    public Version getIncompatibleImprovements() {
-        // This can be only set on the Configuration-level
-        return cfg.getIncompatibleImprovements();
-    }
-
-    @Override
-    public int getTabSize() {
-        return tCfg.isTabSizeSet() ? tCfg.getTabSize() : cfg.getTabSize();
-    }
-
-    @Override
-    public boolean isTabSizeSet() {
-        return true;
-    }
-
-    @Override
-    public Charset getSourceEncoding() {
-        return tCfg.isSourceEncodingSet() ? tCfg.getSourceEncoding() : cfg.getSourceEncoding();
-    }
-
-    @Override
-    public boolean isSourceEncodingSet() {
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/TemplateParsingConfigurationWithFallback.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateParsingConfigurationWithFallback.java b/src/main/java/org/apache/freemarker/core/TemplateParsingConfigurationWithFallback.java
new file mode 100644
index 0000000..93a5840
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/TemplateParsingConfigurationWithFallback.java
@@ -0,0 +1,146 @@
+/*
+ * 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;
+
+import java.nio.charset.Charset;
+
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
+import org.apache.freemarker.core.outputformat.OutputFormat;
+
+/**
+ * Adds {@link Configuration} fallback to the {@link ParsingConfiguration} part of a {@link TemplateConfiguration}.
+ */
+final class TemplateParsingConfigurationWithFallback implements ParsingConfiguration {
+
+    private final Configuration cfg;
+    private final TemplateConfiguration tCfg;
+
+    TemplateParsingConfigurationWithFallback(Configuration cfg, TemplateConfiguration tCfg) {
+        this.cfg = cfg;
+        this.tCfg = tCfg;
+    }
+
+    @Override
+    public TemplateLanguage getTemplateLanguage() {
+        return tCfg.isTemplateLanguageSet() ? tCfg.getTemplateLanguage() : cfg.getTemplateLanguage();
+    }
+
+    @Override
+    public boolean isTemplateLanguageSet() {
+        return true;
+    }
+
+    @Override
+    public int getTagSyntax() {
+        return tCfg.isTagSyntaxSet() ? tCfg.getTagSyntax() : cfg.getTagSyntax();
+    }
+
+    @Override
+    public boolean isTagSyntaxSet() {
+        return true;
+    }
+
+    @Override
+    public int getNamingConvention() {
+        return tCfg.isNamingConventionSet() ? tCfg.getNamingConvention() : cfg.getNamingConvention();
+    }
+
+    @Override
+    public boolean isNamingConventionSet() {
+        return true;
+    }
+
+    @Override
+    public boolean getWhitespaceStripping() {
+        return tCfg.isWhitespaceStrippingSet() ? tCfg.getWhitespaceStripping() : cfg.getWhitespaceStripping();
+    }
+
+    @Override
+    public boolean isWhitespaceStrippingSet() {
+        return true;
+    }
+
+    @Override
+    public ArithmeticEngine getArithmeticEngine() {
+        return tCfg.isArithmeticEngineSet() ? tCfg.getArithmeticEngine() : cfg.getArithmeticEngine();
+    }
+
+    @Override
+    public boolean isArithmeticEngineSet() {
+        return true;
+    }
+
+    @Override
+    public int getAutoEscapingPolicy() {
+        return tCfg.isAutoEscapingPolicySet() ? tCfg.getAutoEscapingPolicy() : cfg.getAutoEscapingPolicy();
+    }
+
+    @Override
+    public boolean isAutoEscapingPolicySet() {
+        return true;
+    }
+
+    @Override
+    public OutputFormat getOutputFormat() {
+        return tCfg.isOutputFormatSet() ? tCfg.getOutputFormat() : cfg.getOutputFormat();
+    }
+
+    @Override
+    public boolean isOutputFormatSet() {
+        return true;
+    }
+
+    @Override
+    public boolean getRecognizeStandardFileExtensions() {
+        return tCfg.isRecognizeStandardFileExtensionsSet() ? tCfg.getRecognizeStandardFileExtensions()
+                : cfg.getRecognizeStandardFileExtensions();
+    }
+
+    @Override
+    public boolean isRecognizeStandardFileExtensionsSet() {
+        return true;
+    }
+
+    @Override
+    public Version getIncompatibleImprovements() {
+        // This can be only set on the Configuration-level
+        return cfg.getIncompatibleImprovements();
+    }
+
+    @Override
+    public int getTabSize() {
+        return tCfg.isTabSizeSet() ? tCfg.getTabSize() : cfg.getTabSize();
+    }
+
+    @Override
+    public boolean isTabSizeSet() {
+        return true;
+    }
+
+    @Override
+    public Charset getSourceEncoding() {
+        return tCfg.isSourceEncodingSet() ? tCfg.getSourceEncoding() : cfg.getSourceEncoding();
+    }
+
+    @Override
+    public boolean isSourceEncodingSet() {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/_EvalUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/_EvalUtil.java b/src/main/java/org/apache/freemarker/core/_EvalUtil.java
index c89af2f..727085f 100644
--- a/src/main/java/org/apache/freemarker/core/_EvalUtil.java
+++ b/src/main/java/org/apache/freemarker/core/_EvalUtil.java
@@ -539,7 +539,7 @@ public class _EvalUtil {
     static ArithmeticEngine getArithmeticEngine(Environment env, ASTNode tObj) {
         return env != null
                 ? env.getArithmeticEngine()
-                : tObj.getTemplate().getParserConfiguration().getArithmeticEngine();
+                : tObj.getTemplate().getParsingConfiguration().getArithmeticEngine();
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/java/org/apache/freemarker/core/util/_KeyValuePair.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/_KeyValuePair.java b/src/main/java/org/apache/freemarker/core/util/_KeyValuePair.java
new file mode 100644
index 0000000..d88d8e4
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/util/_KeyValuePair.java
@@ -0,0 +1,61 @@
+/*
+ * 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.util;
+
+public class _KeyValuePair<K, V> {
+    private final K key;
+    private final V value;
+
+    public _KeyValuePair(K key, V value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    public K getKey() {
+        return key;
+    }
+
+    public V getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        _KeyValuePair<?, ?> that = (_KeyValuePair<?, ?>) o;
+
+        if (key != null ? !key.equals(that.key) : that.key != null) return false;
+        return value != null ? value.equals(that.value) : that.value == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = key != null ? key.hashCode() : 0;
+        result = 31 * result + (value != null ? value.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "_KeyValuePair{key=" + key + ", value=" + value + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 661cb5d..14a2fe7 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -80,7 +80,7 @@ public class FMParser {
     private OutputFormat outputFormat;
     private int autoEscapingPolicy;
     private boolean autoEscaping;
-    private ParserConfiguration pCfg;
+    private ParsingConfiguration pCfg;
     private InputStream streamToUnmarkWhenEncEstabd;
 
     /** Keeps track of #list nesting. */
@@ -96,21 +96,21 @@ public class FMParser {
     private int mixedContentNesting; // for stripText
 
     FMParser(Template template, Reader reader,
-            ParserConfiguration pCfg, OutputFormat outputFormat, Integer autoEscapingPolicy,
+            ParsingConfiguration pCfg, OutputFormat outputFormat, Integer autoEscapingPolicy,
             InputStream streamToUnmarkWhenEncEstabd) {
         this(template, true, readerToTokenManager(reader, pCfg),
                 pCfg, outputFormat, autoEscapingPolicy,
                 streamToUnmarkWhenEncEstabd);
     }
 
-    private static FMParserTokenManager readerToTokenManager(Reader reader, ParserConfiguration pCfg) {
+    private static FMParserTokenManager readerToTokenManager(Reader reader, ParsingConfiguration pCfg) {
         SimpleCharStream simpleCharStream = new SimpleCharStream(reader, 1, 1);
         simpleCharStream.setTabSize(pCfg.getTabSize());
         return new FMParserTokenManager(simpleCharStream);
     }
 
     FMParser(Template template, boolean newTemplate, FMParserTokenManager tkMan,
-            ParserConfiguration pCfg, OutputFormat contextOutputFormat, Integer contextAutoEscapingPolicy,
+            ParsingConfiguration pCfg, OutputFormat contextOutputFormat, Integer contextAutoEscapingPolicy,
     		InputStream streamToUnmarkWhenEncEstabd) {
         this(tkMan);
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/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 ba0267b..e74a951 100644
--- a/src/manual/en_US/FM3-CHANGE-LOG.txt
+++ b/src/manual/en_US/FM3-CHANGE-LOG.txt
@@ -190,6 +190,7 @@ the FreeMarer 3 changelog here:
   - Made TemplateConfiguration immutable, added a TemplateConfiguration.Builder.
   - Made Template immutable (via public API-s). Template-specific settings now can only come from the TemplateConfiguration associated
     to the template, or from the #ftl header for some settings (most notably for custom attributes).
+  - Renamed ParserConfiguration to ParsingConfiguration, so that the name is more consistent with the new ProcessingConfiguration.
 - Settings that have contained a charset name (sourceEncoding, outputEncoding, URLEscapingCharset) are now of type Charset,
   not String. For string based configuration sources (such as .properties files) this means that:
   - Unrecognized charset names are now errors

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/OutputFormatTest.java b/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
index 64fad5f..d651b9d 100644
--- a/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
+++ b/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
@@ -827,8 +827,9 @@ public class OutputFormatTest extends TemplateTest {
     
     @Test
     public void testDynamicParsingBIsInherticContextOutputFormat() throws Exception {
-        // Dynamic parser BI-s are supposed to use the parserConfiguration of the calling template, and ignore anything
-        // inside the calling template itself. Except, the outputFormat has to come from the calling lexical context.
+        // Dynamic parser BI-s are supposed to use the ParsingConfiguration of the calling template, and ignore anything
+        // inside the calling template itself. Except, the outputFormat and autoEscapingPolicy has to come from the
+        // calling lexical context.
         
         String commonFTL
                 = "Eval: ${'.outputFormat'?eval}; "

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/18a4ace8/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java b/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
index 5d57e48..593b912 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
@@ -254,7 +254,7 @@ public class TemplateConfigurationTest {
     static {
         PARSER_PROP_NAMES = new HashSet<>();
         // It's an interface; can't use standard Inrospector
-        for (Method m : ParserConfiguration.class.getMethods()) {
+        for (Method m : ParsingConfiguration.class.getMethods()) {
             String propertyName;
             String name = m.getName();
             if (name.startsWith("get")) {


Mime
View raw message