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 2022/12/31 23:15:27 UTC

[freemarker] branch 3 updated (d70778b3 -> cfb0651b)

This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a change to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git


    from d70778b3 Merge pull request #81 from kelemen/gradle-github-actions-v3
     new ef0c4296 Forward ported from 2.3-gae: Don't generate Google Analytics. (For simplicity I just copied the whole manual, but it's for FM2.)
     new 10e31294 Forward ported from 2.3-gae: Typo fixes, and some minor javadoc improvements
     new 1c8ea677 Forward ported from 2.3-gae: Added ?cUpperCase, and ?cLowerCase
     new f27a1276 Forward ported from 2.3-gae: FREEMARKER-198: To avoid deadlock when class initialization happens on multiple threads (like _TemplateAPI->DefaultObjectWrapper, and DefaultObjectWrapper->_TemplateAPI), factored out static fields from _TemplateAPI into their owns classes.
     new 6c535b8f Forward ported from 2.3-gae: PR #77
     new 53728100 Forward ported from 2.3-gae: Replace String with StringBuilder in ElementModel (PR #82)
     new 80a71b7d Forward ported from 2.3-gae: [FREEMARKER-187] Build failed on some systems due to character encoding issue
     new d2773c44 Forward ported from 2.3-gae: Fix: Typos "clalc." in TemplateException (PR #76)
     new cfb0651b Forward ported from 2.3-gae: Fix HTLM typos (PR #73)

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 FM3-CHANGE-LOG.txt                                 |     2 +-
 .../freemarker/converter/_ConverterUtils.java      |     2 +-
 .../apache/freemarker/core/ConfigurationTest.java  |    85 +-
 .../core/model/impl/DefaultObjectWrapperTest.java  |    60 +-
 .../templatesuite/expected/string-builtins1.txt    |     1 +
 .../templatesuite/templates/string-builtins1.f3ac  |     7 +
 .../org/apache/freemarker/core/ASTExpBuiltIn.java  |    49 +-
 .../freemarker/core/BuiltInsForStringsBasic.java   |    36 +-
 .../org/apache/freemarker/core/JSONParser.java     |    15 +-
 .../org/apache/freemarker/core/NativeSequence.java |    10 +-
 .../apache/freemarker/core/TemplateException.java  |    15 +-
 .../java/org/apache/freemarker/core/_CoreAPI.java  |     6 +-
 .../org/apache/freemarker/core/_DelayedAOrAn.java  |     2 +-
 .../core/_DelayedConversionToString.java           |     2 +-
 .../freemarker/core/_DelayedGetCanonicalForm.java  |     2 +-
 .../apache/freemarker/core/_DelayedGetMessage.java |     2 +-
 .../core/_DelayedGetMessageWithoutStackTop.java    |     2 +-
 .../org/apache/freemarker/core/_DelayedJQuote.java |     2 +-
 .../freemarker/core/_DelayedJQuotedListing.java    |     6 +-
 .../freemarker/core/_DelayedJoinWithComma.java     |     2 +-
 .../_DelayedTemplateLanguageTypeDescription.java   |     2 +-
 .../freemarker/core/_ErrorDescriptionBuilder.java  |    10 +-
 .../java/org/apache/freemarker/core/_Java8.java    |     2 +-
 .../org/apache/freemarker/core/_Java8Impl.java     |     2 +-
 .../_ObjectBuilderSettingEvaluationException.java  |     2 +-
 .../core/_ObjectBuilderSettingEvaluator.java       |    52 +-
 .../core/_SettingEvaluationEnvironment.java        |     6 +-
 ..._UnexpectedTypeErrorExplainerTemplateModel.java |     2 +-
 .../{_CharsetBuilder.java => _VersionInts.java}    |    25 +-
 .../impl/BigDecimalArithmeticEngine.java           |     6 +-
 .../freemarker/core/debug/_DebuggerService.java    |    10 +-
 .../core/model/TemplateMarkupOutputModel.java      |     4 +-
 .../outputformat/CommonMarkupOutputFormat.java     |    14 +-
 .../core/outputformat/MarkupOutputFormat.java      |    10 +-
 .../impl/DefaultTruncateBuiltinAlgorithm.java      |     4 +-
 .../templateresolver/TemplateLoadingSource.java    |     8 +-
 .../freemarker/core/util/_ArrayAdapterList.java    |     2 +-
 .../freemarker/core/util/_ArrayIterator.java       |     2 +-
 .../apache/freemarker/core/util/_ClassUtils.java   |     8 +-
 .../freemarker/core/util/_CollectionUtils.java     |    12 +-
 .../apache/freemarker/core/util/_DateUtils.java    |     8 +-
 .../apache/freemarker/core/util/_JavaVersions.java |     2 +-
 .../apache/freemarker/core/util/_NumberUtils.java  |     2 +-
 .../freemarker/core/util/_SortedArraySet.java      |     2 +-
 .../apache/freemarker/core/util/_StringUtils.java  |    10 +-
 .../core/util/_UnmodifiableCompositeSet.java       |     2 +-
 .../freemarker/core/util/_UnmodifiableSet.java     |     2 +-
 .../core/valueformat/TemplateNumberFormat.java     |     6 +-
 .../org/apache/freemarker/dom/ElementModel.java    |    10 +-
 freemarker-manual/src/main/docgen/en_US/book.xml   | 43816 ++++++++++++++++++-
 .../src/main/docgen/en_US/docgen.cjson             |    39 +-
 .../examples/AutoEscapingExample-convert.f3ah      |     2 +-
 .../examples/AutoEscapingExample-convert.f3ah.out  |     2 +-
 .../src/test/resources/META-INF/malformed.tld      |    31 -
 .../CopyrightCommentRemoverTemplateLoader.java     |    18 +-
 55 files changed, 44013 insertions(+), 430 deletions(-)
 copy freemarker-core/src/main/java/org/apache/freemarker/core/{_CharsetBuilder.java => _VersionInts.java} (61%)
 delete mode 100644 freemarker-servlet/src/test/resources/META-INF/malformed.tld


[freemarker] 07/09: Forward ported from 2.3-gae: [FREEMARKER-187] Build failed on some systems due to character encoding issue

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 80a71b7d89cf06fd1f30f200a7d207576399d9ff
Author: ddekany <dd...@apache.org>
AuthorDate: Sun Jan 1 00:09:10 2023 +0100

    Forward ported from 2.3-gae: [FREEMARKER-187] Build failed on some systems due to character encoding issue
---
 .../core/pluggablebuiltin/impl/DefaultTruncateBuiltinAlgorithm.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/pluggablebuiltin/impl/DefaultTruncateBuiltinAlgorithm.java b/freemarker-core/src/main/java/org/apache/freemarker/core/pluggablebuiltin/impl/DefaultTruncateBuiltinAlgorithm.java
index 48899e06..2a243713 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/pluggablebuiltin/impl/DefaultTruncateBuiltinAlgorithm.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/pluggablebuiltin/impl/DefaultTruncateBuiltinAlgorithm.java
@@ -91,8 +91,8 @@ public class DefaultTruncateBuiltinAlgorithm extends TruncateBuiltinAlgorithm {
             STANDARD_ASCII_TERMINATOR, STANDARD_M_TERMINATOR, true);
 
     /**
-     * Instance uses that {@code "[…]"} as the {@code defaultTerminator} constructor argument, which contains
-     * ellipsis character ({@code "…"}, U+2026), and thus only works with UTF-8, and the cp125x charsets (like
+     * Instance uses that {@code "[\u2026]"} as the {@code defaultTerminator} constructor argument, which contains
+     * ellipsis character ({@code "\u2026"}, U+2026), and thus only works with UTF-8, and the cp125x charsets (like
      * cp1250), and with some other rarely used ones. It does not work (becomes to a question mark) with ISO-8859-x
      * charsets (like ISO-8859-1), which are probably the most often used charsets after UTF-8.
      *


[freemarker] 06/09: Forward ported from 2.3-gae: Replace String with StringBuilder in ElementModel (PR #82)

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 537281002e34762543a760d33f12619d010aa54f
Author: ddekany <dd...@apache.org>
AuthorDate: Sun Jan 1 00:04:13 2023 +0100

    Forward ported from 2.3-gae: Replace String with StringBuilder in ElementModel (PR #82)
---
 .../src/main/java/org/apache/freemarker/dom/ElementModel.java  | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/freemarker-dom/src/main/java/org/apache/freemarker/dom/ElementModel.java b/freemarker-dom/src/main/java/org/apache/freemarker/dom/ElementModel.java
index 99750977..318278a0 100644
--- a/freemarker-dom/src/main/java/org/apache/freemarker/dom/ElementModel.java
+++ b/freemarker-dom/src/main/java/org/apache/freemarker/dom/ElementModel.java
@@ -19,8 +19,6 @@
  
 package org.apache.freemarker.dom;
 
-import java.util.Collections;
-
 import org.apache.freemarker.core.Environment;
 import org.apache.freemarker.core.Template;
 import org.apache.freemarker.core.TemplateException;
@@ -34,6 +32,8 @@ import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import java.util.Collections;
+
 class ElementModel extends NodeModel implements TemplateStringModel {
 
     public ElementModel(Element element) {
@@ -126,7 +126,7 @@ class ElementModel extends NodeModel implements TemplateStringModel {
     @Override
     public String getAsString() throws TemplateException {
         NodeList nl = node.getChildNodes();
-        String result = "";
+        StringBuilder result = new StringBuilder();
         for (int i = 0; i < nl.getLength(); i++) {
             Node child = nl.item(i);
             int nodeType = child.getNodeType();
@@ -137,10 +137,10 @@ class ElementModel extends NodeModel implements TemplateStringModel {
                              + "\" has a child element named: " + child.getNodeName();
                 throw new TemplateException(msg);
             } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) {
-                result += child.getNodeValue();
+                result.append(child.getNodeValue());
             }
         }
-        return result;
+        return result.toString();
     }
     
     @Override


[freemarker] 01/09: Forward ported from 2.3-gae: Don't generate Google Analytics. (For simplicity I just copied the whole manual, but it's for FM2.)

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit ef0c4296d77dbb9331037d6c4eacea543f85f4cb
Author: ddekany <dd...@apache.org>
AuthorDate: Sat Dec 31 21:49:36 2022 +0100

    Forward ported from 2.3-gae: Don't generate Google Analytics. (For simplicity I just copied the whole manual, but it's for FM2.)
---
 freemarker-manual/src/main/docgen/en_US/book.xml   | 43816 ++++++++++++++++++-
 .../src/main/docgen/en_US/docgen.cjson             |    39 +-
 2 files changed, 43805 insertions(+), 50 deletions(-)

diff --git a/freemarker-manual/src/main/docgen/en_US/book.xml b/freemarker-manual/src/main/docgen/en_US/book.xml
index e1013618..2f9d3b7d 100644
--- a/freemarker-manual/src/main/docgen/en_US/book.xml
+++ b/freemarker-manual/src/main/docgen/en_US/book.xml
@@ -19,59 +19,43805 @@
 -->
 <book conformance="docgen" version="5.0" xml:lang="en"
       xmlns="http://docbook.org/ns/docbook"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
 >
   <info>
     <title>Apache FreeMarker Manual</title>
 
     <titleabbrev>Manual</titleabbrev>
 
-    <productname>Freemarker 3.0.0</productname>
+    <productname>Freemarker 2.3.32</productname>
   </info>
 
   <preface role="index.html" xml:id="preface">
-    <title>TODO</title>
+    <title>What is Apache FreeMarker?</title>
 
-    <para>TODO... Eventually, we might copy the FM2 Manual and rework
-    it.</para>
+    <para>FreeMarker is a <emphasis>template engine</emphasis>: a generic tool
+    to generate text output (HTML web pages, e-mails, configuration files,
+    source code, etc.) based on templates and changing data. It's not an
+    application for end-users in itself, but a Java library, a component that
+    programmers can embed into their products.</para>
 
-    <para>Anchors to satisfy Docgen:</para>
+    <para>Templates are written in the FreeMarker Template Language (FTL).
+    It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
+    programming language like PHP. You are meant to prepare the data to
+    display in a real programming language, like issue database queries and do
+    business calculations, and then the template displays that already
+    prepared data. In the template you are focusing on how to present the
+    data, and outside the template you are focusing on what data to
+    present.</para>
 
-    <itemizedlist>
-      <listitem>
-        <para xml:id="app_versions">app_versions</para>
-      </listitem>
+    <mediaobject>
+      <imageobject>
+        <imagedata fileref="figures/overview.png"/>
+      </imageobject>
+    </mediaobject>
 
-      <listitem>
-        <para xml:id="app_license">app_license</para>
-      </listitem>
+    <para>This approach is often referred to as the <link
+    linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
+    particularly popular for dynamic web pages. It helps in separating web
+    page designers (HTML authors) from developers (Java programmers usually).
+    Designers won't face complicated logic in templates, and can change the
+    appearance of a page without programmers having to change or recompile
+    code.</para>
 
-      <listitem>
-        <para xml:id="exp_cheatsheet">exp_cheatsheet</para>
-      </listitem>
+    <para>While FreeMarker was originally created for generating HTML pages in
+    MVC web application frameworks, it isn't bound to servlets or HTML or
+    anything web-related. It's used in non-web application environments as
+    well.</para>
 
-      <listitem>
-        <para xml:id="ref_directive_alphaidx">ref_directive_alphaidx</para>
-      </listitem>
+    <para>FreeMarker is <link
+    xlink:href="http://www.fsf.org/philosophy/free-sw.html">Free</link>,
+    released under the Apache License, Version 2.0.</para>
+  </preface>
+
+  <part xml:id="dgui">
+    <title>Template Author's Guide</title>
+
+    <chapter xml:id="dgui_quickstart">
+      <title>Getting Started</title>
+
+      <para>This chapter is a very rough introduction to FreeMarker. The
+      chapters after this will go over things in much greater detail.
+      Nonetheless, once you have read this chapter, you will be able to write
+      simple but useful FreeMarker templates.</para>
+
+      <section xml:id="dgui_quickstart_basics">
+        <title>Template + data-model = output</title>
+
+        <para>Let's assume that you need a HTML page on a website, similar to
+        this:</para>
+
+        <programlisting role="output">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome <emphasis>John Doe</emphasis>!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="<emphasis>products/greenmouse.html</emphasis>"&gt;<emphasis>green mouse</emphasis>&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+        <para>But the user's name ("John Doe" above) depends on who the
+        logged-in user is, and the latest product information should come from
+        a database. Because this data changes, you cannot use static HTML.
+        Instead, you can use a <emphasis role="term">template</emphasis> of
+        the desired output. The template is the same as the static HTML would
+        be, except that it contains some instructions to FreeMarker that makes
+        it dynamic:</para>
+
+        <programlisting role="template" xml:id="example.first">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome <emphasis>${user}</emphasis>!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="<emphasis>${latestProduct.url}</emphasis>"&gt;<emphasis>${latestProduct.name}</emphasis>&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+        <para>The template is stored on the Web server, usually just like the
+        static HTML page would be. But whenever someone visits this page,
+        FreeMarker will step in and transform the template on-the-fly to plain
+        HTML by replacing the
+        <literal>${<replaceable>...</replaceable>}</literal>-s with up-to-date
+        content, and send the result to the visitor's Web browser. So the
+        visitor's Web browser will receive something like the first example
+        HTML (i.e., plain HTML without FreeMarker instructions), and it will
+        not perceive that FreeMarker is used on the server. (Of course, the
+        template file stored on the Web server is not changed by this; the
+        substitutions only appear in the Web server's response.)</para>
+
+        <para>Note that the template doesn't contain the programming logic to
+        find out who the current visitor is, or to query the database to get
+        the latest product. The data to be displayed is prepared outside
+        FreeMarker, usually by parts written in some <quote>real</quote>
+        programming language like Java. The template author needn't know how
+        these values were calculated. In fact, the way these values are
+        calculated can be completely changed while the templates can remain
+        exactly the same, and also, the look of the page can be completely
+        changed without touching anything but the template. This separation of
+        presentation logic and business logic can be especially useful when
+        the template authors (designers) and the programmers are different
+        individuals, but also helps managing application complexity if they
+        are the same person. Keeping templates focused on presentation issues
+        (visual design, layout and formatting) is a key for using template
+        engines like FreeMarker efficiently.</para>
+
+        <para><indexterm>
+            <primary>data-model</primary>
+          </indexterm>The totality of data that was prepared for the template
+        is called the <emphasis role="term">data-model</emphasis>. As far as
+        the template author is concerned, the data-model is a tree-like
+        structure (like folders and files on your hard disk), which, in this
+        case, could be visualized as:</para>
+
+        <programlisting role="dataModel">(root)
+  |
+  +- <emphasis>user</emphasis> = "Big Joe"
+  |
+  +- <emphasis>latestProduct</emphasis>
+      |
+      +- <emphasis>url</emphasis> = "products/greenmouse.html"
+      |
+      +- <emphasis>name</emphasis> = "green mouse"</programlisting>
+
+        <note>
+          <para>The above is just a visualization; the data-model is not in a
+          textual format, it's from Java objects. For the Java programmers,
+          the root is perhaps a Java object with <literal>getUser()</literal>
+          and <literal>getLatestProduct()</literal> methods, or maybe a Java
+          <literal>Map</literal> with <literal>"user"</literal> and
+          <literal>"latestProducts"</literal> keys. Similarly,
+          <literal>latestProduct</literal> is perhaps a Java Object with
+          <literal>getUrl()</literal> and <literal>getName()</literal>
+          methods.</para>
+        </note>
+
+        <para>Earlier, you have picked values from this data-model, with the
+        <literal>user</literal> and <literal>latestProduct.name</literal>
+        expressions. If we go on with the analogy that the data model is like
+        a file system, then <quote>(root)</quote> and
+        <literal>latestProduct</literal> correspond to directories (folders),
+        and <literal>user</literal>, <literal>url</literal> and
+        <literal>name</literal> are files in those directories.</para>
+
+        <para>To recapitulate, a template and a data-model is needed for
+        FreeMarker to generate the output (like the HTML shown first):</para>
+
+        <para><phrase role="markedTemplate">Template</phrase> + <phrase
+        role="markedDataModel">data-model</phrase> = <phrase
+        role="markedOutput">output</phrase></para>
+      </section>
+
+      <section xml:id="dgui_quickstart_datamodel">
+        <title>The data-model at a glance</title>
+
+        <para>As you have seen, the data-model is basically a tree. This tree
+        can be arbitrarily complicated and deep, for example:</para>
+
+        <programlisting role="dataModel"
+                        xml:id="example.qStart.dataModelWithHashes">(root)
+  |
+  +- animals
+  |   |
+  |   +- mouse
+  |   |   |
+  |   |   +- size = "small"
+  |   |   |
+  |   |   +- price = 50
+  |   |
+  |   +- elephant
+  |   |   |
+  |   |   +- size = "large"
+  |   |   |
+  |   |   +- price = 5000
+  |   |
+  |   +- python
+  |       |
+  |       +- size = "medium"
+  |       |
+  |       +- price = 4999
+  |
+  +- message = "It is a test"
+  |
+  +- misc
+      |
+      +- foo = "Something"</programlisting>
+
+        <para>The variables that act like directories (the root,
+        <literal>animals</literal>, <literal>mouse</literal>,
+        <literal>elephant</literal>, <literal>python</literal>,
+        <literal>misc</literal>) are called <emphasis
+        role="term">hashes</emphasis>. Hashes store other variables (the so
+        called <anchor xml:id="topic.dataModel.subVar"/><emphasis>sub
+        variables</emphasis>) by a lookup name (e.g., <quote>animals</quote>,
+        <quote>mouse</quote> or <quote>price</quote>).</para>
+
+        <para>The variables that store a single value
+        (<literal>size</literal>, <literal>price</literal>,
+        <literal>message</literal> and <literal>foo</literal>) are called
+        <emphasis role="term">scalars</emphasis>.</para>
+
+        <para><anchor xml:id="topic.qStart.accessVariables"/>When you want to
+        use a subvariable in a template, you specify its path from the root,
+        and separate the steps with dots. To access the
+        <literal>price</literal> of a <literal>mouse</literal>, you start from
+        the root and go into <literal>animals</literal>, and then go into
+        <literal>mouse</literal> then go into <literal>price</literal>. So you
+        write <literal>animals.mouse.price</literal>.</para>
+
+        <para>Another important kind of variables are <emphasis
+        role="term">sequences</emphasis>. They store subvariables like hashes,
+        but here subvariables doesn't have a name, they are just items in a
+        list. For example, in this data-model, <literal>animals</literal> and
+        <literal>misc.fruits</literal> are sequences:</para>
+
+        <programlisting role="dataModel"
+                        xml:id="example.qStart.dataModelWithSequences">(root)
+  |
+  +- animals
+  |   |
+  |   +- (1st)
+  |   |   |
+  |   |   +- name = "mouse"
+  |   |   |
+  |   |   +- size = "small"
+  |   |   |
+  |   |   +- price = 50
+  |   |
+  |   +- (2nd)
+  |   |   |
+  |   |   +- name = "elephant"
+  |   |   |
+  |   |   +- size = "large"
+  |   |   |
+  |   |   +- price = 5000
+  |   |
+  |   +- (3rd)
+  |       |
+  |       +- name = "python"
+  |       |
+  |       +- size = "medium"
+  |       |
+  |       +- price = 4999
+  |
+  +- misc
+      |
+      +- fruits
+          |
+          +- (1st) = "orange"
+          |
+          +- (2nd) = "banana"</programlisting>
+
+        <para>To access a subvariable of a sequence you use a numerical index
+        in square brackets. Indexes start from 0 (it's a programmer tradition
+        to start with 0), thus the index of the 1st item is 0, the index of
+        the 2nd item is 1, and so on. So to get the name of the first animal
+        you write <literal>animals[0].name</literal>. To get the second item
+        in <literal>misc.fruits</literal> (the string
+        <literal>"banana"</literal>) you write
+        <literal>misc.fruits[1]</literal>. (In practice, you usually just walk
+        through sequences in order, not caring about the index, but that will
+        be <link linkend="topic.tutorial.list">shown later</link>.)</para>
+
+        <para>Scalars can be further divided into these categories:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>String: Text, that is, an arbitrary sequence of characters
+            such as ''m'', ''o'', ''u'', ''s'', ''e'' above. For example the
+            <literal>name</literal>-s and <literal>size</literal>-s are
+            strings above.</para>
+          </listitem>
+
+          <listitem>
+            <para>Number: It's a numerical value, like the
+            <literal>price</literal>-s above. The string
+            <literal>"50"</literal> and the number <literal>50</literal> are
+            two totally different things in FreeMarker. The former is just a
+            sequence of two characters (which happens to be readable as a
+            number for humans), while the latter is a numerical value that you
+            can use in arithmetical calculations.</para>
+          </listitem>
+
+          <listitem>
+            <para>Date-like: Either a date-time (stores a date with time of
+            the day), or a date (no time of day), or a time (time of day, no
+            date).</para>
+          </listitem>
+
+          <listitem>
+            <para>Boolean: A true/false (yes/no, on/off, etc.) thing. Like
+            animals could have a <literal>protected</literal> subvariable,
+            which store if the animal is protected or not.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Summary:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>The data-model can be visualized as a tree.</para>
+          </listitem>
+
+          <listitem>
+            <para>Scalars store a single value. The value can be a string or a
+            number or a date-time/date/time or a boolean.</para>
+          </listitem>
+
+          <listitem>
+            <para>Hashes are containers that store other variables and
+            associate them with a unique lookup name.</para>
+          </listitem>
+
+          <listitem>
+            <para>Sequences are containers that store other variables in an
+            ordered sequence. The stored variables can be retrieved via their
+            numerical index, starting from 0.</para>
+          </listitem>
+        </itemizedlist>
+
+        <note>
+          <para>There are other, more advanced value types that we don't cover
+          here, such as methods and directives.</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_quickstart_template">
+        <title>The template at a glance</title>
+
+        <para>The simplest template is a plain HTML file (or whatever text
+        file; FreeMarker is not confined to HTML). When the client visits that
+        page, FreeMarker will send that HTML to the client as is. However if
+        you want that page to be more dynamic then you begin to put special
+        parts into the HTML which will be understood by FreeMarker:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><literal>${<replaceable>...</replaceable>}</literal>:
+            FreeMarker will replace it in the output with the actual value of
+            the expression inside the curly brackets. They are called
+            <emphasis role="term">interpolation</emphasis>s.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">FTL tags</emphasis> (for FreeMarker
+            Template Language tags): FTL tags are a bit similar to HTML tags,
+            but they are instructions to FreeMarker and will not be printed to
+            the output. The name of these tags start with
+            <literal>#</literal>. (User-defined FTL tags use
+            <literal>@</literal> instead of <literal>#</literal>, but they are
+            an advanced topic.)</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Comments:</emphasis> Comments are
+            similar to HTML comments, but they are delimited by
+            <literal>&lt;#--</literal> and <literal>--&gt;</literal>. Unlike
+            HTML comments, FTL comments won't get into the output (won't be
+            visible in the page source for the visitor), because FreeMarker
+            skips them.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Anything not an FTL tag or an interpolation or comment is
+        considered static text and will not be interpreted by FreeMarker; it
+        is just printed to the output as-is.</para>
+
+        <para>With FTL tags you refer to so-called <emphasis
+        role="term">directives</emphasis>. This is the same kind of
+        relationship as between HTML tags (e.g.:
+        <literal>&lt;table&gt;</literal> and
+        <literal>&lt;/table&gt;</literal>) and HTML elements (e.g., the
+        <literal>table</literal> element) to which you refer to with the HTML
+        tags. (If you don't understand this difference then consider "FTL tag"
+        and "directive" synonyms.)</para>
+
+        <note>
+          <para>You can easily try writing templates on <link
+          xlink:href="http://freemarker-online.kenshoo.com/">http://freemarker-online.kenshoo.com/</link></para>
+        </note>
+
+        <section>
+          <title>Some basic directives</title>
+
+          <para>Here we will look at some of the most commonly used directives
+          (<link linkend="ref_directives">but there are much
+          more</link>).</para>
+
+          <section>
+            <title>The if directive</title>
+
+            <para>With the <literal>if</literal> directive you can
+            conditionally skip a section of the template. For example, assume
+            that in the <link linkend="example.first">very first
+            example</link> you want to greet your boss, Big Joe, differently
+            than other users:</para>
+
+            <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;
+    Welcome ${user}<emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>, our beloved leader<emphasis>&lt;/#if&gt;</emphasis>!
+  &lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>Here you have told FreeMarker that the <quote>, our beloved
+            leader</quote> should be there only if the value of the variable
+            <literal>user</literal> is equal to the string <literal>"Big
+            Joe"</literal>. In general, things between <literal>&lt;#if
+            <replaceable>condition</replaceable>&gt;</literal> and
+            <literal>&lt;/#if&gt;</literal> tags are skipped if
+            <literal><replaceable>condition</replaceable></literal> is false
+            (the boolean value).</para>
+
+            <para>Let's look at
+            <literal><replaceable>condition</replaceable></literal> more
+            closely: <literal>==</literal> is an operator that tests if the
+            values at its left and right side are equivalent, and the results
+            is a boolean value, true or false accordingly. On the left side of
+            <literal>==</literal> I have <link
+            linkend="topic.qStart.accessVariables">referenced a
+            variable</link> with the syntax that should be already familiar;
+            this will be replaced with the value of the variable. In general,
+            unquoted words inside directives or interpolations are treated as
+            references to variables. On the right side I have specified a
+            literal string. Literal strings in templates must
+            <emphasis>always</emphasis> be put inside quotation marks.</para>
+
+            <para>This will print <quote>Pythons are free today!</quote> if
+            their price is 0:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price == <emphasis>0</emphasis>&gt;
+  Pythons are free today!
+&lt;/#if&gt;</programlisting>
+
+            <para>Similarly as earlier when a string was specified directly,
+            here a number is specified directly (<literal>0</literal>). Note
+            that the number is <emphasis>not</emphasis> quoted. If you quoted
+            it (<literal>"0"</literal>), FreeMarker would misinterpret it as a
+            string literal, and because the price to compare it to is a
+            number, you get an error.</para>
+
+            <para>This will print "Pythons are not free today!" if their price
+            is not 0:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price <emphasis>!=</emphasis> 0&gt;
+  Pythons are not free today!
+&lt;/#if&gt;</programlisting>
+
+            <para>As you probably guessed, <literal>!=</literal> means
+            <quote>not equals</quote>.</para>
+
+            <para>You can write things like this too (using <link
+            linkend="example.qStart.dataModelWithHashes">the data-model used
+            to demonstrate hashes</link>):</para>
+
+            <programlisting role="template">&lt;#if <emphasis>animals.python.price &lt; animals.elephant.price</emphasis>&gt;
+  Pythons are cheaper than elephants today.
+&lt;/#if&gt;</programlisting>
+
+            <para>With the <literal>&lt;#else&gt;</literal> tag you can
+            specify what to do if the condition is false. For example:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
+  Pythons are cheaper than elephants today.
+<emphasis>&lt;#else&gt;</emphasis>
+  Pythons are not cheaper than elephants today.
+&lt;/#if&gt;</programlisting>
+
+            <para>This prints <quote>Pythons are cheaper than elephants
+            today.</quote> if the price of python is less than the price of
+            elephant, or else it prints <quote>Pythons are not cheaper than
+            elephants today.</quote> You can refine this further by using
+            <literal>elseif</literal>:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
+  Pythons are cheaper than elephants today.
+<emphasis>&lt;#elseif animals.elephant.price &lt; animals.python.price&gt;</emphasis>
+  Elephants are cheaper than pythons today.
+&lt;#else&gt;
+  Elephants and pythons cost the same today.
+&lt;/#if&gt;</programlisting>
+
+            <para>If you have a variable with boolean value (a true/false
+            thing) then you can use it directly as the
+            <literal><replaceable>condition</replaceable></literal> of
+            <literal>if</literal>:</para>
+
+            <programlisting role="template">&lt;#if animals.python.protected&gt;
+  Pythons are protected animals!
+&lt;/#if&gt;</programlisting>
+          </section>
+
+          <section>
+            <title>The list directive</title>
+
+            <anchor xml:id="topic.tutorial.list"/>
+
+            <para>This is needed when you want to list something. For example
+            if you merge this template with the <link
+            linkend="example.qStart.dataModelWithSequences">data-model used
+            earlier to demonstrate sequences</link>:</para>
+
+            <programlisting role="template">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+  <emphasis>&lt;#list animals as animal&gt;</emphasis>
+    &lt;tr&gt;&lt;td&gt;${<emphasis>animal</emphasis>.name}&lt;td&gt;${<emphasis>animal</emphasis>.price} Euros
+  <emphasis>&lt;/#list&gt;</emphasis>
+&lt;/table&gt;</programlisting>
+
+            <para>then the output will be:</para>
+
+            <programlisting role="output">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+    <emphasis>&lt;tr&gt;&lt;td&gt;mouse&lt;td&gt;50 Euros
+    &lt;tr&gt;&lt;td&gt;elephant&lt;td&gt;5000 Euros
+    &lt;tr&gt;&lt;td&gt;python&lt;td&gt;4999 Euros</emphasis>
+&lt;/table&gt;</programlisting>
+
+            <para>The generic form of the <literal>list</literal> directive
+            is:<literal> &lt;#list <replaceable>sequence</replaceable> as
+            <replaceable>loopVariable</replaceable>&gt;<replaceable>repeatThis</replaceable>&lt;/#list&gt;</literal>.
+            The <literal><replaceable>repeatThis</replaceable></literal> part
+            will be repeated for each item in the sequence that you have
+            specified with
+            <literal><replaceable>sequence</replaceable></literal>, one after
+            the other, starting from the first item. In all repetitions
+            <literal><replaceable>loopVariable</replaceable></literal> will
+            hold the value of the current item. This variable exists only
+            between the <literal>&lt;#list
+            <replaceable>...</replaceable>&gt;</literal> and
+            <literal>&lt;/#list&gt;</literal> tags.</para>
+
+            <para>The <literal><replaceable>sequence</replaceable></literal>
+            can be any kind of expression. For example we could list the
+            fruits of the example data model like this:</para>
+
+            <programlisting role="template">&lt;ul&gt;
+<emphasis>&lt;#list misc.fruits as fruit&gt;</emphasis>
+  &lt;li&gt;${fruit}
+<emphasis>&lt;/#list&gt;</emphasis>
+&lt;/ul&gt;</programlisting>
+
+            <para>The <literal>misc.fruits</literal> expression should be
+            familiar to you; it <link
+            linkend="topic.qStart.accessVariables">references a variable in
+            the data-model</link>.</para>
+
+            <para>A problem with the above example is that if we happen to
+            have 0 fruits, it will still print an empty
+            <literal>&lt;ul&gt;&lt;/ul&gt;</literal> instead of just nothing.
+            To avoid that, you can use this form of
+            <literal>list</literal>:</para>
+
+            <programlisting role="template">&lt;#list misc.fruits&gt;
+  &lt;ul&gt;
+   <emphasis> &lt;#items as fruit&gt;</emphasis>
+      &lt;li&gt;${fruit}
+ <emphasis>   &lt;/#items&gt;</emphasis>
+  &lt;/ul&gt;
+&lt;/#list&gt;</programlisting>
+
+            <para>Here, the <literal>list</literal> directive represents the
+            listing as a whole, and only the part inside the
+            <literal>items</literal> directive is repeated for each fruit. If
+            we have 0 fruits, everything inside <literal>list</literal> is
+            skipped, hence we will not have <literal>ul</literal> tags in
+            case.</para>
+
+            <para>Another frequent listing-related task: let's list the fruits
+            separating them with something, like a comma:</para>
+
+            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}<emphasis>&lt;#sep&gt;, </emphasis>&lt;/#list&gt;</programlisting>
+
+            <programlisting role="output">&lt;p&gt;Fruits: orange, banana</programlisting>
+
+            <para>The section covered by <literal>sep</literal> (which we
+            could be written like this too:
+            <literal><replaceable>...</replaceable>&lt;#sep&gt;,
+            &lt;/#sep&gt;&lt;/#list&gt;</literal>) will be only executed when
+            there will be a next item. Hence there's no comma after the last
+            fruit.</para>
+
+            <para>Here again, what if we have 0 fruits? Just printing
+            <quote>Fruits:</quote> and then nothing is awkward. A
+            <literal>list</literal>, just like an <literal>if</literal>, can
+            have an <literal>else</literal>, which is executed if there were 0
+            list items:</para>
+
+            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}&lt;#sep&gt;, <emphasis>&lt;#else&gt;None</emphasis>&lt;/#list&gt;</programlisting>
+
+            <note>
+              <para>As a matter of fact, this simplistic example could be
+              written like this, but it uses language devices that are off
+              topic here:</para>
+
+              <programlisting role="template">&lt;p&gt;Fruits: ${fruits?join(", ", "None")}</programlisting>
+            </note>
+
+            <para>All these directives (<literal>list</literal>,
+            <literal>items</literal>, <literal>sep</literal>,
+            <literal>else</literal>) can be used together:</para>
+
+            <programlisting role="template">&lt;#list misc.fruits&gt;
+  &lt;p&gt;Fruits:
+  &lt;ul&gt;
+    &lt;#items as fruit&gt;
+      &lt;li&gt;${fruit}&lt;#sep&gt; and&lt;/#sep&gt;
+    &lt;/#items&gt;
+  &lt;/ul&gt;
+&lt;#else&gt;
+  &lt;p&gt;We have no fruits.
+&lt;/#list&gt;</programlisting>
+
+            <note>
+              <para>You can read more about these directives <link
+              linkend="ref_directive_list">in the Reference</link>.</para>
+            </note>
+          </section>
+
+          <section>
+            <title>The include directive</title>
+
+            <para>With the <literal>include</literal> directive you can insert
+            the content of another file into the template.</para>
+
+            <para>Suppose you have to show the same copyright notice on
+            several pages. You can create a file that contains the copyright
+            notice only, and insert that file everywhere where you need that
+            copyright notice. Say, you store this copyright notice in
+            <literal>copyright_footer.html</literal>:</para>
+
+            <programlisting role="template">&lt;hr&gt;
+&lt;i&gt;
+Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
+&lt;br&gt;
+All Rights Reserved.
+&lt;/i&gt;</programlisting>
+
+            <para>Whenever you need that file you simply insert it with the
+            <literal>include</literal> directive:</para>
+
+            <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Test page&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Test page&lt;/h1&gt;
+  &lt;p&gt;Blah blah...
+<emphasis>  &lt;#include "/copyright_footer.html"&gt;</emphasis>
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>and the output will be:</para>
+
+            <programlisting role="output">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Test page&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Test page&lt;/h1&gt;
+  &lt;p&gt;Blah blah...
+<emphasis>&lt;hr&gt;
+&lt;i&gt;
+Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
+&lt;br&gt;
+All Rights Reserved.
+&lt;/i&gt;</emphasis>
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>If you change the <literal>copyright_footer.html</literal>,
+            then the visitor will see the new copyright notice on all
+            pages.</para>
+
+            <note>
+              <para>A much more powerful way of reusing snippets is using
+              macros, but that's an advanced topic <link
+              linkend="dgui_misc_userdefdir">discussed later</link>.</para>
+            </note>
+          </section>
+        </section>
+
+        <section>
+          <title>Using directives together</title>
+
+          <para>You can use directives as many times on a page as you want,
+          and you can nest directives into each other freely. For example,
+          here you nest <literal>if</literal> directive inside a
+          <literal>list</literal> directive:</para>
+
+          <programlisting role="template"><emphasis>&lt;#list animals as animal&gt;</emphasis>
+      &lt;div<emphasis>&lt;#if animal.protected&gt;</emphasis><emphasis> </emphasis>class="protected"<emphasis>&lt;/#if&gt;</emphasis>&gt;
+        ${animal.name} for ${animal.price} Euros
+      &lt;/div&gt;
+<emphasis>&lt;/#list&gt;</emphasis></programlisting>
+
+          <para>Note that since FreeMarker does not interpret text outside FTL
+          tags, interpolations and FTL comments, above you could use the FTL
+          tags inside HTML attributes without problem.</para>
+        </section>
+
+        <section>
+          <title>Using built-ins</title>
+
+          <para>The so-called built-ins are like subvariables (or rather like
+          methods, if you know that Java term) that aren't coming from the
+          data-model, but added by FreeMarker to the values. In order to make
+          it clear where subvariables comes from, you have to use
+          <literal>?</literal> (question mark) instead of <literal>.</literal>
+          (dot) to access them. <anchor
+          xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most
+          commonly used built-ins:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>user?upper_case</literal> gives the upper case
+              version of the value of <literal>user</literal> (like
+              <quote>JOHN DOE</quote> instead of <quote>John
+              Doe</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animal.name?cap_first</literal> give the
+              <literal>animal.name</literal> with its first letter converted
+              to upper case (like <quote>Mouse</quote> instead of
+              <quote>mouse</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?length</literal> gives the number of
+              <emphasis>characters</emphasis> in the value of
+              <literal>user</literal> (8 for <quote>John Doe</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animals?size</literal> gives the number of
+              <emphasis>items</emphasis> in the <literal>animals</literal>
+              sequence (3 in our example data-model)</para>
+            </listitem>
+
+            <listitem>
+              <para>If you are between <literal>&lt;#list animals as
+              animal&gt;</literal> and the corresponding
+              <literal>&lt;/#list&gt;</literal> tag:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para><literal>animal?index</literal> gives the 0-based
+                  index of <literal>animal</literal> inside
+                  <literal>animals</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>animal?counter</literal> is like
+                  <literal>index</literal>, but gives the 1-based index</para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>animal?item_parity</literal> gives the
+                  strings <quote>odd</quote> or <quote>even</quote>, depending
+                  on the current counter parity. This is commonly used for
+                  coloring rows with alternating colors, like in
+                  <literal>&lt;td
+                  class="${animal?item_parity}Row"&gt;</literal>.</para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+          </itemizedlist>
+
+          <para>Some built-ins require parameters to specify the behavior
+          more, for example:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>animal.protected?string("Y", "N")</literal>
+              return the string <quote>Y</quote> or <quote>N</quote> depending
+              on the boolean value of
+              <literal>animal.protected</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animal?item_cycle('lightRow',
+              'darkRow')</literal> is the more generic variant of
+              <literal>item_parity</literal> from earlier.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>fruits?join(", ")</literal>: converts the list to
+              a string by concatenating items, and inserting the parameter
+              separator between each items (like <quote>orange,
+              banana</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?starts_with("J")</literal> gives boolean
+              true of false depending on if <literal>user</literal> starts
+              with the letter <quote>J</quote> or not.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animals?filter(it -&gt; it.protected)</literal>
+              gives the list of protected animals. To list protected animals
+              only, you could use <literal>&lt;#list animals?filter(it -&gt;
+              it.protected) as
+              animal&gt;<replaceable>...</replaceable>&lt;/#list&gt;</literal>.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Built-in applications can be chained, like
+          <literal>fruits?join(", ")?upper_case</literal> will first convert
+          the list a to a string, then converts it to upper case. (This is
+          just like you can chain <literal>.</literal>-s (dots) too.)</para>
+
+          <para>You can find the <link linkend="ref_builtins">full set of
+          built-ins in the Reference</link>.</para>
+        </section>
+
+        <section>
+          <title>Dealing with missing variables</title>
+
+          <para>The data-model often has variables that are optional (i.e.,
+          sometimes missing). To spot some typical human mistakes, FreeMarker
+          doesn't tolerate references to missing variables unless you tell
+          explicitly what to do if the variable is missing. Here we will show
+          the two most typical ways of doing that.</para>
+
+          <para><phrase role="forProgrammers">Note for programmers: A
+          non-existent variable and a variable with <literal>null</literal>
+          value is the same for FreeMarker. The "missing" term used here
+          covers both cases.</phrase></para>
+
+          <para>Wherever you refer to a variable, you can specify a default
+          value for the case the variable is missing by following the variable
+          name with a <literal>!</literal> and the default value. Like in the
+          following example, when <literal>user</literal> is missing from data
+          model, the template will behave like if <literal>user</literal>'s
+          value were the string <literal>"visitor"</literal>. (When
+          <literal>user</literal> isn't missing, this template behaves exactly
+          like with <literal>${user}</literal>):</para>
+
+          <programlisting role="template">&lt;h1&gt;Welcome ${user<emphasis>!"visitor"</emphasis>}!&lt;/h1&gt;</programlisting>
+
+          <para>You can ask whether a variable isn't missing by putting
+          <literal>??</literal> after its name. Combining this with the
+          already introduced <literal>if</literal> directive you can skip the
+          whole greeting if the <literal>user</literal> variable is
+          missing:</para>
+
+          <programlisting role="template">&lt;#if <emphasis>user??</emphasis>&gt;&lt;h1&gt;Welcome ${user}!&lt;/h1&gt;&lt;/#if&gt;</programlisting>
+
+          <para>Regarding variable accessing with multiple steps, like
+          <literal>animals.python.price</literal>, writing
+          <literal>animals.python.price!0</literal> is correct only if
+          <literal>animals.python</literal> is never missing and only the last
+          subvariable, <literal>price</literal>, is possibly missing (in which
+          case here we assume it's <literal>0</literal>). If
+          <literal>animals</literal> or <literal>python</literal> is missing,
+          the template processing will stop with an "undefined variable"
+          error. To prevent that, you have to write
+          <literal>(animals.python.price)!0</literal>. In that case the
+          expression will be <literal>0</literal> even if
+          <literal>animals</literal> or <literal>python</literal> is missing.
+          Same logic goes for <literal>??</literal>;
+          <literal>animals.python.price??</literal> versus
+          <literal>(animals.python.price)??</literal>.</para>
+        </section>
+
+        <section xml:id="dgui_quickstart_template_autoescaping">
+          <title>Escaping for HTML, XML and other markup</title>
+
+          <para>Let's say the template generates HTML, and you insert values
+          with <literal>${<replaceable>...</replaceable>}</literal> that are
+          plain text (not HTML), like company names coming from a database.
+          Characters that has special meaning in HTML must be
+          <emphasis>escaped</emphasis> in such values, like if
+          <literal>name</literal> is <quote>Someone &amp; Co.</quote> then
+          <literal>${name}</literal> should print <quote>Someone
+          <emphasis>&amp;amp;</emphasis> Co.</quote>.</para>
+
+          <para>FreeMarker automatically escapes all values printed with
+          <literal>${<replaceable>...</replaceable>}</literal> <emphasis>if
+          it's properly configured</emphasis> (that's the responsibility of
+          the programmers; <link
+          linkend="pgui_config_outputformatsautoesc">see here how</link>). The
+          recommended practice is using <literal>ftlh</literal> file extension
+          to activate HTML auto-escaping, and <literal>ftlx</literal> file
+          extension to activate XML auto-escaping.</para>
+
+          <para>You can try if auto-escaping is on like
+          <literal>${"&lt;"}</literal> and then checking the raw output (for
+          HTML or XML escaping). If it's not, and the configuration won't be
+          adjusted, add this as the very first line of the template:</para>
+
+          <programlisting role="template">&lt;#ftl output_format="HTML"&gt;</programlisting>
+
+          <para>(Use <literal>"XML"</literal> instead of
+          <literal>"HTML"</literal> above if you generate XML.)</para>
+
+          <para>If the string value to print deliberately contains markup,
+          auto-escaping must be prevented like
+          <literal>${<replaceable>value</replaceable>?no_esc}</literal>.</para>
+
+          <para>You can find out much more about auto-escaping and output
+          formats <link linkend="dgui_misc_autoescaping">here...</link></para>
+
+          <note>
+            <para>The kind of automatic escaping described here requires at
+            least FreeMarker 2.3.24. If you have to use an earlier version,
+            use the deprecated <link
+            linkend="ref_directive_escape"><literal>escape</literal>
+            directive</link> instead.</para>
+          </note>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_datamodel">
+      <title>Values, Types</title>
+
+      <section xml:id="dgui_datamodel_basics">
+        <title>Basics</title>
+
+        <note>
+          <para>It is assumed that you have already read the <xref
+          linkend="dgui_quickstart"/> chapter.</para>
+        </note>
+
+        <para>Understanding the concept of values and types is crucial for the
+        understanding of data-models. However, the concept of values and types
+        is not confined to data-models, as you will see.</para>
+
+        <section xml:id="topic.value">
+          <title>What is a value?</title>
+
+          <indexterm>
+            <primary>value</primary>
+          </indexterm>
+
+          <para><phrase role="forProgrammers">Real programmers can safely skip
+          this section.</phrase></para>
+
+          <para>Examples of <emphasis>values</emphasis> as you know the term
+          from the everyday math are 16, 0.5, and so on, i.e. numbers. In the
+          case of computer languages the value term has a wider meaning, as a
+          value needn't be a number. For example, take this data-model:</para>
+
+          <programlisting role="dataModel" xml:id="example.stdDataModel">(root)
+ |
+ +- user = "Big Joe"
+ |
+ +- today = Jul 6, 2007
+ |
+ +- todayHoliday = false
+ |
+ +- lotteryNumbers
+ |   |
+ |   +- (1st) = 20
+ |   |
+ |   +- (2nd) = 14
+ |   |
+ |   +- (3rd) = 42
+ |   |
+ |   +- (4th) = 8
+ |   |
+ |   +- (5th) = 15
+ |
+ +- cargo
+     |
+     +- name = "coal"
+     |
+     +- weight = 40
+</programlisting>
+
+          <para>We say that the <emphasis>value</emphasis> of the the
+          <literal>user</literal> variable is "Big Joe" (a string), the
+          <emphasis>value</emphasis> of <literal>today</literal> is Jul 6,
+          2007 (a date), the <emphasis>value</emphasis> of
+          <literal>todayHoliday</literal> is false (a boolean, ie. a yes/no
+          thing). The <emphasis>value</emphasis> of
+          <literal>lotteryNumbers</literal> is the sequence that contains 20,
+          14, 42, 8, 15. Surely <literal>lotteryNumbers</literal> is multiple
+          values in the sense that it <emphasis>contains</emphasis> multiple
+          values (for example, the 2nd item in it is a the
+          <emphasis>value</emphasis> 14), but still,
+          <literal>lotteryNumbers</literal> itself is a single value. It's
+          like a box that contains many other items; the whole box can be seen
+          as a single item. Last not least we also have the
+          <emphasis>value</emphasis> of <literal>cargo</literal>, which is a
+          hash (a box-like thing again).So, a value is something that can be
+          stored in a variable (e.g., in <literal>user</literal> or
+          <literal>cargo</literal> or <literal>cargo.name</literal>). But a
+          value need not be stored in a variable to be called a value, for
+          example we have the value 100 here:</para>
+
+          <programlisting role="template">&lt;#if cargo.weight &lt; <emphasis>100</emphasis>&gt;Light cargo&lt;/#if&gt;</programlisting>
+
+          <para>The temporaly result of a calculations are also called values,
+          like 20 and 120 when this template is executed (it will print
+          120):</para>
+
+          <programlisting role="template">${cargo.weight / 2 + 100}</programlisting>
+
+          <para>Explanation for this last: As the result of dividing the two
+          values, 40 (the weight of the cargo) and 2, a new value 20 is
+          created. Then 100 is added to it, so the value 120 is created. Then
+          120 is printed
+          (<literal>${<replaceable>...</replaceable>}</literal>), and the
+          template execution goes on and all these values gone.</para>
+
+          <para>Certainly now you feel what the value term means.</para>
+        </section>
+
+        <section>
+          <title>What is type?</title>
+
+          <para>Values have an important aspect, their type. For example the
+          type of the value of the <literal>user</literal> variable is string,
+          and the type of the value of the <literal>lotteryNumbers</literal>
+          variable is sequence. The type of a value is important because it
+          determines to a large extent how and where you can use the value.
+          Like <literal>${user / 2}</literal> is an error, but
+          <literal>${cargo.weight / 2}</literal> works and prints 20, since
+          division only does make sense for a number, but not for a string.
+          Or, using dot like in <literal>cargo.name</literal> does make sense
+          only if <literal>cargo</literal> is a hash. Or, you can list with
+          <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
+          sequences only. Or, the condition of <literal>&lt;#if
+          ...&gt;</literal> must be a boolean. And so on.</para>
+
+          <note>
+            <para>A little terminology... Saying "a boolean" or "a boolean
+            value" or "a value of type boolean" are all the same.</para>
+          </note>
+
+          <para xml:id="topic.multitype"><indexterm>
+              <primary>Multi-typed value</primary>
+            </indexterm>A value can have multiple types at the same time,
+          although it's rarely utilized. For example in the data-model below
+          <literal>mouse</literal> is both a string and a hash:</para>
+
+          <programlisting role="dataModel">(root)
+ |
+ +- mouse = "Yerri"
+     |
+     +- age = 12
+     |
+     +- color = "brown"</programlisting>
+
+          <para>If you merge this template with the above data-model:</para>
+
+          <programlisting role="template">${mouse}       &lt;#-- uses mouse as a string --&gt;
+${mouse.age}   &lt;#-- uses mouse as a hash --&gt;
+${mouse.color} &lt;#-- uses mouse as a hash --&gt;</programlisting>
+
+          <para>the output will be:</para>
+
+          <programlisting role="output">Yerri
+12
+brown</programlisting>
+        </section>
+
+        <section>
+          <title>The data-model is a hash</title>
+
+          <para>Looking at the various data-model examples you may already
+          realized: the thing marked as "(root)" is just a value of type hash.
+          When you write something like <literal>user</literal>, that means
+          that you want the "user" variable stored in the root hash. Like if
+          you were writing <literal>root.user</literal>, except that there is
+          no variable called "root" so that wouldn't work.</para>
+
+          <para>Some may get confused by the fact that our example data-model,
+          that is, the root hash, contains further hashes and sequences
+          (<literal>lotteryNumbers</literal> and <literal>cargo</literal>).
+          There is nothing special in that. A hash contains other variables,
+          and those variables have a value, which can be a string, a number,
+          etc., and of course it can be a hash or sequence as well. Because,
+          as it was explained earlier, a sequence or a hash is just a value,
+          like a string or a number is.</para>
+        </section>
+      </section>
+
+      <section xml:id="dgui_datamodel_types">
+        <title>The types</title>
+
+        <para>The suppored types are:</para>
+
+        <itemizedlist spacing="compact">
+          <listitem>
+            <para><link linkend="dgui_datamodel_scalar"
+            os="">Scalars:</link></para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para>String</para>
+              </listitem>
+
+              <listitem>
+                <para>Number</para>
+              </listitem>
+
+              <listitem>
+                <para>Boolean</para>
+              </listitem>
+
+              <listitem>
+                <para>Date-like (date, time, or date-time)</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para><link
+            linkend="dgui_datamodel_container">Containers:</link></para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para>Hash</para>
+              </listitem>
+
+              <listitem>
+                <para>Sequence</para>
+              </listitem>
+
+              <listitem>
+                <para>Collection</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Subroutines:</para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para><link linkend="dgui_datamodel_method">Methods and
+                functions</link></para>
+              </listitem>
+
+              <listitem>
+                <para><link linkend="dgui_datamodel_userdefdir">User-defined
+                directives</link></para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Miscellaneous/seldom used:</para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para><link linkend="dgui_datamodel_node">Node</link></para>
+              </listitem>
+
+              <listitem>
+                <para><link linkend="dgui_datamodel_markupoutput">Markup
+                output</link></para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="dgui_datamodel_scalar">
+          <title>Scalars</title>
+
+          <anchor xml:id="topic.designer.scalarVariable"/>
+
+          <para>These are the basic, simple kind of values. They can
+          be:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><indexterm>
+                  <primary>string</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>String: It is simple text, e.g., the name of a
+              product.</para>
+
+              <para>If you want to give a string value directly in the
+              template, rather than use a variable that comes from the data
+              model, you write the text between quotation marks, e.g.,
+              <literal>"green mouse"</literal> or <literal>'green
+              mouse'</literal>. (More details regarding the syntax can be
+              found <link linkend="dgui_template_exp_direct_string"
+              xml:lang="">later</link>.)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>number</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Number: For example the price of a product.
+              <phrase role="forProgrammers">Whole numbers and non-whole
+              numbers are not distinguished; there is only a single number
+              type. So for example 3/2 will be always 1.5, and never 1. Just
+              like if you are using a calculator.</phrase></para>
+
+              <para>If you want to give a numerical value directly in the
+              template, then you write for example: <literal>150</literal> or
+              <literal>-90.05</literal> or <literal>0.001</literal>. (More
+              details regarding the syntax can be found <link
+              linkend="dgui_template_exp_direct_number"
+              xml:lang="">later</link>.)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>boolean</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Boolean: A boolean value represents a logical true
+              or false (yes or no). For example, if a the visitor has been
+              logged in or not. Typically you use booleans as the condition of
+              the <literal>if</literal> directive, like <literal>&lt;#if
+              loggedIn
+              &gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal> or
+              <literal>&lt;#if price ==
+              0&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>; in
+              the last case the result of the <literal>price == 0</literal>
+              part is a boolean value.</para>
+
+              <para>In the templates you can directly specify a boolean with
+              the reserved words <literal>true</literal> and
+              <literal>false</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>date</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm><indexterm>
+                  <primary>time</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm><indexterm>
+                  <primary>date-time</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Date: A date-like value stores date/time related
+              data. It has three variations:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para>Date: Like April 4, 2003. Day precision, no time of
+                  day part.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Time: Like 10:19:18 PM. Millisecond precision, no date
+                  part.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Date-time (sometimes called "time stamp") as April 4,
+                  2003 10:19:18 PM. Both date and time, with millisecond
+                  precision.</para>
+                </listitem>
+              </itemizedlist>
+
+              <para>Unfortunately, because of the limitations of the Java
+              platform, FreeMarker sometimes can't decide which parts of the
+              date are in use (i.e., if it is date-time, a date or a time).
+              The solution for this problem is an advanced topic that will be
+              discussed <link
+              linkend="ref_builtin_date_datetype">later</link>.</para>
+
+              <para>It is possible to define date-like values directly in
+              templates, but this is an advanced topic that will be explained
+              <link linkend="ref_builtin_string_date">later</link>.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Bear in mind that FreeMarker distinguishes strings from
+          numbers, booleans and date-like values. For example, while the
+          string <literal>"150"</literal> looks like the number
+          <literal>150</literal>, a string is still just arbitrary sequence of
+          characters, and you can't do arithmetic with it, can't compare it
+          with another number, etc.</para>
+        </section>
+
+        <section xml:id="dgui_datamodel_container">
+          <title>Containers</title>
+
+          <remark>Re-explanation of hashes and sequences from a more
+          ''professional'' viewpoint as earlier, and some meditation about
+          them.</remark>
+
+          <para>These are the values whose purpose is to contain other
+          variables; they are just containers. The contained variables are
+          often referred as <emphasis>sub variables</emphasis>. The container
+          types are:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><indexterm>
+                  <primary>hash</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Hash: Associates a unique lookup name with each of
+              its sub variables. The name is an unrestricted string. A hash
+              <emphasis>doesn't define an ordering</emphasis> for the sub
+              variables in it. That is, there is no such thing as the first
+              subvariable, and the second subvariable, etc.; the variables are
+              just accessed by name.</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>sequence</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Sequence: Associates an integer number with each
+              of its sub variables. The first subvariable is associated with
+              0, the second with 1, the third to 2, and so on; the sub
+              variables are ordered. These numbers are often called the
+              <emphasis>indexes</emphasis> of the sub variables. Sequences are
+              usually dense, i.e., all indexes up to the index of the last
+              subvariable have an associated subvariable, but it's not
+              strictly necessary. The type of the subvariable values need not
+              be the same.</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>collection</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Collection: A collection, from the viewpoint of
+              the template author, is a restricted sequence. You cannot access
+              its size or retrieve its sub variables by index, but they can be
+              still listed with the <link
+              linkend="ref.directive.list"><literal>list</literal>
+              directive</link>. Furthermore, very often they can only be
+              listed once. (If you are a Java programmer,
+              <quote>iterable</quote> would be a more fitting name than
+              collection.)</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Note that since <link linkend="topic.multitype">a value can
+          have multiple types</link>, it is possible for a value to be both a
+          hash and a sequence, in which case it would support index-based
+          access as well as access by lookup name. However, typically a
+          container will be either a hash or a sequence, not both.</para>
+
+          <para>As the value of the variables stored in hashes and sequences
+          (and collections) can be anything, it can be a hash or sequence (or
+          collection) as well. This way you can build arbitrarily deep
+          structures.</para>
+
+          <para>The data-model itself (or better said the root of it) is a
+          hash.</para>
+
+          <para>FreeMarker templates don't support modifying the contents of
+          containers (such as adding, removing or replacing sub variables),
+          and it assumes that their content won't change during template
+          processing. (But you can make new container values by adding
+          together two existing container values with <literal>+</literal>;
+          see that in the <link linkend="exp_cheatsheet">chapter about
+          expressions</link>, and please note the performance
+          consequences.)</para>
+        </section>
+
+        <section>
+          <title>Subroutines</title>
+
+          <section xml:id="dgui_datamodel_method">
+            <title>Methods and functions</title>
+
+            <anchor xml:id="topic.designer.methodVariable"/>
+
+            <indexterm>
+              <primary>method</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>A value that is a method or a function is used to calculate
+            another value, influenced by the parameters you give to it.</para>
+
+            <para><phrase role="forProgrammers">For programmer types:
+            Methods/functions are first-class values, just like in functional
+            programming languages. This means that functions/methods can be
+            the parameters or return values of other functions/methods, you
+            can assign them to variables, and so on.</phrase></para>
+
+            <para>Suppose that programmers have put the method variable
+            <literal>avg</literal> in the data-model that can be used to
+            calculate the average of numbers. If you give the 3 and 5 as
+            parameters when you access <literal>avg</literal>, then you get
+            the value 4.</para>
+
+            <para>The usage of methods will be explained <link
+            linkend="dgui_template_exp_methodcall">later</link>, but perhaps
+            this example helps to understand what methods are:</para>
+
+            <programlisting role="template">The average of 3 and 5 is: ${avg(3, 5)}
+The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
+The average of the price of a python and an elephant is:
+${avg(animals.python.price, animals.elephant.price)}</programlisting>
+
+            <para>this will output:</para>
+
+            <programlisting role="output">The average of 3 and 5 is: 4
+The average of 6 and 10 and 20 is: 12
+The average of the price of a python and an elephant is:
+4999.5</programlisting>
+
+            <para>What is the difference between a method and a function? As
+            far as the template author is concerned, nothing. Well not really
+            nothing, as methods typically come from the data-model (<phrase
+            role="forProgrammers">as they reflect the methods of Java
+            objects</phrase>), and functions are defined in templates (with
+            the <link
+            linkend="ref.directive.function"><literal>function</literal>
+            directive</link> -- an advanced topic), but both can be used on
+            the same way.</para>
+          </section>
+
+          <section xml:id="dgui_datamodel_userdefdir">
+            <title>User-defined directives</title>
+
+            <indexterm>
+              <primary>macro</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>directive</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>user-defined directive</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>A value of this type can be used as user-defined directive
+            (with other words, as FreeMarker tag). An user-defined directive
+            is a subroutine, something like a little reusable template
+            fragment. But this is an advanced topic that will be explained
+            <link linkend="dgui_misc_userdefdir">later</link> in its own
+            chapter.</para>
+
+            <para><phrase role="forProgrammers">For programmer types:
+            user-defined directives (such as macros), are first-class values
+            too, just like functions/methods are.</phrase></para>
+
+            <para>Just to get an idea about user-defined directives (so just
+            ignore this if you won't understand), assume we have a variable,
+            <literal>box</literal>, whose value is a user-defined directive
+            that prints some kind of fancy HTML message box with a title bar
+            and a message in it. The <literal>box</literal> variable could be
+            used in the template like this (for example):</para>
+
+            <programlisting role="template">&lt;@<emphasis>box</emphasis> title="Attention!"&gt;
+  Too much copy-pasting may leads to
+  maintenance headaches.
+&lt;/@<emphasis>box</emphasis>&gt;</programlisting>
+          </section>
+
+          <section>
+            <title>Function/method versus user-defined directive</title>
+
+            <para>This is for advanced users again (so ignore it if you don't
+            understand). It's a frequent dilemma if you should use a
+            function/method or an user-defined directive to implement
+            something. The rule of thumb is: Implement the facility as
+            user-defined directive instead of as function/method if:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>... the purpose of it is generating a piece of the
+                output that's not just a single value, and typically involves
+                markup. The template language was designed for printing to the
+                output directly, piece by piece, as it goes though
+                <literal>list</literal> loops, <literal>if</literal>-s, etc.
+                Building up a string value in a variable then returning it is
+                much less convenient.</para>
+              </listitem>
+
+              <listitem>
+                <para>... it's the side-effect that is important and not the
+                return value. For example, a directive whose purpose is to add
+                an entry to the server log is like that. (In fact you can't
+                have a return value for a user-defined directive, but some
+                kind of feedback is still possible by setting non-local
+                variables.)</para>
+              </listitem>
+
+              <listitem>
+                <para>... it will do flow control on the caller side (like for
+                example <literal>list</literal> or <literal>if</literal>
+                directives do). You just can't do that with a
+                function/method.</para>
+              </listitem>
+
+              <listitem>
+                <para>... you are using legacy escaping via the
+                <literal>escape</literal> directive (instead of <link
+                linkend="dgui_misc_autoescaping">auto-escaping</link>), and
+                the result contains markup. When you print the result with
+                <literal>${<replaceable>...</replaceable>}</literal>, the
+                markup will be escaped and thus ruined, but if it's printed by
+                a directive call
+                (<literal>&lt;@<replaceable>...</replaceable>&gt;</literal>),
+                it won't be.</para>
+              </listitem>
+            </itemizedlist>
+
+            <para>The Java methods of FreeMarker-unaware Java objects are
+            normally visible as methods in templates, regardless of the nature
+            of the Java method; you have no choice there.</para>
+          </section>
+        </section>
+
+        <section>
+          <title>Miscellaneous</title>
+
+          <section xml:id="dgui_datamodel_node">
+            <title>Nodes</title>
+
+            <indexterm>
+              <primary>node</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>Node variables represent a node in a tree structure, and are
+            used mostly with <link linkend="xgui">XML processing</link>, which
+            is an advanced, and specialized topic.</para>
+
+            <para>Still, a quick overview <emphasis>for advanced
+            users</emphasis>: A node is similar to a sequence that stores
+            other nodes, which are often referred as the children nodes. A
+            node stores a reference to its container node, which is often
+            referred as the parent node. The main point of being a node is the
+            topological information; other data must be stored by utilizing
+            that a value can have multiple types. Like, a value may be both a
+            node and a number, in which case it can store a number as the
+            "pay-load". Apart from the topological information, a node can
+            store some metainformation as well: a node name, a node type
+            (string), and a node namespace (string). For example, if the node
+            symbolizes a <literal>h1</literal> element in an XHTML document,
+            then its name could be <literal>"h1"</literal>, it's node type
+            could be <literal>"element"</literal>, and it's namespace could be
+            <literal>"http://www.w3.org/1999/xhtml"</literal>. But it's up to
+            the designer of the data-model if what meaning these
+            metainformations have, and if they are used at all. The way of
+            retrieving the topological and metainformations is described <link
+            linkend="ref_builtins_node">in a later chapter</link> (that you
+            don't have to understand at this point).</para>
+          </section>
+
+          <section xml:id="dgui_datamodel_markupoutput">
+            <title>Markup output</title>
+
+            <indexterm>
+              <primary>markup output</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>This type is related to <link
+            linkend="dgui_misc_autoescaping">auto-escaping mechanism</link>
+            introduced FreeMarker 2.3.24; you can <link
+            linkend="dgui_misc_autoescaping_movalues">read about this type
+            there</link>. But in short, this is a value that stores text
+            that's already in the output markup format (like HTML, XML, RTF,
+            etc.), and hence must not be auto-escaped.</para>
+
+            <para>Values of this type are usually produced inside the
+            templates (like with <link
+            linkend="ref_builtin_no_esc"><literal>no_esc</literal>
+            built-in</link> or <link linkend="ref_directive_assign">output
+            capturing assignments</link>), but can also be part of the
+            data-model. Such values in the data-model are useful for example
+            if you have message resources that sometimes contain the message
+            in HTML format, rather than in plain text. If the data-model uses
+            HTML markup output values for those messages instead of strings,
+            then the template author need not know which messages contain HTML
+            and which plain text, as double escaping will be avoided
+            automatically when the message is inserted with
+            <literal>${<replaceable>...</replaceable>}</literal>.</para>
+          </section>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_template">
+      <title>The Template</title>
+
+      <indexterm>
+        <primary>template</primary>
+      </indexterm>
+
+      <note>
+        <para>It is assumed that you have already read the <xref
+        linkend="dgui_quickstart"/> and the <xref linkend="dgui_datamodel"/>
+        chapter.</para>
+      </note>
+
+      <section xml:id="dgui_template_overallstructure">
+        <title>Overall structure</title>
+
+        <para>Templates are in fact programs you write in a language called
+        <indexterm>
+            <primary>FTL</primary>
+          </indexterm><emphasis role="term">FTL</emphasis> (for FreeMarker
+        Template Language). This is a quite simple programming language
+        designed for writing templates and nothing else.</para>
+
+        <para>A template (= FTL program) is a mix of the following
+        sections:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><emphasis role="term">Text</emphasis><indexterm>
+                <primary>text</primary>
+              </indexterm>: Text that will be printed to the output as
+            is.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Interpolation</emphasis><indexterm>
+                <primary>interpolation</primary>
+              </indexterm>: These sections will be replaced with a calculated
+            value in the output. Interpolations are delimited by
+            <literal>${</literal> and <literal>}</literal> (or with
+            <literal>#{</literal> and <literal>}</literal>, but that shouldn't
+            be used anymore; <link
+            linkend="ref_depr_numerical_interpolation">see more
+            here</link>).</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">FTL tags</emphasis><indexterm>
+                <primary>FTL tag</primary>
+              </indexterm>: FTL tags are a bit similar to HTML tags, but they
+            are instructions to FreeMarker and will not be printed to the
+            output.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Comments</emphasis><indexterm>
+                <primary>comment</primary>
+              </indexterm><indexterm>
+                <primary>&lt;#--...--&gt;</primary>
+              </indexterm><indexterm>
+                <primary>#</primary>
+              </indexterm>: Comments are similar to HTML comments, but they
+            are delimited by <literal>&lt;#--</literal> and
+            <literal>--&gt;</literal>. Comments will be ignored by FreeMarker,
+            and will not be written to the output.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Let's see a concrete template. I have marked the template's
+        components with colors: <phrase role="markedText">text</phrase>,
+        <phrase role="markedInterpolation">interpolation</phrase>, <phrase
+        role="markedFTLTag">FTL tag</phrase>, <phrase
+        role="markedComment">comment</phrase>. With the <phrase
+        role="markedInvisibleText">[BR]</phrase>-s I intend to visualize the
+        <link linkend="gloss.lineBreak">line breaks</link>.</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;html&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;title&gt;Welcome!&lt;/title&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedComment">&lt;#-- Greet the user with his/her name --&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;h1&gt;Welcome <phrase role="markedInterpolation">${user}</phrase>!&lt;/h1&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;#list animals as animal&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+    &lt;li&gt;<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/html&gt;</phrase></programlisting>
+
+        <para>FTL distinguishes upper case and lower case letters. So
+        <literal>list</literal> is good directive name, while
+        <literal>List</literal> is not. Similarly <literal>${name}</literal>
+        is not the same as <literal>${Name}</literal> or
+        <literal>${NAME}</literal></para>
+
+        <para>It is important to realize that <phrase
+        role="markedInterpolation">interpolations</phrase> can be used in
+        <phrase role="markedText">text</phrase> (and in string literal
+        expressions; see <link
+        linkend="dgui_template_exp_stringop_interpolation">later</link>)
+        only.</para>
+
+        <para>An <phrase role="markedFTLTag">FTL tag</phrase> can't be inside
+        another <phrase role="markedFTLTag">FTL tag</phrase> nor inside an
+        <phrase role="markedInterpolation">interpolation</phrase>. For example
+        this is <emphasis>WRONG</emphasis>: <literal>&lt;#if &lt;#include
+        'foo'&gt;='bar'&gt;...&lt;/#if&gt;</literal></para>
+
+        <para><phrase role="markedComment">Comments</phrase> can be placed
+        inside <phrase role="markedFTLTag">FTL tags</phrase> and <phrase
+        role="markedInterpolation">interpolations</phrase>. For
+        example:</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;h1&gt;Welcome <phrase
+              role="markedInterpolation">${user <phrase role="markedComment">&lt;#-- The name of user --&gt;</phrase>}</phrase>!&lt;/h1&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;#list <phrase role="markedComment">&lt;#-- some comment... --&gt;</phrase> animals as <phrase
+                role="markedComment">&lt;#-- again... --&gt;</phrase> animal&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase></phrase>
+<replaceable>...</replaceable></programlisting>
+
+        <note>
+          <para>For those of you who have tried the above examples: You may
+          notice that some of spaces, tabs and line breaks are missing from
+          the template output, even though we said that <phrase
+          role="markedText">text</phrase> is printed as is. Don't bother with
+          it now. This is because the feature called ''white-space stripping''
+          is turned on, and that automatically removes some superfluous
+          spaces, tabs and line breaks. This will be explained <link
+          linkend="dgui_misc_whitespace">later</link>.</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_template_directives">
+        <title>Directives</title>
+
+        <indexterm>
+          <primary>&lt;#...&gt;</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>#</primary>
+        </indexterm>
+
+        <anchor xml:id="term.designer.directive"/>
+
+        <remark>Note that the Expressions chapter depends on this chapter, and
+        Interpolations chapter depends on Expressions chapter. Thus Directives
+        must be the first chapter after Basics.</remark>
+
+        <para><indexterm>
+            <primary>directive</primary>
+          </indexterm>You use FTL tags to call <emphasis
+        role="term">directives</emphasis>. In the example you have called the
+        <literal>list</literal> directive. Syntactically you have done it with
+        two tags: <literal>&lt;#list animals as animal&gt;</literal> and
+        <literal>&lt;/#list&gt;</literal>.</para>
+
+        <para><indexterm>
+            <primary>FTL tag</primary>
+          </indexterm>There are two kind of FTL tags:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>Start-tag:
+            <literal>&lt;#<replaceable>directivename</replaceable>
+            <replaceable>parameters</replaceable>&gt;</literal></para>
+          </listitem>
+
+          <listitem>
+            <para>End-tag:
+            <literal>&lt;/#<replaceable>directivename</replaceable>&gt;</literal></para>
+          </listitem>
+        </itemizedlist>
+
+        <para>This is similar to HTML or XML syntax, except that the tag name
+        starts with <literal>#</literal>. If the directive doesn't have nested
+        content (content between the start-tag and the end-tag), you must use
+        the start-tag with no end-tag. For example you write <literal>&lt;#if
+        <replaceable>something</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>,
+        but just <literal>&lt;#include
+        <replaceable>something</replaceable>&gt;</literal> as FreeMarker knows
+        that the <literal>include</literal> directive can't have nested
+        content.</para>
+
+        <para>The format of the
+        <literal><replaceable>parameters</replaceable></literal> depends on
+        the
+        <literal><replaceable>directivename</replaceable></literal>.</para>
+
+        <para>In fact there are two types of directives: <link
+        linkend="gloss.predefinedDirective">predefined directives</link> and
+        <link linkend="gloss.userDefinedDirective">user-defined
+        directives</link>. For user-defined directives you use
+        <literal>@</literal> instead of <literal>#</literal>, for example
+        <literal>&lt;@mydirective
+        <replaceable>parameters</replaceable>&gt;<replaceable>...</replaceable>&lt;/@mydirective&gt;</literal>.
+        Further difference is that if the directive has no nested content, you
+        must use a tag like <literal>&lt;@mydirective
+        <replaceable>parameters</replaceable> /&gt;</literal>, similarly as in
+        XML (e.g. <literal>&lt;img <replaceable>...</replaceable>
+        /&gt;</literal>). But user-defined directives is an advanced topic
+        that will be discussed <link
+        linkend="dgui_misc_userdefdir">later</link>.</para>
+
+        <para>FTL tags, like HTML tags, must be properly nested. So the code
+        below is wrong, as the <literal>if</literal> directive is both inside
+        and outside of the nested content of the <literal>list</literal>
+        directive:</para>
+
+        <programlisting role="template">&lt;ul&gt;
+<emphasis>&lt;#list animals as animal&gt;</emphasis>
+  &lt;li&gt;${animal.name} for ${animal.price} Euros
+  <emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>
+     (except for you)
+<emphasis>&lt;/#list&gt;</emphasis> &lt;#-- WRONG! The "if" has to be closed first. --&gt;
+<emphasis>&lt;/#if&gt;</emphasis>
+&lt;/ul&gt;</programlisting>
+
+        <para>Note that FreeMarker doesn't care about the nesting of HTML
+        tags, only about the nesting of FTL tags. It just sees HTML as flat
+        text, it doesn't interpret it in any way.</para>
+
+        <para>If you try to use a non-existing directive (e.g., you mistype
+        the directive name), FreeMarker will decline to use the template and
+        produce an error message.</para>
+
+        <para>FreeMarker ignores superfluous <link
+        linkend="gloss.whiteSpace">white-space</link> inside FTL tags. So you
+        can write this:</para>
+
+        <programlisting role="template"><phrase role="markedText"><phrase
+              role="markedFTLTag">&lt;#list<phrase role="markedInvisibleText">[BR]</phrase>
+  animals       as<phrase role="markedInvisibleText">[BR]</phrase>
+     animal<phrase role="markedInvisibleText">[BR]</phrase>
+&gt;</phrase><phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;/#list    &gt;</phrase></phrase></programlisting>
+
+        <para>You may not, however, insert white-space between the
+        <literal>&lt;</literal> or <literal>&lt;/</literal> and the directive
+        name.</para>
+
+        <para>The complete list and description of all directives can be found
+        in the <xref linkend="ref_directives"/> (but I recommend that you look
+        at the chapter about expressions first).</para>
+
+        <note>
+          <para>FreeMarker can be configured to use <literal>[</literal> and
+          <literal>]</literal> instead of <literal>&lt;</literal> and
+          <literal>&gt;</literal> in the FTL tags and FTL comments, like
+          <literal>[#if user == "Big
+          Joe"]<replaceable>...</replaceable>[/#if]</literal>. For more
+          information read: <xref
+          linkend="dgui_misc_alternativesyntax"/>.</para>
+        </note>
+
+        <note>
+          <para>FreeMarker can be configured so that it understands predefined
+          directives without <literal>#</literal> (like <literal>&lt;if user
+          == "Big
+          Joe"&gt;<replaceable>...</replaceable>&lt;/if&gt;</literal>).
+          However we don't recommend the usage of this mode. For more
+          information read: <xref linkend="ref_depr_oldsyntax"/></para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_template_exp">
+        <title>Expressions</title>
+
+        <para><indexterm>
+            <primary>expression</primary>
+          </indexterm>When you supply values for interpolations or directive
+        parameters you can use variables or more complex expressions. For
+        example, if x is the number 8 and y is 5, the value of <literal>(x +
+        y)/2</literal> resolves to the numerical value 6.5.</para>
+
+        <para>Before we go into details, let's see some concrete
+        examples:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>When you supply value for interpolations: The usage of
+            interpolations is
+            <literal>${<replaceable>expression</replaceable>}</literal> where
+            expression gives the value you want to insert into the output as
+            text. So <literal>${(5 + 8)/2}</literal> prints <quote>6.5</quote>
+            to the output (or possibly <quote>6,5</quote> if the language of
+            your output is not US English).</para>
+          </listitem>
+
+          <listitem>
+            <para>When you supply a value for the directive parameter: You
+            have already seen the <literal>if</literal> directive in the
+            Getting Started section. The syntax of this directive is:
+            <literal>&lt;#if
+            <replaceable>expression</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>.
+            The expression here must evaluate to a boolean value. For example
+            in <literal>&lt;#if 2 &lt; 3&gt;</literal> the <literal>2 &lt;
+            3</literal> (2 is less than 3) is an expression which evaluates to
+            <literal>true</literal>.</para>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="exp_cheatsheet">
+          <title>Quick overview (cheat sheet)</title>
+
+          <para>This is a reminder for those of you who already know
+          FreeMarker or are just experienced programmers:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para><link linkend="dgui_template_exp_direct">Specify values
+              directly</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_string">Strings</link>:
+                  <literal>"Foo"</literal> or <literal>'Foo'</literal> or
+                  <literal>"It's \"quoted\""</literal> or <literal>'It\'s
+                  "quoted"'</literal> or
+                  <literal>r"C:\raw\string"</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_number">Numbers</link>:
+                  <literal>123.45</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_boolean">Booleans</link>:
+                  <literal>true</literal>, <literal>false</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_seuqence">Sequences</link>:
+                  <literal>["foo", "bar", 123.45]</literal>; Ranges:
+                  <literal>0..9</literal>, <literal>0..&lt;10</literal> (or
+                  <literal>0..!10</literal>), <literal>0..</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_hash">Hashes</link>:
+                  <literal>{"name":"green mouse",
+                  "price":150}</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_var">Retrieving
+              variables</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_var_toplevel">Top-level
+                  variables</link>: <literal>user</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link linkend="dgui_template_exp_var_hash">Retrieving
+                  data from a hash</link>: <literal>user.name</literal>,
+                  <literal>user["name"]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_var_sequence">Retrieving data
+                  from a sequence</link>:
+                  <literal>products[5]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link linkend="dgui_template_exp_var_special">Special
+                  variable</link>: <literal>.main</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_stringop">String
+              operations</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_stringop_interpolation">Interpolation
+                  and concatenation</link>:
+                  <literal>"Hello ${user}!"</literal> (or <literal>"Hello
+                  " + user + "!"</literal>)</para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_get_character">Getting a
+                  character</link>: <literal>name[0]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_stringop_slice">String
+                  slice:</link> Inclusive end: <literal>name[0..4]</literal>,
+                  Exclusive end: <literal>name[0..&lt;5]</literal>,
+                  Length-based (lenient): <literal>name[0..*5]</literal>,
+                  Remove starting: <literal>name[5..]</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_sequenceop">Sequence
+              operations</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_sequenceop_cat">Concatenation</link>:
+                  <literal>users + ["guest"]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_seqenceop_slice">Sequence
+                  slice</link>: Inclusive end:
+                  <literal>products[20..29]</literal>, Exclusive end:
+                  <literal>products[20..&lt;30]</literal>, Length-based
+                  (lenient): <literal>products[20..*10]</literal>, Remove
+                  starting: <literal>products[20..]</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_hashop">Hash
+              operations</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_hashop_cat">Concatenation</link>:
+                  <literal>passwords + { "joe": "secret42" }</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_arit">Arithmetical
+              calculations</link>: <literal>(x * 1.5 + 10) / 2 - y %
+              100</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link
+              linkend="dgui_template_exp_comparison">Comparison</link>:
+              <literal>x == y</literal>, <literal>x != y</literal>,
+              <literal>x &lt; y</literal>, <literal>x &gt; y</literal>,
+              <literal>x &gt;= y</literal>, <literal>x &lt;= y</literal>,
+              <literal>x lt y</literal>, <literal>x lte y</literal>,
+              <literal>x gt y</literal>, <literal>x gte y</literal>,
+              ...etc.</para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_logicalop">Logical
+              operations</link>: <literal>!registered &amp;&amp; (firstVisit
+              || fromEurope)</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link
+              linkend="dgui_template_exp_builtin">Built-ins</link>:
+              <literal>name?upper_case</literal>,
+              <literal>path?ensure_starts_with('/')</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_methodcall">Method
+              call</link>: <literal>repeat("What", 3)</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_missing">Missing value
+              handler operators</link>:</para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_missing_default">Default
+                  value</link>: <literal>name!"unknown"</literal> or
+                  <literal>(user.name)!"unknown"</literal> or
+                  <literal>name!</literal> or
+                  <literal>(user.name)!</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link linkend="dgui_template_exp_missing_test">Missing
+                  value test</link>: <literal>name??</literal> or
+                  <literal>(user.name)??</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_assignment">Assignment
+              operators</link>: <literal>=</literal>, <literal>+=</literal>,
+              <literal>-=</literal>, <literal>*=</literal>,
+              <literal>/=</literal>, <literal>%=</literal>,
+              <literal>++</literal>, <literal>--</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_lambda">Local
+              lambdas</link>: <literal>x -&gt; x + 1</literal>, <literal>(x,
+              y) -&gt; x + y</literal></para>
+            </listitem>
+          </itemizedlist>
+
+          <para>See also: <link
+          linkend="dgui_template_exp_precedence">Operator
+          precedence</link></para>
+        </section>
+
+        <section xml:id="dgui_template_exp_direct">
+          <title>Specify values directly</title>
+
+          <indexterm>
+            <primary>literal</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>constant</primary>
+          </indexterm>
+
+          <para>Often you want to specify a value directly and not as a result
+          of some calculations.</para>
+
+          <section xml:id="dgui_template_exp_direct_string">
+            <title>Strings</title>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <para>To specify a string value directly you give the text in
+            quotation marks, e.g.: <literal>"some text"</literal> or in
+            apostrophe-quote, e.g. <literal>'some text'</literal>. The two
+            forms are equivalent. If the text itself contains the character
+            used for the quoting (either <literal>"</literal> or
+            <literal>'</literal>) or backslashes, you have to precede them
+            with a backslash; this is called escaping. You can type any other
+            character, including <link linkend="gloss.lineBreak">line
+            breaks</link>, in the text directly. Example:</para>
+
+            <programlisting role="template">${"It's \"quoted\" and
+this is a backslash: \\"}
+
+${'It\'s "quoted" and
+this is a backslash: \\'}</programlisting>
+
+            <para>will print:</para>
+
+            <programlisting role="output">It's "quoted" and
+this is a backslash: \
+
+It's "quoted" and
+this is a backslash: \</programlisting>
+
+            <note>
+              <para>Of course, you could simply type the above text into the
+              template, without using
+              <literal>${<replaceable>...</replaceable>}</literal>. But we do
+              it here just for the sake of example, to demonstrate
+              expressions.</para>
+            </note>
+
+            <anchor xml:id="topic.escapeSequence"/>
+
+            <indexterm>
+              <primary>escape sequences</primary>
+            </indexterm>
+
+            <para>This is the list of all supported escape sequences. All
+            other usage of backlash in string literals is an error and any
+            attempt to use the template will fail.</para>
+
+            <informaltable border="1">
+              <thead>
+                <tr>
+                  <th>Escape sequence</th>
+
+                  <th>Meaning</th>
+                </tr>
+              </thead>
+
+              <tbody>
+                <tr>
+                  <td><literal>\"</literal></td>
+
+                  <td>Quotation mark (u0022)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\'</literal></td>
+
+                  <td>Apostrophe (a.k.a. apostrophe-quote) (u0027)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\{</literal></td>
+
+                  <td>Opening curly brace: <literal>{</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\=</literal></td>
+
+                  <td>Equals character: <literal>=</literal> (Supported since
+                  FreeMarker 2.3.28.)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\\</literal></td>
+
+                  <td>Back slash (u005C)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\n</literal></td>
+
+                  <td>Line feed (u000A)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\r</literal></td>
+
+                  <td>Carriage return (u000D)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\t</literal></td>
+
+                  <td>Horizontal tabulation (a.k.a. tab) (u0009)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\b</literal></td>
+
+                  <td>Backspace (u0008)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\f</literal></td>
+
+                  <td>Form feed (u000C)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\l</literal></td>
+
+                  <td>Less-than sign: <literal>&lt;</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\g</literal></td>
+
+                  <td>Greater-than sign: <literal>&gt;</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\a</literal></td>
+
+                  <td>Ampersand: <literal>&amp;</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\x<replaceable>Code</replaceable></literal></td>
+
+                  <td>Character given with its hexadecimal <link
+                  linkend="gloss.unicode">Unicode</link> code (<link
+                  linkend="gloss.UCS">UCS</link> code)</td>
+                </tr>
+              </tbody>
+            </informaltable>
+
+            <para>The <literal><replaceable>Code</replaceable></literal> after
+            the <literal>\x</literal> is 1 to 4 hexadecimal digits. For
+            example this all put a copyright sign into the string:
+            <literal>"\xA9 1999-2001"</literal>,
+            <literal>"\x0A9 1999-2001"</literal>,
+            <literal>"\x00A9 1999-2001"</literal>. When the character directly
+            after the last hexadecimal digit can be interpreted as hexadecimal
+            digit, you must use all 4 digits or else FreeMarker will
+            misunderstand you.</para>
+
+            <para>Note that the character sequence <literal>${</literal> and
+            <literal>#{</literal> (and rarely <literal>[=</literal> instead,
+            depending on <link linkend="dgui_misc_alternativesyntax">the
+            configured syntax</link>) has special meaning. They are used to
+            insert the value of expressions (typically: the value of
+            variables, as in <literal>"Hello ${user}!"</literal>). This will
+            be explained <link
+            linkend="dgui_template_exp_stringop_interpolation">later</link>.
+            If you want to print <literal>${</literal> or
+            <literal>#{</literal> (or <literal>[=</literal>), you should
+            either use raw string literals as explained below, or escape the
+            <literal>{</literal> like in <literal>"foo $\{bar}"</literal> (or
+            the <literal>=</literal> like in <literal>"foo
+            [\=bar]"</literal>).</para>
+
+            <indexterm>
+              <primary>raw string literal</primary>
+            </indexterm>
+
+            <para>A special kind of string literals is the raw string
+            literals. In raw string literals, backslash and
+            <literal>${</literal> have no special meaning, they are considered
+            as plain characters. To indicate that a string literal is a raw
+            string literal, you have to put an <literal>r</literal> directly
+            before the opening quotation mark or apostrophe-quote.
+            Example:</para>
+
+            <programlisting role="template">${r"${foo}"}
+${r"C:\foo\bar"}</programlisting>
+
+            <para>will print:</para>
+
+            <programlisting role="output">${foo}
+C:\foo\bar</programlisting>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_number">
+            <title>Numbers</title>
+
+            <indexterm>
+              <primary>number</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <para>To specify a numerical value directly you type the number
+            without quotation marks. You have to use the dot as your decimal
+            separator and must not use any grouping separator symbols. You can
+            use <literal>-</literal> or <literal>+</literal> to indicate the
+            sign (<literal>+</literal> is redundant). Scientific notation is
+            not yet supported (so <literal>1E3</literal> is wrong). Also, you
+            cannot omit the 0 before the decimal separator (so
+            <literal>.5</literal> is wrong).</para>
+
+            <para>Examples of valid number literals: <literal>0.08</literal>,
+            <literal>-5.013</literal>, <literal>8</literal>,
+            <literal>008</literal>, <literal>11</literal>,
+            <literal>+11</literal></para>
+
+            <para>Note that numerical literals like <literal>08</literal>,
+            <literal>+8</literal>, <literal>8.00</literal> and
+            <literal>8</literal> are totally equivalent as they all symbolize
+            the number eight. Thus, <literal>${08}</literal>,
+            <literal>${+8}</literal>, <literal>${8.00}</literal> and
+            <literal>${8}</literal> will all print exactly same.</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_boolean">
+            <title>Booleans</title>
+
+            <indexterm>
+              <primary>boolean</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>literal</primary>
+
+              <secondary>boolean</secondary>
+            </indexterm>
+
+            <para>To specify a boolean value you write <literal>true</literal>
+            or <literal>false</literal>. Don't use quotation marks.</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_seuqence">
+            <title>Sequences</title>
+
+            <indexterm>
+              <primary>sequence</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>numerical sequence</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>numerical range expression</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>range expression</primary>
+            </indexterm>
+
+            <para>To specify a literal sequence, you list the <link
+            linkend="topic.dataModel.subVar">sub variables</link> separated by
+            commas, and put the whole list into square brackets. For
+            example:</para>
+
+            <programlisting role="template">&lt;#list <emphasis>["foo", "bar", "baz"]</emphasis> as x&gt;
+${x}
+&lt;/#list&gt;</programlisting>
+
+            <para>will print:</para>
+
+            <programlisting role="output">foo
+bar
+baz
+ </programlisting>
+
+            <para>The items in the list are expressions, so you can do this
+            for example: <literal>[2 + 2, [1, 2, 3, 4], "foo"]</literal>. Here
+            the first subvariable will be the number 4, the second will be
+            another sequence, and the third subvariable will be the string
+            <quote>foo</quote>.</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_ranges">
+            <title>Ranges</title>
+
+            <para>Ranges are just sequences, but they are created by
+            specifying what range of whole numbers they contain, instead of
+            specifying their items one by one. For example,
+            <literal>0..&lt;m</literal>, assuming the <literal>m</literal>
+            variable stores 5, will give a sequence that contains <literal>[0,
+            1, 2, 3, 4]</literal>. Ranges are primarily used for iterating
+            over a range of numbers with <literal>&lt;#list
+            <replaceable>...</replaceable>&gt;</literal> and for <link
+            linkend="dgui_template_exp_seqenceop_slice">slicing
+            sequences</link> and <link
+            linkend="dgui_template_exp_stringop_slice">slicing
+            strings</link>.</para>
+
+            <para>The generic forms of range expressions are (where
+            <literal><replaceable>start</replaceable></literal> and
+            <literal><replaceable>end</replaceable></literal> can be any
+            expression that evaluates to a number):</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..<replaceable>end</replaceable></literal>:
+                Range with inclusive end. For example, <literal>1..4</literal>
+                gives <literal>[1, 2, 3, 4]</literal>, and
+                <literal>4..1</literal> gives <literal>[4, 3, 2, 1]</literal>.
+                Beware, ranges with inclusive end never give an empty
+                sequence, so <literal>0..length-1</literal> is
+                <emphasis>WRONG</emphasis>, because when length is
+                <literal>0</literal> it gives <literal>[0,
+                -1]</literal>.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..&lt;<replaceable>end</replaceable></literal>
+                or
+                <literal><replaceable>start</replaceable>..!<replaceable>end</replaceable></literal>:
+                Range with exclusive end. For example,
+                <literal>1..&lt;4</literal> gives <literal>[1, 2,
+                3]</literal>, <literal>4..&lt;1</literal> gives <literal>[4,
+                3, 2]</literal>, and <literal>1..&lt;1</literal> gives
+                <literal>[]</literal>. Note the last example; the result can
+                be an empty sequence. There's no difference between
+                <literal>..&lt;</literal> and <literal>..!</literal>; the last
+                form is used in applications where using the
+                <literal>&lt;</literal> character causes problems (for HTML
+                editors and such).</para>
+              </listitem>
+
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..*<replaceable>length</replaceable></literal>:
+                Length limited range. For example, <literal>10..*4</literal>
+                gives <literal>[10, 11, 12, 13]</literal>,
+                <literal>10..*-4</literal> gives <literal>[10, 9, 8,
+                7]</literal>, and <literal>10..*0</literal> gives
+                <literal>[]</literal>. When these kind of ranges are used for
+                slicing, the slice will end without error if the end of the
+                sliced sequence or string is reached before the specified
+                range length was reached; see <link
+                linkend="dgui_template_exp_seqenceop_slice">slicing
+                sequences</link> for more.</para>
+
+                <note>
+                  <para>Length limited ranges were introduced in FreeMarker
+                  2.3.21.</para>
+                </note>
+              </listitem>
+
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..</literal>:
+                Right-unbounded range. This are like length limited ranges
+                with infinite length. For example <literal>1..</literal> gives
+                <literal>[1, 2, 3, 4, 5, 6, ... ]</literal>, up to infinity.
+                Be careful when processing (like listing) such ranges, as
+                processing all items of it it would take forever or until the
+                application runs out of memory and crashes. Just like with
+                length limited ranges, when these kind of ranges are used for
+                slicing, the slice will end when the end of the sliced
+                sequence or string is reached.</para>
+
+                <warning>
+                  <para>Right-unbounded ranges before FreeMarker 2.3.21 were
+                  only used for slicing, and behaved like an empty sequence
+                  for other purposes. To activate the new behavior, it's not
+                  enough to use FreeMarker 2.3.21, the programmer also have to
+                  set the <literal>incompatible_improvements</literal>
+                  configuration setting to at least 2.3.21.</para>
+                </warning>
+              </listitem>
+            </itemizedlist>
+
+            <para>Further notes on ranges:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>Range expressions themselves don't have square brackets,
+                for example, you write <literal>&lt;#assign myRange =
+                0..&lt;x</literal>, NOT <literal>&lt;#assign myRange =
+                [0..&lt;x]&gt;</literal>. The last would create a sequence
+                that contains an item that's a range. The square brackets are
+                part of the slicing syntax, like
+                <literal><replaceable>seq</replaceable>[<replaceable>myRange</replaceable>]</literal>.</para>
+              </listitem>
+
+              <listitem>
+                <para>You can write arithmetical expression on the sides of
+                the <literal>..</literal> without parenthesis, like <literal>n
+                + 1 ..&lt; m / 2 - 1</literal>.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>..</literal>, <literal>..&lt;</literal>,
+                <literal>..!</literal> and <literal>..*</literal> are
+                operators, so you can't have space inside them. Like
+                <literal>n .. &lt;m</literal> is WRONG, but <literal>n ..&lt;
+                m</literal> is good.</para>
+              </listitem>
+
+              <listitem>
+                <para>The reported size of right-unbounded ranges is
+                2147483647 (or 0 if
+                <literal>incompatible_improvements</literal> is less than
+                2.3.21) due to a technical limitation (32 bits). However, when
+                listing them, their actual size is infinite.</para>
+              </listitem>
+
+              <listitem>
+                <para>Ranges don't really store the numbers they consist of,
+                thus for example <literal>0..1</literal> and
+                <literal>0..100000000</literal> is equally fast to create and
+                takes the same amount of memory.</para>
+              </listitem>
+            </itemizedlist>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_hash">
+            <title>Hashes</title>
+
+            <indexterm>
+              <primary>hash</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>literal</primary>
+
+              <secondary>hash</secondary>
+            </indexterm>
+
+            <para>To specify a hash in a template, you list the key/value
+            pairs separated by commas, and put the list into curly brackets.
+            The key and value within a key/value pair are separated with a
+            colon. Here is an example: <literal>{ "name": "green mouse",
+            "price": 150 }</literal>. Note that both the names and the values
+            are expressions. The keys must be strings. The values can be if
+            any type.</para>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_var">
+          <title>Retrieving variables</title>
+
+          <section xml:id="dgui_template_exp_var_toplevel">
+            <title>Top-level variables</title>
+
+            <indexterm>
+              <primary>subvariable</primary>
+
+              <secondary>accessing</secondary>
+            </indexterm>
+
+            <para>To access a top-level variable, you simply use the variable
+            name. For example, the expression <literal>user</literal> will
+            evaluate to the value of variable stored with name
+            <quote>user</quote> in the root. So this will print what you store
+            there:</para>
+
+            <programlisting role="template">${user}</programlisting>
+
+            <para>If there is no such top-level variable, then an error will
+            result when FreeMarker tries to evaluate the expression, and it
+            aborts template processing (unless programmers has configured
+            FreeMarker differently).</para>
+
+            <para>In this kind of expression, the variable name can only
+            contain letters (including non-Latin letters), digits (including
+            non-Latin digits), underline (<literal>_</literal>), dollar
+            (<literal>$</literal>), at sign (<literal>@</literal>).
+            Furthermore, the first character can't be an ASCII digit
+            (<literal>0</literal>-<literal>9</literal>). Since FreeMarker
+            2.3.22 the variable name can also contain minus
+            (<literal>-</literal>), dot (<literal>.</literal>), and colon
+            (<literal>:</literal>) at any position, but these must be escaped
+            with a preceding backslash (<literal>\</literal>), otherwise they
+            are interpreted as operators. For example, to read the variable
+            whose name is <quote>data-id</quote>, the expression is
+            <literal>data\-id</literal>, as <literal>data-id</literal> would
+            be interpreted as <quote>data minus id</quote>. (Note that these
+            escapes only work in identifiers, not in string literals.)
+            Furthermore, since FreeMarker 2.3.31, hash mark
+            (<literal>#</literal>) can also be used, but must be escaped with
+            a preceding backslash (<literal>\</literal>).</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_var_hash">
+            <title>Retrieving data from a hash</title>
+
+            <indexterm>
+              <primary>subvariable</primary>
+
+              <secondary>accessing</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>hash</primary>
+
+              <secondary>accessing subvariable</secondary>
+            </indexterm>
+
+            <para>If we already have a hash as a result of an expression, then
+            we can get its subvariable with a dot and the name of the
+            subvariable. Assume that we have this data-model:</para>
+
+            <programlisting role="dataModel">(root)
+ |
+ +- book
+ |   |
+ |   +- title = "Breeding green mouses"
+ |   |
+ |   +- author
+ |       |
+ |       +- name = "Julia Smith"
+ |       |
+ |       +- info = "Biologist, 1923-1985, Canada"
+ |
+ +- test = "title"</programlisting>
+
+            <para>Now we can read the <literal>title</literal> with
+            <literal>book.title</literal>, since the book expression will
+            return a hash (as explained in the last chapter). Applying this
+            logic further, we can read the name of the author with this
+            expression: <literal>book.author.name</literal>.</para>
+
+            <para>There is an alternative syntax if we want to specify the
+            subvariable name with an expression:
+            <literal>book["title"]</literal>. In the square brackets you can
+            give any expression as long as it evaluates to a string. So with
+            this data-model you can also read the title with
+            <literal>book[test]</literal>. More examples; these are all
+            equivalent: <literal>book.author.name</literal>,
+            <literal>book["author"].name</literal>,
+            <literal>book.author["name"]</literal>,
+            <literal>book["author"]["name"]</literal>.</para>
+
+            <para>When you use the dot syntax, the same restrictions apply
+            regarding the variable name as with top-level variables (name can
+            contain only letters, digits, <literal>_</literal>,
+            <literal>$</literal>, <literal>@</literal> but can't start with
+            <literal>0</literal>-<literal>9</literal>, also starting from
+            2.3.22 you can also use <literal>\-</literal>,
+            <literal>\.</literal> and <literal>\:</literal>). There are no
+            such restrictions when you use the square bracket syntax, since
+            the name is the result of an arbitrary expression. (Note, that to
+            help the FreeMarker XML support, if the subvariable name is
+            <literal>*</literal> (asterisk) or <literal>**</literal>, then you
+            do not have to use square bracket syntax.)</para>
+
+            <para>As with the top-level variables, trying to access a
+            non-existent subvariable causes an error and aborts the processing
+            of the template (unless programmers has configured FreeMarker
+            differently).</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_var_sequence">
+            <title>Retrieving data from a sequence</title>
+
+            <indexterm>
+              <primary>subvariable</primary>
+
+              <secondary>accessing</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>sequence</primary>
+
+              <secondary>accessing subvariable</secondary>
+            </indexterm>
+
+            <para>This is the same as for hashes, but you can use the square
+            bracket syntax only, and the expression in the brackets must
+            evaluate to a number, not a string. For example to get the name of
+            the first animal of the <link
+            linkend="example.stdDataModel">example data-model</link> (remember
+            that the number of the first item is 0, not 1):
+            <literal>animals[0].name</literal></para>
+          </section>
+
+          <section xml:id="dgui_template_exp_var_special">
+            <title>Special variables</title>
+
+            <indexterm>
+              <primary>special variables</primary>
+            </indexterm>
+
+            <para>Special variables are variables defined by the FreeMarker
+            engine itself. To access them, you use the
+            <literal>.<replaceable>variable_name</replaceable></literal>
+            syntax.</para>
+
+            <para>Normally you don't need to use special variables. They are
+            for expert users. The complete list of special variables can be
+            found in the <link linkend="ref_specvar">reference</link>.</para>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_stringop">
+          <title>String operations</title>
+
+          <indexterm>
+            <primary>string</primary>
+
+            <secondary>operations</secondary>
+          </indexterm>
+
+          <section xml:id="dgui_template_exp_stringop_interpolation">
+            <title>Interpolation and concatenation</title>
+
+            <indexterm>
+              <primary>interpolation</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>concatenate strings</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>joining strings</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>concatenate</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>interpolation</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>adding strings</primary>
+            </indexterm>
+
+            <para>If you want to insert the value of an expression into a
+            string, you can use
+            <literal>${<replaceable>...</replaceable>}</literal> (and the
+            deprecated <literal>#{<replaceable>...</replaceable>}</literal>)
+            in string literals.
+            <literal>${<replaceable>...</replaceable>}</literal> in string
+            literals <link linkend="dgui_template_valueinsertion">behaves
+            similarly as in <phrase role="markedText">text</phrase>
+            sections</link> (so it goes through the same <emphasis>locale
+            sensitive</emphasis> number and date/time formatting).</para>
+
+            <note>
+              <para>It's possible to configure FreeMarker's interpolation
+              syntax to use
+              <literal>[=<replaceable>...</replaceable>]</literal> instead;
+              <link linkend="dgui_misc_alternativesyntax_interpolation">see
+              here</link>.</para>
+            </note>
+
+            <para>Example (assume that user is <quote>Big Joe</quote>):</para>
+
+            <programlisting role="template">&lt;#assign s = "Hello ${user}!"&gt;
+${s} &lt;#-- Just to see what the value of s is --&gt;
+</programlisting>
+
+            <para>This will print:</para>
+
+            <programlisting role="output">Hello Big Joe!</programlisting>
+
+            <warning>
+              <para>A frequent mistake of users is the usage of interpolations
+              in places where they needn't/shouldn't/can't be used.
+              Interpolations work <emphasis>only</emphasis> in <link
+              linkend="dgui_template_overallstructure"><phrase
+              role="markedText">text</phrase> sections</link> (e.g.
+              <literal>&lt;h1&gt;Hello ${name}!&lt;/h1&gt;</literal>) and in
+              string literals (e.g. <literal>&lt;#include
+              "/footer/${company}.html"&gt;</literal>). A typical
+              <emphasis>WRONG</emphasis> usage is <literal>&lt;#if
+              ${big}&gt;...&lt;/#if&gt;</literal>, which will cause a
+              syntactical error. You should simply write <literal>&lt;#if
+              big&gt;...&lt;/#if&gt;</literal>. Also, <literal>&lt;#if
+              "${big}"&gt;...&lt;/#if&gt;</literal> is
+              <emphasis>WRONG</emphasis>, since it converts the parameter
+              value to string and the <literal>if</literal> directive wants a
+              boolean value, so it will cause a runtime error.</para>
+            </warning>
+
+            <para
+            xml:id="dgui_template_exp_stringop_concatenation">Alternatively,
+            you can use the <literal>+</literal> operator to achieve similar
+            result:</para>
+
+            <programlisting role="template">&lt;#assign s = "Hello " + user + "!"&gt;</programlisting>
+
+            <para>This gives the same result as the earlier example with the
+            <literal>${<replaceable>...</replaceable>}</literal>.</para>
+
+            <warning>
+              <para>Because <literal>+</literal> follows similar rules as
+              <literal>${<replaceable>...</replaceable>}</literal>, the
+              appended string is influenced by the <literal>locale</literal>,
+              <literal>number_format</literal>,
+              <literal>date_format</literal>, <literal>time_format</literal>,
+              <literal>datetime_format</literal> and
+              <literal>boolean_format</literal>, etc. settings, and thus the
+              result targets humans and isn't in generally machine parseable.
+              This mostly leads to problems with numbers, as many locales use
+              grouping (thousands separators) by default, and so
+              <literal>"someUrl?id=" + id</literal> becomes to something like
+              <literal>"someUrl?id=1 234"</literal>. To prevent this, use the
+              <literal>?c</literal> (for Computer audience) built-in, like in
+              <literal>"someUrl?id=" + id?c</literal> or
+              <literal>"someUrl?id=${id?c}"</literal>, which will evaluate to
+              something like <literal>"someUrl?id=1234"</literal>, regardless
+              of locale and format settings.</para>
+            </warning>
+
+            <para>As when <literal>${<replaceable>...</replaceable>}</literal>
+            is used inside string <emphasis>expressions</emphasis> it's just a
+            shorthand of using the <literal>+</literal> operator, <link
+            linkend="dgui_misc_autoescaping">auto-escaping</link> is not
+            applied on it.</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_get_character">
+            <title>Getting a character</title>
+
+            <indexterm>
+              <primary>charAt</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>get character</primary>
+            </indexterm>
+
+            <para>You can get a single character of a string at a given index
+            similarly as you can <link
+            linkend="dgui_template_exp_var_sequence">read the subvariable of a
+            sequence</link>, e.g. <literal>user[0]</literal>. The result will
+            be a string whose length is 1; FTL doesn't have a separate
+            character type. As with sequence sub variables, the index must be
+            a number that is at least 0 and less than the length of the
+            string, or else an error will abort the template
+            processing.</para>
+
+            <para>Since the sequence subvariable syntax and the character
+            getter syntax clashes, you can use the character getter syntax
+            only if the variable is not a sequence as well (which is possible
+            because FTL supports multi-typed values), since in that case the
+            sequence behavior prevails. (To work this around, you can use
+            <link linkend="ref_builtin_string_for_string">the
+            <literal>string</literal> built-in</link>, e.g.
+            <literal>user?string[0]</literal>. Don't worry if you don't
+            understand this yet; built-ins will be discussed later.)</para>
+
+            <para>Example (assume that user is <quote>Big Joe</quote>):</para>
+
+            <programlisting role="template">${user[0]}
+${user[4]}</programlisting>
+
+            <para>will print (note that the index of the first character is
+            0):</para>
+
+            <programlisting role="output">B
+J</programlisting>
+          </section>
+
+          <section xml:id="dgui_template_exp_stringop_slice">
+            <title>String slicing (substrings)</title>
+
+            <indexterm>
+              <primary>string slicing</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>substring</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>slice</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>substring</secondary>
+            </indexterm>
+
+            <para>You can slice a string in the same way as you <link
+            linkend="dgui_template_exp_seqenceop_slice">slice a
+            sequence</link> (see there), only here instead of sequence items
+            you work with characters. Some differences are:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>Decreasing ranges aren't allowed for string slicing.
+                (That's because unlike sequences, you seldom if ever want to
+                show a string reversed, so if that happens, that's almost
+                always the result of an oversight.)</para>
+              </listitem>
+
+              <listitem>
+                <para>If a value is both a string and a sequence (a
+                multi-typed value), then slicing will slice the sequence
+                instead of the string. When you are processing XML, such
+                values are common. In such cases you can use
+                <literal><replaceable>someXMLnode</replaceable>?string[<replaceable>range</replaceable>]</literal>
+                to fore string slicing.</para>
+              </listitem>
+
+              <listitem>
+                <para>There's a legacy bug where a range with
+                <emphasis>inclusive</emphasis> end that's one less than the
+                starting index and is non-negative (like in
+                <literal>"abc"[1..0]</literal>) will give an empty string
+                instead of an error. (It should be an error as it's a
+                decreasing range.) Currently this bug is emulated for backward
+                compatibility, but you shouldn't utilize it, as in the future
+                it will be certainly an error.</para>
+              </listitem>
+            </itemizedlist>
+
+            <para>Example:</para>
+
+            <programlisting role="template">&lt;#assign s = "ABCDEF"&gt;
+${s[2..3]}
+${s[2..&lt;4]}
+${s[2..*3]}
+${s[2..*100]}
+${s[2..]}</programlisting>
+
+            <para>will print:</para>
+
+            <programlisting role="output">CD
+CD
+CDE
+CDEF
+CDEF</programlisting>
+
+            <note>
+              <para>Some of the typical use-cases of string slicing is covered
+              by convenient built-ins: <link
+              linkend="ref_builtin_remove_beginning"><literal>remove_beginning</literal></link>,
+              <link
+              linkend="ref_builtin_remove_ending"><literal>remove_ending</literal></link>,
+              <link
+              linkend="ref_builtin_keep_before"><literal>keep_before</literal></link>,
+              <link
+              linkend="ref_builtin_keep_after"><literal>keep_after</literal></link>,
+              <link
+              linkend="ref_builtin_keep_before_last"><literal>keep_before_last</literal></link>,
+              <link
+              linkend="ref_builtin_keep_after_last"><literal>keep_after_last</literal></link></para>
+            </note>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_sequenceop">
+          <title>Sequence operations</title>
+
+          <indexterm>
+            <primary>sequence</primary>
+
+            <secondary>operations</secondary>
+          </indexterm>
+
+          <section xml:id="dgui_template_exp_sequenceop_cat">
+            <title>Concatenation</title>
+
+            <indexterm>
+              <primary>concatenate sequences</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>joining sequences</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>sequence</primary>
+
+              <secondary>concatenate</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>adding sequences</primary>
+            </indexterm>
+
+            <para>You can concatenate sequences in the same way as strings,
+            with <literal>+</literal>. Example:</para>
+
+            <programlisting role="template">&lt;#list ["Joe", "Fred"] + ["Julia", "Kate"] as user&gt;
+- ${user}
+&lt;/#list&gt;</programlisting>
+
+            <para>will print:</para>
+
+            <programlisting role="output">- Joe
+- Fred
+- Julia
+- Kate
+ </programlisting>
+
+            <para>Note that sequence concatenation is not to be used for many
+            repeated concatenations, like for appending items to a sequence
+            inside a loop. It's just for things like <literal>&lt;#list users
+            + admins as person&gt;</literal>. Although concatenating sequences
+            is fast and is constant time (it's speed is independently of the
+            size of the concatenated sequences), the resulting sequence will
+            be always a little bit slower to read than the original two
+            sequences were. Thus, after tens or hundreds of repeated
+            concatenations the result can be impractically slow to
+            reader.</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_seqenceop_slice">
+            <title>Sequence slicing</title>
+
+            <indexterm>
+              <primary>sequence slice</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>sequence</primary>
+
+              <secondary>slice</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>subsequence</primary>
+            </indexterm>
+
+            <para>With
+            <literal><replaceable>seq</replaceable>[<replaceable>range</replaceable>]</literal>,
+            were <literal><replaceable>range</replaceable></literal> is a
+            range value <link linkend="dgui_template_exp_direct_ranges">as
+            described here</link>, you can take a slice of the sequence. The
+            resulting sequence will contain the items from the original
+            sequence (<literal><replaceable>seq</replaceable></literal>) whose
+            indexes are in the range. For example:</para>
+
+            <programlisting role="template">&lt;#assign seq = ["A", "B", "C", "D", "E"]&gt;
+&lt;#list seq[1..3] as i&gt;${i}&lt;/#list&gt;</programlisting>
+
+            <para>will print</para>
+
+            <programlisting role="output">BCD </programlisting>
+
+            <para>Furthermore, the items in the slice will be in the same
+            order as in the range. Thus for example the above example with the
+            <literal>3..1</literal> range would print
+            <literal>DCB</literal>.</para>
+
+            <para>The numbers in the range must be valid indexes in the
+            sequence, or else the processing of the template will be aborted
+            with error. Like in the last example,
+            <literal>seq[-1..0]</literal> would be an error as
+            <literal>seq[-1]</literal> is invalid, also
+            <literal>seq[1..5]</literal> would be because
+            <literal>seq[5]</literal> is invalid. (Note that
+            <literal>seq[100..&lt;100]</literal> or
+            <literal>seq[100..*0]</literal> would be valid despite that 100 is
+            out of bounds, because those ranges are empty.)</para>
+
+            <para>Length limited ranges
+            (<literal><replaceable>start</replaceable>..*<replaceable>length</replaceable></literal>)
+            and right-unbounded ranges
+            (<literal><replaceable>start</replaceable>..</literal>) adapt to
+            the length of the sliced sequence. They will slice out at most as
+            many items as there is available:</para>
+
+            <programlisting role="template">&lt;#assign seq = ["A", "B", "C"]&gt;
+
+Slicing with length limited ranges:
+- &lt;#list seq[0..*2] as i&gt;${i}&lt;/#list&gt;
+- &lt;#list seq[1..*2] as i&gt;${i}&lt;/#list&gt;
+- &lt;#list seq[2..*2] as i&gt;${i}&lt;/#list&gt; &lt;#-- Not an error --&gt;
+- &lt;#list seq[3..*2] as i&gt;${i}&lt;/#list&gt; &lt;#-- Not an error --&gt;
+
+Slicing with right-unlimited ranges:
+- &lt;#list seq[0..] as i&gt;${i}&lt;/#list&gt;
+- &lt;#list seq[1..] as i&gt;${i}&lt;/#list&gt;
+- &lt;#list seq[2..] as i&gt;${i}&lt;/#list&gt;
+- &lt;#list seq[3..] as i&gt;${i}&lt;/#list&gt;</programlisting>
+
+            <para>This will print:</para>
+
+            <programlisting role="output">Slicing with length limited ranges:
+- AB
+- BC
+- C
+-
+
+Slicing with right-unlimited ranges:
+- ABC
+- BC
+- C
+-</programlisting>
+
+            <para>Note above that slicing with length limited and right
+            unbounded ranges allow the starting index to be past the last item
+            <emphasis>by one</emphasis> (but no more).</para>
+
+            <note>
+              <para>To split a sequence to slices of a given size, you should
+              use the <link
+              linkend="ref_builtin_chunk"><literal>chunk</literal></link>
+              built-in.</para>
+            </note>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_hashop">
+          <title>Hash operations</title>
+
+          <indexterm>
+            <primary>hash</primary>
+
+            <secondary>operations</secondary>
+          </indexterm>
+
+          <section xml:id="dgui_template_exp_hashop_cat">
+            <title>Concatenation</title>
+
+            <indexterm>
+              <primary>concatenate hashes</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>joining hashes</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>hash</primary>
+
+              <secondary>concatenate</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>adding hashes</primary>
+            </indexterm>
+
+            <para>You can concatenate hashes in the same way as strings, with
+            <literal>+</literal>. If both hashes contain the same key, the
+            hash on the right-hand side of the <literal>+</literal> takes
+            precedence. Example:</para>
+
+            <programlisting role="template">&lt;#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}&gt;
+- Joe is ${ages.Joe}
+- Fred is ${ages.Fred}
+- Julia is ${ages.Julia}
+</programlisting>
+
+            <para>will print:</para>
+
+            <programlisting role="output">- Joe is 30
+- Fred is 25
+- Julia is 18</programlisting>
+
+            <para>Note that hash concatenation is not to be used for many
+            repeated concatenations, like for adding items to a hash inside a
+            loop. While adding together hashes is fast and is constant time
+            (independent of the size of the hashes added), the resulting hash
+            is a bit slower to read than the hashes added together. Thus after
+            tens or hundreds of additions the result can be impractically slow
+            to read.</para>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_arit">
+          <title>Arithmetical calculations</title>
+
+          <indexterm>
+            <primary>arithmetic</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>math</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>addition</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>subtraction</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>division</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>modulus</primary>
+          </indexterm>
+
+          <para>This is the basic 4-function calculator arithmetic plus the
+          modulus operator. So the operators are:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para>Addition: <literal>+</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Subtraction: <literal>-</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Multiplication: <literal>*</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Division: <literal>/</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Modulus (remainder) of integer operands:
+              <literal>%</literal></para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Example:</para>
+
+          <programlisting role="template">${100 - x * x}
+${x / 2}
+${12 % 10}</programlisting>
+
+          <para>Assuming that <literal>x</literal> is 5, it will print:</para>
+
+          <programlisting role="output">75
+2.5
+2</programlisting>
+
+          <para>Both operands must be expressions which evaluate to a
+          numerical value. So the example below will cause an error when
+          FreeMarker tries to evaluate it, since <literal>"5"</literal> is a
+          string and not the number 5:</para>
+
+          <programlisting role="template">${3 * "5"} &lt;#-- WRONG! --&gt;</programlisting>
+
+          <para>There is an exception to the above rule. The
+          <literal>+</literal> operator, is used to <link
+          linkend="dgui_template_exp_stringop_interpolation">concatenate
+          strings</link> as well. If on one side of <literal>+</literal> is a
+          string and on the other side of <literal>+</literal> is a numerical
+          value, then it will convert the numerical value to string (using the
+          format appropriate for language of the page) and then use the
+          <literal>+</literal> as string concatenation operator.
+          Example:</para>
+
+          <programlisting role="template">${3 + "5"}</programlisting>
+
+          <programlisting role="output">35</programlisting>
+
+          <para>Generally, FreeMarker never converts a string to a number
+          automatically, but it may convert a number to a string
+          automatically.</para>
+
+          <para><indexterm>
+              <primary>integer division</primary>
+            </indexterm><indexterm>
+              <primary>integer part</primary>
+            </indexterm> People often want only the integer part of the result
+          of a division (or of other calculations). This is possible with the
+          <literal>int</literal> built-in. (Built-ins are explained <link
+          linkend="dgui_template_exp_builtin">later</link>):</para>
+
+          <programlisting role="template">${(x/2)?int}
+${1.1?int}
+${1.999?int}
+${-1.1?int}
+${-1.999?int}</programlisting>
+
+          <para>Assuming that <literal>x</literal> is 5, it will print:</para>
+
+          <programlisting role="output">2
+1
+1
+-1
+-1</programlisting>
+
+          <para>Due to historical reasons, the <literal>%</literal> operator
+          works by first truncating the operands to an integer number, and
+          then returning the remainder of the division:</para>
+
+          <programlisting role="template">${12 % 5}   &lt;#-- Prints 2 --&gt;
+${12.9 % 5} &lt;#-- Prints 2 --&gt;
+${12.1 % 5} &lt;#-- Prints 2 --&gt;
+
+${12 % 6}   &lt;#-- Prints 0 --&gt;
+${12 % 6.9} &lt;#-- Prints 0 --&gt;</programlisting>
+
+          <para>The sign of the result of <literal>%</literal> is the same as
+          the sign of the left hand operand, and its absolute value is the
+          same as if both operands where positive:</para>
+
+          <programlisting role="template">${-12 % -5} &lt;#-- Prints -2 --&gt;
+${-12 % 5} &lt;#-- Prints -2 --&gt;
+${12 % -5} &lt;#-- Prints 2 --&gt;
+</programlisting>
+
+          <para role="forProgrammers">About the precision of the operations:
+          By default FreeMarker uses <literal>BigDecimal</literal>-s for all
+          arithmetical calculations, to avoid rounding and overflow/underflow
+          artifacts, and also keeps the result as
+          <literal>BigDecimal</literal>-s. So <literal>+</literal> (addition),
+          <literal>-</literal> (subtraction) and <literal>*</literal>
+          (multiplication) are <quote>lossless</quote>. Again by default,
+          <literal>/</literal> (division) results are calculated to 12
+          decimals with half-up rounding (unless some operands have even more
+          decimals, in which case it's calculated with that much decimals).
+          All this behavior depends on the
+          <literal>arithmetic_engine</literal> configuration setting
+          (<literal>Configurable.setArithmericEngine(ArithmericEngine)</literal>)
+          though, and some application might use a different value than the
+          default, although that's highly uncommon.</para>
+        </section>
+
+        <section xml:id="dgui_template_exp_comparison">
+          <title>Comparison</title>
+
+          <indexterm>
+            <primary>comparison operators</primary>
+          </indexterm>
+
+          <para>Sometimes you want to know if two values are equal or not, or
+          which value is the greater.</para>
+
+          <para>To show concrete examples I will use the <literal>if</literal>
+          directive here. The usage of <literal>if</literal> directive is:
+          <literal>&lt;#if
+          <replaceable>expression</replaceable>&gt;...&lt;/#if&gt;</literal>,
+          where expression must evaluate to a boolean value or else an error
+          will abort the processing of the template. If the value of
+          expression is <literal>true</literal> then the things between the
+          begin and end-tag will be processed, otherwise they will be
+          skipped.</para>
+
+          <para>To test two values for equality you use <literal>==</literal>
+          (or <literal>=</literal> as a <emphasis>deprecated</emphasis>
+          alternative) To test two values for inequality you use
+          <literal>!=</literal>. For example, assume that
+          <literal>user</literal> is <quote>Big Joe</quote>:</para>
+
+          <programlisting role="template">&lt;#if <emphasis>user == "Big Joe"</emphasis>&gt;
+  It is Big Joe
+&lt;/#if&gt;
+&lt;#if <emphasis>user != "Big Joe"</emphasis>&gt;
+  It is not Big Joe
+&lt;/#if&gt;</programlisting>
+
+          <para>The <literal>user == "Big Joe"</literal> expression in the
+          <literal>&lt;#if ...&gt;</literal> will evaluate to the boolean
+          <literal>true</literal>, so the above will say <quote>It is Big
+          Joe</quote>.</para>
+
+          <para>The expressions on both sides of the <literal>==</literal> or
+          <literal>!=</literal> must evaluate to a scalar (not a sequence or
+          hash). Furthermore, the two scalars must have the same type (i.e.
+          strings can only be compared to strings and numbers can only be
+          compared to numbers, etc.) or else an error will abort template
+          processing. For example <literal>&lt;#if 1 == "1"&gt;</literal> will
+          cause an error. Note that FreeMarker does exact comparison, so
+          string comparisons are case and white-space sensitive:
+          <literal>"x"</literal> and <literal>"x "</literal> and
+          <literal>"X"</literal> are not equal values.</para>
+
+          <para>For numerical and date, time and date-time values you can also
+          use <literal>&lt;</literal>, <literal>&lt;=</literal>,
+          <literal>&gt;=</literal> and <literal>&gt;</literal>. You can't use
+          them for strings! Example:</para>
+
+          <programlisting role="template">&lt;#if x <emphasis>&lt;=</emphasis> 12&gt;
+  x is less or equivalent with 12
+&lt;/#if&gt;</programlisting>
+
+          <para>There's a problem with <literal>&gt;=</literal> and
+          <literal>&gt;</literal>. FreeMarker interprets the
+          <literal>&gt;</literal> character as the closing character of the
+          FTL tag. To prevent this, you can use <literal>lt</literal> instead
+          of <literal>&lt;</literal>, <literal>lte</literal> instead of
+          <literal>&lt;=</literal>, <literal>gt</literal> instead of
+          <literal>&gt;</literal> and <literal>gte</literal> instead of
+          <literal>&gt;=</literal>, like in <literal>&lt;#if x gt
+          y&gt;</literal>. Another trick it to put the expression into <link
+          linkend="dgui_template_exp_parentheses">parentheses</link> like in
+          <literal>&lt;#if (x &gt; y)&gt;</literal>, although it's considered
+          to be less elegant.</para>
+
+          <para>FreeMarker supports some more syntactical alternatives:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>&amp;gt;</literal> and
+              <literal>&amp;lt;</literal> can also be used, like in:
+              <literal>&lt;#if x &amp;gt; y&gt;</literal> or <literal>&lt;#if
+              x &amp;gt;= y&gt;</literal>. This isn't meant to be entered
+              manually; it's to work around cases where the template gets
+              XML/HTML escaped and the user can't easily prevent that
+              happening. Note that in general FTL does not support entity
+              references (the
+              <literal>&amp;<replaceable>...</replaceable>;</literal> things)
+              in FTL tags; it's just an exception with these operators.</para>
+            </listitem>
+
+            <listitem>
+              <para>Deprecated forms: <literal>\lt</literal>,
+              <literal>\lte</literal>, <literal>\gt</literal> and
+              <literal>\gte</literal>. These are the same as the ones without
+              the backslash.</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section xml:id="dgui_template_exp_logicalop">
+          <title>Logical operations</title>
+
+          <indexterm>
+            <primary>boolean</primary>
+
+            <secondary>operations</secondary>
+          </indexterm>
+
+          <indexterm>
+            <primary>logical operations</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>or</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>and</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>not</primary>
+          </indexterm>
+
+          <para>Just the usual logical operators:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para>Logical or: <literal>||</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Logical and: <literal>&amp;&amp;</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Logical not: <literal>!</literal></para>
+            </listitem>
+          </itemizedlist>
+
+          <para>The operators will work with boolean values only. Otherwise an
+          error will abort the template processing.</para>
+
+          <para>Example:</para>
+
+          <programlisting role="template">&lt;#if x &lt; 12 <emphasis>&amp;&amp;</emphasis> color == "green"&gt;
+  We have less than 12 things, and they are green.
+&lt;/#if&gt;
+&lt;#if <emphasis>!</emphasis>hot&gt; &lt;#-- here hot must be a boolean --&gt;
+  It's not hot.
+&lt;/#if&gt;</programlisting>
+
+          <para>FreeMarker supports some more syntactical alternatives:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>\and</literal> (since FreeMarker 2.3.27): In some
+              applications using <literal>&amp;&amp;</literal> causes problems
+              as it's not valid in XML or HTML. While FreeMarker templates was
+              never intended to be valid XML/HTML, only their output should be
+              that, in reality there are some applications that expect the
+              template itself to be valid XML/HTML regardless. This syntax is
+              a workaround for such cases. Also note that unlike with the
+              comparison operators, <literal>and</literal> without
+              <literal>\</literal> is not supported due to backward
+              compatibility restrictions.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>&amp;amp;&amp;amp;</literal> (since FreeMarker
+              2.3.27): This isn't meant to be entered manually; it's to work
+              around cases where the template gets XML/HTML escaped and the
+              user can't easily prevent that happening. Note that in general
+              FTL does not support entity references (the
+              <literal>&amp;<replaceable>...</replaceable>;</literal> things)
+              in FTL tags; it's just an exception with these operators.</para>
+            </listitem>
+
+            <listitem>
+              <para>Deprecated forms: <literal>&amp;</literal> and
+              <literal>|</literal>. Don't use them anymore.</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section xml:id="dgui_template_exp_builtin">
+          <title>Built-ins</title>
+
+          <indexterm>
+            <primary>built-in</primary>
+          </indexterm>
+
+          <para>Built-ins are like methods that are added to the objects by
+          FreeMarker. To prevent name clashes with actual methods and other
+          sub-variables, instead of dot (<literal>.</literal>), you separate
+          them from the parent object with question mark
+          (<literal>?</literal>). For example, if you want to ensure that
+          <literal>path</literal> has an initial <literal>/</literal> then you
+          could write <literal>path?ensure_starts_with('/')</literal>. The
+          Java object behind <literal>path</literal> (a
+          <literal>String</literal> most certainly) doesn't have such method,
+          FreeMarker adds it. For brevity, if the method has no parameters,
+          you <emphasis>must</emphasis> omit the <literal>()</literal>, like,
+          to get the length of <literal>path</literal>, you have to write
+          <literal>path?length</literal>, <emphasis>not</emphasis>
+          <literal>path?length()</literal>.</para>
+
+          <para>The other reason why built-ins are crucial is that normally
+          (though it depends on configuration settings), FreeMarker doesn't
+          expose the Java API of the objects. So despite that Java's
+          <literal>String</literal> has a <literal>length()</literal> method,
+          it's hidden from the template, you <emphasis>have to</emphasis> use
+          <literal>path?length</literal> instead. The advantage of that is
+          that thus the template doesn't depend on the exactly type of the
+          underlying Java objects. (Like <literal>path</literal> is maybe a
+          <literal>java.nio.Path</literal> behind the scenes, but if the
+          programmers has configure FreeMarker to expose
+          <literal>Path</literal> objects as FTL strings, the template won't
+          be aware of that, and <literal>?length</literal> will work, despite
+          that <literal>java.nio.Path</literal> has no similar method.)</para>
+
+          <para>You can find some of the <link
+          linkend="topic.commonlyUsedBuiltIns">most commonly used built-ins
+          mentioned here</link>, and the <link linkend="ref_builtins">complete
+          list of built-ins in the Reference</link>. For now, just a few of
+          the more important ones:</para>
+
+          <para>Example:</para>
+
+          <programlisting role="template">${testString?upper_case}
+${testString?html}
+${testString?upper_case?html}
+
+${testSequence?size}
+${testSequence?join(", ")}</programlisting>
+
+          <para>Assuming that <literal>testString</literal> stores the string
+          <quote>Tom &amp; Jerry</quote>, and testSequnce stores the strings
+          <quote>foo</quote>, <quote>bar</quote> and <quote>baz</quote>, the
+          output will be:</para>
+
+          <programlisting role="output">TOM &amp; JERRY
+Tom &amp;amp; Jerry
+TOM &amp;amp; JERRY
+
+3
+foo, bar, baz</programlisting>
+
+          <para>Note the <literal>test?upper_case?html</literal> above. Since
+          the result of <literal>test?upper_case</literal> is a string, you
+          can apply the <literal>html</literal> built-in on it.</para>
+
+          <para>Naturally, the left side of the built-in can be arbitrary
+          expression, not just a variable name:</para>
+
+          <programlisting role="template">${testSeqence[1]?cap_first}
+${"horse"?cap_first}
+${(testString + " &amp; Duck")?html}</programlisting>
+
+          <programlisting role="output">Bar
+Horse
+Tom &amp;amp; Jerry &amp;amp; Duck</programlisting>
+        </section>
+
+        <section xml:id="dgui_template_exp_methodcall">
+          <title>Method call</title>
+
+          <indexterm>
+            <primary>call a method</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>method</primary>
+
+            <secondary>call</secondary>
+          </indexterm>
+
+          <para>If you have a method then you can use the method call
+          operation on it. The method call operation is a comma-separated list
+          of expressions in parentheses. These values are called parameters.
+          The method call operation passes these values to the method which
+          will in turn return a result. This result will be the value of the
+          whole method call expression.</para>
+
+          <para>For example, assume the programmers have made available a
+          method variable called <literal>repeat</literal>. You give a string
+          as the first parameter, and a number as the second parameter, and it
+          returns a string which repeats the first parameter the number of
+          times specified by the second parameter.</para>
+
+          <programlisting role="template">${repeat("Foo", 3)}</programlisting>
+
+          <para>will print:</para>
+
+          <programlisting role="output">FooFooFoo</programlisting>
+
+          <para>Here <literal>repeat</literal> was evaluated to the method
+          variable (according to how you <link
+          linkend="dgui_template_exp_var_toplevel">access top-level
+          variables</link>) and then <literal>("What", 3)</literal> invoked
+          that method.</para>
+
+          <para>I would like to emphasize that method calls are just plain
+          expressions, like everything else. So this:</para>
+
+          <programlisting role="template">${repeat(repeat("x", 2), 3) + repeat("Foo", 4)?upper_case}</programlisting>
+
+          <para>will print this:</para>
+
+          <programlisting role="output">xxxxxxFOOFOOFOOFOO</programlisting>
+        </section>
+
+        <section xml:id="dgui_template_exp_missing">
+          <title>Handling missing values</title>
+
+          <note>
+            <para>These operators exist since FreeMarker 2.3.7 (replacing the
+            <literal>default</literal>, <literal>exists</literal> and
+            <literal>if_exists</literal> built-ins).</para>
+          </note>
+
+          <indexterm>
+            <primary>undefined variable</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>missing variable</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>null</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>handling null-s</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>error handling</primary>
+          </indexterm>
+
+          <para>As we explained earlier, an error will occur and abort the
+          template processing if you try to access a missing variable. However
+          two special operators can suppress this error, and handle the
+          problematic situation. The handled variable can be top-level
+          variable, hash subvariable, or sequence subvariable as well.
+          Furthermore these operators handle the situation when a method call
+          doesn't return a value <phrase role="forProgrammers">(from the
+          viewpoint of Java programmers: it returns <literal>null</literal> or
+          it's return type is <literal>void</literal>)</phrase>, so it's more
+          correct to say that these operators handle missing values in
+          general, rather than just missing variables.</para>
+
+          <para><phrase role="forProgrammers">For those who know what's Java
+          <literal>null</literal>, FreeMarker 2.3.<replaceable>x</replaceable>
+          treats them as missing values. Simply, the template language doesn't
+          know the concept of <literal>null</literal>. For example, if you
+          have a bean that has a <literal>maidenName</literal> property, and
+          the value of that property is <literal>null</literal>, then that's
+          the same as if there were no such property at all, as far as the
+          template is concerned (assuming you didn't configured FreeMarker to
+          use some extreme object wrapper, that is). The result of a method
+          call that returns <literal>null</literal> is also treated as a
+          missing variable (again, assuming that you use some usual object
+          wrapper). See more <link linkend="faq_null">in the
+          FAQ</link>.</phrase></para>
+
+          <note>
+            <para>If you wonder why is FreeMarker so picky about missing
+            variables, <link linkend="faq_picky_about_missing_vars">read this
+            FAQ entry</link>.</para>
+          </note>
+
+          <section xml:id="dgui_template_exp_missing_default">
+            <title>Default value operator</title>
+
+            <indexterm>
+              <primary>default value operator</primary>
+            </indexterm>
+
+            <para>Synopsis:
+            <literal><replaceable>unsafe_expr</replaceable>!<replaceable>default_expr</replaceable></literal>
+            or <literal><replaceable>unsafe_expr</replaceable>!</literal> or
+            <literal>(<replaceable>unsafe_expr</replaceable>)!<replaceable>default_expr</replaceable></literal>
+            or
+            <literal>(<replaceable>unsafe_expr</replaceable>)!</literal></para>
+
+            <para>This operator allows you to specify a default value for the
+            case when the value is missing.</para>
+
+            <para>Example. Assume no variable called <literal>mouse</literal>
+            is present:</para>
+
+            <programlisting role="template">${mouse!"No mouse."}
+&lt;#assign mouse="Jerry"&gt;
+${mouse!"No mouse."}</programlisting>
+
+            <para>The output will be:</para>
+
+            <programlisting role="output">No mouse.
+Jerry</programlisting>
+
+            <para>The default value can be any kind of expression, so it
+            doesn't have to be a string. For example you can write
+            <literal>hits!0</literal> or <literal>colors!["red", "green",
+            "blue"]</literal>. There is no restriction regarding the
+            complexity of the expression that specifies the default value, for
+            example you can write: <literal>cargo.weight!(item.weight *
+            itemCount + 10)</literal>.</para>
+
+            <warning>
+              <para>If you have a composite expression after the
+              <literal>!</literal>, like <literal>1 + x</literal>,
+              <emphasis>always</emphasis> use parentheses, like
+              <literal>${x!(1 + y)}</literal> or <literal>${(x!1) +
+              y)}</literal>, depending on which interpretation you meant.
+              That's needed because due to a programming mistake in FreeMarker
+              2.3.x, the precedence of <literal>!</literal> (when it's used as
+              default value operator) is very low at its right side. This
+              means that, for example, <literal>${x!1 + y}</literal> is
+              misinterpreted by FreeMarker as <literal>${x!(1 + y)}</literal>
+              while it should mean <literal>${(x!1) + y}</literal>. This
+              programming error will be fixed in FreeMarker 2.4, so you should
+              not utilize this wrong behavior, or else your templates will
+              break with FreeMarker 2.4!</para>
+            </warning>
+
+            <para>If the default value is omitted, then it will be empty
+            string and empty sequence and empty hash at the same time. (This
+            is possible because FreeMarker allows multi-type values.) Note the
+            consequence that you can't omit the default value if you want it
+            to be <literal>0</literal> or <literal>false</literal>.
+            Example:</para>
+
+            <programlisting role="template">(${mouse!})
+&lt;#assign mouse = "Jerry"&gt;
+(${mouse!})</programlisting>
+
+            <para>The output will be:</para>
+
+            <programlisting role="output">()
+(Jerry)</programlisting>
+
+            <warning>
+              <para>Due to syntactical ambiguities <literal>&lt;@something
+              a=x! b=y /&gt;</literal> will be interpreted as
+              <literal>&lt;@something a=x!(b=y) /&gt;</literal>, that is, the
+              <literal>b=y</literal> will be interpreted as a comparison that
+              gives the default value for <literal>x</literal>, rather than
+              the specification of the <literal>b</literal> parameter. To
+              prevent this, write: <literal>&lt;@something a=(x!) b=y
+              /&gt;</literal></para>
+            </warning>
+
+            <para>You can use this operator in two ways with non-top-level
+            variables:</para>
+
+            <programlisting role="template">product.color!"red"</programlisting>
+
+            <para>This will handle if <literal>color</literal> is missing
+            inside <literal>product</literal> (and returns
+            <literal>"red"</literal> if so), but will not handle if
+            <literal>product</literal> is missing. That is, the
+            <literal>product</literal> variable itself must exist, otherwise
+            the template processing will die with error.</para>
+
+            <programlisting role="template">(product.color)!"red"</programlisting>
+
+            <para>This will handle if <literal>product.color</literal> is
+            missing. That is, if <literal>product</literal> is missing, or
+            <literal>product</literal> exists but it does not contain
+            <literal>color</literal>, the result will be
+            <literal>"red"</literal>, and no error will occur. The important
+            difference between this and the previous example is that when
+            surrounded with parentheses, it is allowed for any component of
+            the expression to be undefined, while without parentheses only the
+            last component of the expression is allowed to be
+            undefined.</para>
+
+            <para>Of course, the default value operator can be used with
+            sequence sub variables as well:</para>
+
+            <programlisting role="template">&lt;#assign seq = ['a', 'b']&gt;
+${seq[0]!'-'}
+${seq[1]!'-'}
+${seq[2]!'-'}
+${seq[3]!'-'}</programlisting>
+
+            <para>the outpur will be:</para>
+
+            <programlisting role="output">a
+b
+-
+-</programlisting>
+
+            <para>A negative sequence index (as
+            <literal>seq[-1]!'-'</literal>) will always cause an error, you
+            can't suppress that with this or any other operator.</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_missing_test">
+            <title>Missing value test operator</title>
+
+            <indexterm>
+              <primary>existence test operator</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>missing value test operator</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>testing for null</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>testing for missing</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>testing for undefined</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>is null</primary>
+            </indexterm>
+
+            <para>Synopsis:
+            <literal><replaceable>unsafe_expr</replaceable>??</literal> or
+            <literal>(<replaceable>unsafe_expr</replaceable>)??</literal></para>
+
+            <para>This operator tells if a value is missing or not. Depending
+            on that, the result is either <literal>true</literal> or
+            <literal>false</literal>.</para>
+
+            <para>Example. Assume no variable called <literal>mouse</literal>
+            is present:</para>
+
+            <programlisting role="template">&lt;#if mouse??&gt;
+  Mouse found
+&lt;#else&gt;
+  No mouse found
+&lt;/#if&gt;
+Creating mouse...
+&lt;#assign mouse = "Jerry"&gt;
+&lt;#if mouse??&gt;
+  Mouse found
+&lt;#else&gt;
+  No mouse found
+&lt;/#if&gt;</programlisting>
+
+            <para>The output will be:</para>
+
+            <programlisting role="output">  No mouse found
+Creating mouse...
+  Mouse found</programlisting>
+
+            <para>With non-top-level variables the rules are the same as with
+            the default value operator, that is, you can write
+            <literal>product.color??</literal> and
+            <literal>(product.color)??</literal>.</para>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_assignment">
+          <title>Assignment Operators</title>
+
+          <para>These are actually not expressions, but parts of the syntax of
+          the assignment directives, such as <link
+          linkend="ref_directive_assign"><literal>assign</literal></link>,
+          <link linkend="ref_directive_local"><literal>local</literal></link>
+          and <link
+          linkend="ref_directive_global"><literal>global</literal></link>. As
+          such, they can't be used anywhere else.</para>
+
+          <para><literal>&lt;#assign x += y&gt;</literal> is shorthand for
+          <literal>&lt;#assign x = x + y&gt;</literal>, <literal>&lt;#assign x
+          *= y&gt;</literal> is shorthand for <literal>&lt;#assign x = x *
+          y&gt;</literal>, and so on.</para>
+
+          <para><literal>&lt;#assign x++&gt;</literal> differs from
+          <literal>&lt;#assign x += 1&gt;</literal> (or <literal>&lt;#assign x
+          = x + 1&gt;</literal>) in that it always does arithmetical addition
+          (and fails if the variable is not a number), while the others are
+          overloaded to do string and sequence concatenation and hash
+          addition. <literal>&lt;#assign x--&gt;</literal> is shorthand for
+          <literal>&lt;#assign x -= 1&gt;</literal>.</para>
+
+          <note>
+            <para>The shorthand operators (like <literal>+=</literal>,
+            <literal>++</literal>, etc.) are only supported since FreeMarker
+            2.3.23. Before that, you could only use <literal>=</literal> in
+            itself, as in <literal>&lt;#assign x = x + 1&gt;</literal>.</para>
+          </note>
+        </section>
+
+        <section xml:id="dgui_template_exp_lambda">
+          <title>Local lambdas</title>
+
+          <indexterm>
+            <primary>lambda</primary>
+          </indexterm>
+
+          <para>FreeMarker doesn't support general purpose lambdas (unlike
+          Java). The usage of lambdas is restricted to the parameters of
+          certain <link linkend="dgui_template_exp_builtin">built-ins</link>,
+          like: <link
+          linkend="ref_builtin_filter"><literal>filter</literal></link>, <link
+          linkend="ref_builtin_map"><literal>map</literal></link>, <link
+          linkend="ref_builtin_take_while"><literal>take_while</literal></link>,
+          <link
+          linkend="ref_builtin_drop_while"><literal>drop_while</literal></link>.</para>
+
+          <para>The reason of this restriction is that FreeMarker doesn't
+          implement binding/capturing variables that are referred from the
+          lambda, instead it ensures that the evaluation of the lambda happens
+          before the enclosing variable scope is ended. Hence, and to
+          differentiate them from <quote>real</quote> lambdas, these are
+          called <emphasis>local</emphasis> lambdas.</para>
+
+          <para>The syntax of lambdas is like
+          <literal>(<replaceable>name1</replaceable>,
+          <replaceable>name2</replaceable>, <replaceable>...</replaceable>,
+          <replaceable>nameN</replaceable>) -&gt;
+          <replaceable>expression</replaceable></literal>. If there's only a
+          single argument, the parentheses can be omitted:
+          <literal><replaceable>name1</replaceable> -&gt;
+          <replaceable>expression</replaceable></literal>.</para>
+
+          <para>As the right side of the <literal>-&gt;</literal> is just a
+          single expression, if you need complex logic there, you probably
+          want to move that into a <link
+          linkend="ref.directive.function">function</link>, as the you can use
+          directives like <literal>if</literal>, <literal>list</literal>, etc.
+          In that case though, you don't need a lambda expression, as all
+          built-ins that support a lambda parameter, also support passing in a
+          function directly. For example, instead of <literal>seq?map(it -&gt;
+          myMapper(it))</literal> you should just write
+          <literal>seq?map(myMapper)</literal>.</para>
+
+          <para>The argument specified in a lambda expression can hold the
+          missing (Java <literal>null</literal>) value. Reading a lambda
+          argument never falls back to higher scope, so a variable with
+          identical name will not interfere when accessing the lambda
+          parameter. Therefore something like <literal>seq?filter(it -&gt;
+          it??)</literal>, which filters out missing element from the
+          sequence, will work reliably.</para>
+        </section>
+
+        <section xml:id="dgui_template_exp_parentheses">
+          <title>Parentheses</title>
+
+          <indexterm>
+            <primary>parentheses</primary>
+          </indexterm>
+
+          <para>Parentheses can be used to group any expressions. Some
+          examples:</para>
+
+          <programlisting role="template">                               &lt;#-- Output will be: --&gt;
+${3 * 2 + 2}                   &lt;#-- 8 --&gt;
+${3 * (2 + 2)}                 &lt;#-- 12 --&gt;
+${3 * ((2 + 2) * (1 / 2))}     &lt;#-- 6 --&gt;
+${"green " + "mouse"?upper_case}    &lt;#-- green MOUSE --&gt;
+${("green " + "mouse")?upper_case}  &lt;#-- GREEN MOUSE --&gt;
+&lt;#if !(color == "red" || color == "green")&gt;
+  The color is nor red nor green
+&lt;/#if&gt;</programlisting>
+
+          <para>Note that the parentheses of a <link
+          linkend="dgui_template_exp_methodcall">method call
+          expressions</link> have nothing to do with the parentheses used for
+          grouping.</para>
+        </section>
+
+        <section xml:id="dgui_template_exp_whitespace">
+          <title>White-space in expressions</title>
+
+          <para>FTL ignores superfluous <link
+          linkend="gloss.whiteSpace">white-space</link> in expressions. So
+          these are totally equivalent:</para>
+
+          <programlisting role="template">${x + ":" + book.title?upper_case}</programlisting>
+
+          <para>and</para>
+
+          <programlisting role="template">${x+":"+book.title?upper_case}</programlisting>
+
+          <para>and</para>
+
+          <programlisting role="template">${
+   x
+ + ":"   +  book   .   title
+   ?   upper_case
+      }</programlisting>
+        </section>
+
+        <section xml:id="dgui_template_exp_comment">
+          <title>Comments in expressions</title>
+
+          <indexterm>
+            <primary>comment</primary>
+          </indexterm>
+
+          <para>Expression may contain comments anywhere where they can
+          contain ignored white-space (<link
+          linkend="dgui_template_exp_whitespace">see above</link>). Comments
+          look like <literal>&lt;#-- ... --&gt;</literal> or as <literal>[#--
+          ... --]</literal>. Example:</para>
+
+          <programlisting role="template">&lt;#assign x &lt;#-- A comment --&gt; = 123 &lt;#-- A comment --&gt;&gt;
+&lt;#function f(x &lt;#-- A comment --&gt;, y &lt;#-- A comment --&gt;)&gt;
+  &lt;#return &lt;#-- A comment --&gt; 1 &lt;#-- A comment --&gt;&gt;
+&lt;/#function&gt;
+&lt;#assign someHash = {
+    "foo": 123, &lt;#-- A comment --&gt;
+    "bar": x &lt;#-- A comment --&gt; + 1,
+    &lt;#-- A comment --&gt;
+    "baaz": f(1 &lt;#-- A comment --&gt;, 2 &lt;#-- A comment --&gt;)
+} &lt;#-- A comment --&gt;&gt;</programlisting>
+        </section>
+
+        <section xml:id="dgui_template_exp_precedence">
+          <title>Operator precedence</title>
+
+          <indexterm>
+            <primary>precedence</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>operator precedence</primary>
+          </indexterm>
+
+          <para>The following table shows the precedence assigned to the
+          operators. The operators in this table are listed in precedence
+          order: the higher in the table an operator appears, the higher its
+          precedence. Operators with higher precedence are evaluated before
+          operators with a relatively lower precedence. Operators on the same
+          line have equal precedence. When binary operators (operators with
+          two <quote>parameters</quote>, as <literal>+</literal> and
+          <literal>-</literal>) of equal precedence appear next to each other,
+          they are evaluated in left-to-right order.</para>
+
+          <informaltable border="1">
+            <thead>
+              <tr>
+                <th>Operator group</th>
+
+                <th>Operators</th>
+              </tr>
+            </thead>
+
+            <tbody>
+              <tr>
+                <td>highest precedence operators</td>
+
+                <td><literal>[<replaceable>subvarName</replaceable>]
+                [<replaceable>subStringRange</replaceable>] . ?
+                (<replaceable>methodParams</replaceable>)
+                <replaceable>expr</replaceable>!
+                <replaceable>expr</replaceable>??</literal></td>
+              </tr>
+
+              <tr>
+                <td>unary prefix operators</td>
+
+                <td><literal>+<replaceable>expr</replaceable>
+                -<replaceable>expr</replaceable> !expr</literal></td>
+              </tr>
+
+              <tr>
+                <td>multiplicative operators</td>
+
+                <td><literal>* / %</literal></td>
+              </tr>
+
+              <tr>
+                <td>additive operators</td>
+
+                <td><literal>+ -</literal></td>
+              </tr>
+
+              <tr>
+                <td>numerical ranges</td>
+
+                <td><literal>..</literal> <literal>..&lt;</literal>
+                <literal>..!</literal> <literal>..*</literal></td>
+              </tr>
+
+              <tr>
+                <td>relational operators</td>
+
+                <td><literal>&lt; &gt; &lt;= &gt;=</literal> (and equivalents:
+                <literal>gt</literal>, <literal>lt</literal>, etc.)</td>
+              </tr>
+
+              <tr>
+                <td>equality operators</td>
+
+                <td><literal>== !=</literal> (and equivalents:
+                <literal>=</literal>)</td>
+              </tr>
+
+              <tr>
+                <td>logical <quote>and</quote> operator</td>
+
+                <td><literal>&amp;&amp;</literal></td>
+              </tr>
+
+              <tr>
+                <td>logical <quote>or</quote> operator</td>
+
+                <td><literal>||</literal></td>
+              </tr>
+
+              <tr>
+                <td>local lambda</td>
+
+                <td><literal>-&gt;</literal></td>
+              </tr>
+            </tbody>
+          </informaltable>
+
+          <para>For those of you who know C, Java language or JavaScript, note
+          that the precedence rules are the same as in those languages, except
+          that FTL has some operators that do not exist in those
+          languages.</para>
+
+          <para>The default value operator
+          (<literal><replaceable>exp</replaceable>!<replaceable>exp</replaceable></literal>)
+          is not yet in the table because of a programming mistake, which will
+          be only fixed in FreeMarker 2.4 due to backward compatibility
+          constraints. It meant to be a "highest precedence operator", but in
+          FreeMarker 2.3.x the precedence on its right side is very low by
+          accident. So if you have a composite expression on the right side,
+          always use paranthesses, etiher like <literal>x!(y + 1)</literal> or
+          like <literal>(x!y) + 1</literal>. Never write just <literal>x!y +
+          1</literal>.</para>
+        </section>
+      </section>
+
+      <section xml:id="dgui_template_valueinsertion">
+        <title>Interpolations</title>
+
+        <indexterm>
+          <primary>interpolation</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>${...}</primary>
+        </indexterm>
+
+        <section>
+          <title>Overview</title>
+
+          <para>The format of interpolations is
+          <literal>${<replaceable>expression</replaceable>}</literal>, where
+          <literal><replaceable>expression</replaceable></literal> can be all
+          kind of expression (e.g. <literal>${100 + x}</literal>).</para>
+
+          <note>
+            <para>FreeMarker can be configured to use
+            <literal>[=<replaceable>expression</replaceable>]</literal> syntax
+            instead. <link linkend="dgui_misc_alternativesyntax">See more
+            about alternative syntaxes...</link></para>
+          </note>
+
+          <para>The interpolation is used to insert the value of the
+          <literal><replaceable>expression</replaceable></literal> converted
+          to text (to string). Interpolations can be used only on two places:
+          in <link linkend="dgui_template_overallstructure"><phrase
+          role="markedText">text</phrase> sections</link> (e.g.,
+          <literal>&lt;h1&gt;Hello ${name}!&lt;/h1&gt;</literal>) and <link
+          linkend="dgui_template_exp_stringop_interpolation">in string literal
+          expressions</link> (e.g., <literal>&lt;#include
+          "/footer/${company}.html"&gt;</literal>).</para>
+
+          <para>The result of the expression must be a string, number or
+          date/time/date-time value, because (by default) only these types are
+          converted to string by interpolation automatically. Values of other
+          types (such as booleans, sequences) must be converted to string
+          <quote>manually</quote> (see some advices later), or an error will
+          stop the template processing.</para>
+
+          <warning>
+            <para>It's a frequent mistake to use interpolations on places
+            where they needn't/shouldn't/can't be used. Interpolations work
+            <emphasis>only</emphasis> in <link
+            linkend="dgui_template_overallstructure"><phrase
+            role="markedText">text</phrase> sections</link> (e.g.
+            <literal>&lt;h1&gt;Hello ${name}!&lt;/h1&gt;</literal>) and in
+            <link linkend="dgui_template_exp_direct_string">string
+            literals</link> (e.g. <literal>&lt;#include
+            "/footer/${company}.html"&gt;</literal>). A typical
+            <emphasis>WRONG</emphasis> usage is <literal>&lt;#if
+            ${big}&gt;...&lt;/#if&gt;</literal>, which will give syntactical
+            error. You should simply write <literal>&lt;#if
+            big&gt;...&lt;/#if&gt;</literal>. Also, <literal>&lt;#if
+            "${big}"&gt;...&lt;/#if&gt;</literal> is
+            <emphasis>WRONG</emphasis>, since it converts the parameter value
+            to string and the <literal>if</literal> directive wants a boolean
+            value, so it will cause a runtime error.</para>
+          </warning>
+        </section>
+
+        <section>
+          <title>Automatic escaping</title>
+
+          <para>If the interpolation is in a <link
+          linkend="dgui_template_overallstructure"><phrase
+          role="markedText">text</phrase> section</link> (not in a <link
+          linkend="dgui_template_exp_stringop_interpolation">string literal
+          expression</link>), the text that it inserts goes through
+          automatically escaping, <emphasis>if FreeMarker was properly
+          configured</emphasis>. <link
+          linkend="dgui_quickstart_template_autoescaping">See more about
+          escaping here...</link>.</para>
+        </section>
+
+        <section>
+          <title>Guide to inserting numerical values</title>
+
+          <para>If the expression evaluates to a number then the numerical
+          value will be converted to string according the default number
+          format. This may includes the maximum number of decimals, grouping,
+          and like. Usually the programmer should set the default number
+          format; the template author doesn't have to deal with it (but he can
+          with the <literal>number_format</literal> setting; see in the <link
+          linkend="ref_directive_setting">documentation of
+          <literal>setting</literal> directive</link>). Also, you can override
+          the default number format for a single interpolation with the <link
+          linkend="ref_builtin_string_for_number"><literal>string</literal>
+          built-in</link>.</para>
+
+          <para>The decimal separator used (and other such symbols, like the
+          group separator) depends on the current locale (language, country),
+          that also should be set by the programmer. For example, this
+          template:</para>
+
+          <programlisting role="template">${1.5}</programlisting>
+
+          <para>will print something like this if the current locale is
+          English:</para>
+
+          <programlisting role="output">1.5</programlisting>
+
+          <para>but if the current locale is German then it will print
+          something like:</para>
+
+          <programlisting role="output">1,5</programlisting>
+
+          <para>since German people use comma as decimal separator.</para>
+
+          <warning>
+            <para>As you can see, interpolations print for human audience (by
+            default at least), as opposed to ''computer audience''. In some
+            cases this is not good, like when you print a database record ID
+            as the part of an URL or as an invisible field value in a HTML
+            form, or when you print CSS/JavaScript numerical literals, because
+            these printed values will be read by computer programs and not by
+            humans. Most computer programs are very particular about the
+            format of the numbers, and understand only a kind of simple US
+            number formatting. For that, use the <link
+            linkend="ref_builtin_c"><literal>c</literal></link> (stands for
+            ''computer audience'') built-in, for example:</para>
+
+            <programlisting role="template">&lt;a href="/shop/productdetails?id=${product.id?c}"&gt;Details...&lt;/a&gt;</programlisting>
+          </warning>
+        </section>
+
+        <section xml:id="dgui_template_valueinserion_universal_date">
+          <title>Guide to inserting date/time/date-time values</title>
+
+          <para>If the expression evaluates to a date-like value then that
+          will be transformed to a text according to a default format. Usually
+          the programmer should set the default format; the template author
+          doesn't have to deal with it (but if you care, <link
+          linkend="topic.dateTimeFormatSettings">see the
+          <literal>date_format</literal>, <literal>time_format</literal> and
+          <literal>datetime_format</literal> settings</link> in the
+          documentation of the <link
+          linkend="ref.directive.setting"><literal>setting</literal>
+          directive</link>). Also, you can override the default formatting for
+          a single interpolation with the <link
+          linkend="ref_builtin_string_for_date"><literal>string</literal>
+          built-in</link>.</para>
+
+          <warning>
+            <para>To display a date-like value as text, FreeMarker must know
+            which parts of it are in use, that is, if only the date part
+            (year, month, day), or only the time part (hour, minute, second,
+            millisecond), or both. Unfortunately, because of the technical
+            limitations of Java platform, for some variables it is not
+            possible to detect this automatically; ask the programmer if the
+            data-model contains such problematic variables. When it's not
+            possible to find out which parts of the date are in use, then you
+            must help FreeMarker with the <link
+            linkend="ref_builtin_date_datetype"><literal>date</literal>,
+            <literal>time</literal> and <literal>datetime</literal></link>
+            built-ins (like <literal>${lastUpdated?datetime}</literal>), or it
+            will stop with error.</para>
+          </warning>
+        </section>
+
+        <section>
+          <title>Guide to inserting boolean values</title>
+
+          <para>By default an attempt to print boolean values with
+          interpolation causes an error and aborts template processing. For
+          example this will cause an error: <literal>${a == 2}</literal> and
+          will not print ''true'' or something like that. That's because
+          there's no universally useful way of representing booleans
+          (sometimes you want to print yes/no, sometimes enabled/disabled,
+          on/off, etc.).</para>
+
+          <para>However, you can convert booleans to strings with the <link
+          linkend="ref_builtin_string_for_boolean"><literal>?string</literal>
+          built-in</link>. For example, to print the value of the "married"
+          variable (assuming it's a boolean), you could write
+          <literal>${married?string("yes", "no")}</literal>.</para>
+
+          <para>FreeMarker can be configured with a default boolean format
+          with the <literal>boolean_format</literal> setting, then
+          <literal>${married}</literal> and such will work. However, in most
+          applications it's not recommended, as boolean should be rendered
+          differently on different places, and leaving the formatting on the
+          default is possibly just an oversight and thus should generate
+          error.</para>
+
+          <para>When you want to generate JavaScript or other computer
+          language parts, then <literal>${someBoolean?c}</literal>
+          (<quote>c</quote> stands for computer audience) should be used to
+          print true/false. (Remember that <literal>?c</literal> was also used
+          to print numbers for computer audience.)</para>
+        </section>
+
+        <section>
+          <title>Exact conversion rules</title>
+
+          <para>For those who are interested, the exact rules of conversion
+          from the expression value to string (which is then still subject to
+          escaping) are these, in this order:</para>
+
+          <orderedlist>
+            <listitem>
+              <para>If the value is a number, then it is converted to string
+              in the format specified with the
+              <literal>number_format</literal> setting. So this usually
+              formats for human audience, as opposed to computer
+              audience.</para>
+            </listitem>
+
+            <listitem>
+              <para>Else if the value is date, time or date-time, then it is
+              converted to string in the format specified with the
+              <literal>date_format</literal>, <literal>time_format</literal>
+              or <literal>datetime_format</literal> setting, respectively. If
+              it can't be detected what kind of date-like value it is (date vs
+              time vs date-time), an error will occur.</para>
+            </listitem>
+
+            <listitem>
+              <para>Else if the value is a string, then there is no
+              conversion.</para>
+            </listitem>
+
+            <listitem>
+              <para>Else if the engine is in classic compatibility
+              mode:</para>
+
+              <orderedlist>
+                <listitem>
+                  <para>If the value is a boolean, true values are converted
+                  to "true", false values are converted to an empty
+                  string.</para>
+                </listitem>
+
+                <listitem>
+                  <para>If the expression is undefined
+                  (<literal>null</literal> or a variable is undefined), it is
+                  converted to an empty string.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Else an error will abort the template
+                  processing.</para>
+                </listitem>
+              </orderedlist>
+            </listitem>
+
+            <listitem>
+              <para>Else an error will abort the template processing.</para>
+            </listitem>
+          </orderedlist>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_misc">
+      <title>Miscellaneous</title>
+
+      <remark>Do we need a short chapter on i18n/charset issues in general,
+      with the introduction of FreeMarker facilities on this field at the
+      end?</remark>
+
+      <section xml:id="dgui_misc_userdefdir">
+        <title>Defining your own directives</title>
+
+        <indexterm>
+          <primary>macro</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>transform</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>custom directive</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>user-defined directive</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>directive</primary>
+
+          <secondary>user-defined</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>tag</primary>
+
+          <secondary>user-defined</secondary>
+        </indexterm>
+
+        <para>As far as template authors are concerned, user-defined
+        directives can be defined using the <literal>macro</literal>
+        directive. <phrase role="forProgrammers">Java programmers who want to
+        implement directives in Java Language, rather than in a template,
+        should use
+        <literal>freemarker.template.TemplateDirectiveModel</literal> (see
+        <link linkend="pgui_datamodel_directive">more
+        here...</link>).</phrase></para>
+
+        <section>
+          <title>Basics</title>
+
+          <indexterm>
+            <primary>defining macro</primary>
+          </indexterm>
+
+          <para>A macro is a template fragment associated with a variable. You
+          can use that variable in your template as a user-defined directive,
+          so it helps in repetitive tasks. For example, this creates a macro
+          variable that prints a big <quote>Hello Joe!</quote>:</para>
+
+          <programlisting role="template"><emphasis>&lt;#macro greet&gt;</emphasis>
+  &lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;
+<emphasis>&lt;/#macro&gt;</emphasis></programlisting>
+
+          <para>The <literal>macro</literal> directive itself does not print
+          anything; it just creates the macro variable, so there will be a
+          variable called <literal>greet</literal>. Things between the
+          <literal>&lt;#macro greet&gt;</literal> and
+          <literal>&lt;/#macro&gt;</literal> (called <emphasis
+          role="term">macro definition body</emphasis>) will be executed only
+          when you use the variable as directive. You use user-defined
+          directives by writing <literal>@</literal> instead of
+          <literal>#</literal> in the FTL tag. Use the variable name as the
+          directive name. Also, the <link
+          linkend="gloss.endTag">end-tag</link> for user-defined directives is
+          mandatory. So you use <literal>greet</literal> like this:</para>
+
+          <programlisting role="template">&lt;@greet&gt;&lt;/@greet&gt;</programlisting>
+
+          <para>But since
+          <literal>&lt;<replaceable>anything</replaceable>&gt;&lt;/<replaceable>anything</replaceable>&gt;</literal>
+          is equivalent with
+          <literal>&lt;<replaceable>anything</replaceable>/&gt;</literal> you
+          should use this shorter form (that is familiar for you if you know
+          <link linkend="gloss.XML">XML</link>):</para>
+
+          <programlisting role="template">&lt;@greet/&gt;</programlisting>
+
+          <para>This will print:</para>
+
+          <programlisting role="output">  &lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;
+  </programlisting>
+
+          <para>But macros can do much more, since the thing between
+          <literal>&lt;#macro <replaceable>...</replaceable>&gt;</literal> and
+          <literal>&lt;/#macro&gt;</literal> is a template fragment, thus it
+          can contain interpolations
+          (<literal>${<replaceable>...</replaceable>}</literal>) and FTL tags
+          (e.g. <literal>&lt;#if
+          <replaceable>...</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>).</para>
+
+          <note>
+            <para>Programmers will say on
+            <literal>&lt;@<replaceable>...</replaceable>&gt;</literal> that
+            you <emphasis role="term">call</emphasis> the macro.</para>
+          </note>
+        </section>
+
+        <section>
+          <title>Parameters</title>
+
+          <para>Let's improve the <literal>greet</literal> macro so it can use
+          arbitrary name, not only <quote>Joe</quote>. For this purpose you
+          can use <emphasis role="term">parameters</emphasis>. You define the
+          parameters after the name of the macro in the
+          <literal>macro</literal> directive. Here we define one parameter for
+          the <literal>greet</literal> macro,
+          <literal>person</literal>:</para>
+
+          <programlisting role="template">&lt;#macro greet <emphasis>person</emphasis>&gt;
+  &lt;font size="+2"&gt;Hello <emphasis>${person}</emphasis>!&lt;/font&gt;
+&lt;/#macro&gt;</programlisting>
+
+          <para>and then you can use this macro as:</para>
+
+          <programlisting role="template">&lt;@greet <emphasis>person="Fred"</emphasis>/&gt; and &lt;@greet <emphasis>person="Batman"</emphasis>/&gt;
+</programlisting>
+
+          <para>which is similar to HTML syntax. This will print:</para>
+
+          <programlisting role="output">  &lt;font size="+2"&gt;Hello <emphasis>Fred</emphasis>!&lt;/font&gt;
+ and   &lt;font size="+2"&gt;Hello <emphasis>Batman</emphasis>!&lt;/font&gt;
+ </programlisting>
+
+          <para>As you can see, the actual value of the macro parameter is
+          accessible in the macro definition body as a variable
+          (<literal>person</literal>). As with <link
+          linkend="gloss.predefinedDirective">predefined directives</link>,
+          the value of a parameter (the right side of <literal>=</literal>) is
+          an <link linkend="dgui_template_exp">FTL expression</link>. Thus,
+          unlike with HTML, the quotation marks around
+          <literal>"Fred"</literal> and <literal>"Batman"</literal> are not
+          optional. <literal>&lt;@greet person=Fred/&gt;</literal> would mean
+          that you use the value of variable <literal>Fred</literal> for the
+          <literal>person</literal> parameter, rather than the string
+          <literal>"Fred"</literal>. Of course parameter value need not be a
+          string, it can be number, boolean, hash, sequence, etc., also you
+          can use complex expression on the right side of <literal>=</literal>
+          (e.g. <literal>someParam=(price + 50)*1.25</literal>).</para>
+
+          <para>User-defined directives can have multiple parameters. For
+          example, add a new parameter <literal>color</literal>:</para>
+
+          <programlisting role="template">&lt;#macro greet person <emphasis>color</emphasis>&gt;
+  &lt;font size="+2" color="${color}"&gt;Hello ${person}!&lt;/font&gt;
+&lt;/#macro&gt;</programlisting>
+
+          <para>and then you can use this macro like:</para>
+
+          <programlisting role="template">&lt;@greet person="Fred" color="black"/&gt;</programlisting>
+
+          <para>The order of parameters is not important, so this is
+          equivalent with the previous:</para>
+
+          <programlisting role="template">&lt;@greet color="black" person="Fred"/&gt;</programlisting>
+
+          <para>When you call the macro, you can use only parameters that you
+          have defined in the <literal>macro</literal> directive (in this
+          case: <literal>person</literal> and <literal>color</literal>). So if
+          you try <literal>&lt;@greet person="Fred" color="black"
+          background="green"/&gt;</literal> then you will get an error, since
+          you haven't mentioned parameter <literal>background</literal> in the
+          <literal>&lt;#macro
+          <replaceable>...</replaceable>&gt;</literal>.</para>
+
+          <para>Also, you must give value for all parameters that you have
+          defined for the macro. So if you try <literal>&lt;@greet
+          person="Fred"/&gt;</literal> then you will get an error, since you
+          forgot to specify the value of <literal>color</literal>. However, it
+          often happens that you would specify the same value for a parameter
+          in most cases, so you want to specify the value only when you want a
+          different value for it than the usual. This can be achieved if you
+          specify the parameter in the <literal>macro</literal> directive as
+          <literal><replaceable>param_name</replaceable>=<replaceable>usual_value</replaceable></literal>.
+          For example, you want to use <literal>"black"</literal> for
+          <literal>color</literal> if you don't specify value for that
+          parameter when you use the <literal>greet</literal>
+          directive:</para>
+
+          <programlisting role="template">&lt;#macro greet person color<emphasis>="black"</emphasis>&gt;
+  &lt;font size="+2" color="${color}"&gt;Hello ${person}!&lt;/font&gt;
+&lt;/#macro&gt;</programlisting>
+
+          <para>Now <literal>&lt;@greet person="Fred"/&gt;</literal> is OK,
+          since it is equivalent with <literal>&lt;@greet person="Fred"
+          color="black"/&gt;</literal>, thus the value of
+          <literal>color</literal> parameter is known. If you want
+          <literal>"red"</literal> for <literal>color</literal>, then you
+          write <literal>&lt;@greet person="Fred" color="red"/&gt;</literal>,
+          and this value will override the usual value specified with the
+          <literal>macro</literal> directive, so the value of
+          <literal>color</literal> parameter will be
+          <literal>"red"</literal>.</para>
+
+          <para>Also, it is important to realize that -- according to the
+          already explained <link linkend="dgui_template_exp">FTL expression
+          rules</link> -- <literal>someParam=foo</literal> and
+          <literal>someParam="${foo}"</literal> are very different. In the
+          fist case, you use the value of variable <literal>foo</literal> as
+          the value of the parameter. In the second case, you use a <link
+          linkend="dgui_template_exp_stringop_interpolation">string literal
+          with interpolation</link>, so the value of the parameter will be a
+          string -- in this case, the value of <literal>foo</literal> rendered
+          to text -- regardless of the type (as number, date, etc.) of
+          <literal>foo</literal>. Or, another example:
+          <literal>someParam=3/4</literal> and
+          <literal>someParam="${3/4}"</literal> are different. If the
+          directive wants a numerical value for <literal>someParam</literal>,
+          it will not like the second variation. Do not exchange these.</para>
+
+          <para>A very important aspect of macro parameters is that they are
+          local variables. For more information about local variables please
+          read: <xref linkend="dgui_misc_var"/></para>
+        </section>
+
+        <section>
+          <title>Nested content</title>
+
+          <para>Custom directive can have nested content, similarly as
+          predefined directives like <literal>&lt;#if
+          <replaceable>...</replaceable>&gt;<replaceable>nested
+          content</replaceable>&lt;/#if&gt;</literal> can have. For example,
+          this creates a macro that draws borders around its nested
+          content:</para>
+
+          <programlisting role="template">&lt;#macro border&gt;
+  &lt;table border=4 cellspacing=0 cellpadding=4&gt;&lt;tr&gt;&lt;td&gt;
+    <emphasis>&lt;#nested&gt;</emphasis>
+  &lt;/tr&gt;&lt;/td&gt;&lt;/table&gt;
+&lt;/#macro&gt;</programlisting>
+
+          <para>The <literal>&lt;#nested&gt;</literal> directive executes the
+          template fragment between the start-tag and end-tags of the
+          directive. So if you do this:</para>
+
+          <programlisting role="template">&lt;@border&gt;The bordered text&lt;/@border&gt;</programlisting>
+
+          <para>the output will be:</para>
+
+          <programlisting role="output">  &lt;table border=4 cellspacing=0 cellpadding=4&gt;&lt;tr&gt;&lt;td&gt;
+    The bordered text
+  &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
+ </programlisting>
+
+          <para>The <literal>nested</literal> directive can be called for
+          multiple times, for example:</para>
+
+          <programlisting role="template">&lt;#macro do_thrice&gt;<emphasis>
+  &lt;#nested&gt;
+  &lt;#nested&gt;
+  &lt;#nested&gt;</emphasis>
+&lt;/#macro&gt;
+&lt;@do_thrice&gt;
+  Anything.
+&lt;/@do_thrice&gt;</programlisting>
+
+          <para>will print:</para>
+
+          <programlisting role="output">  Anything.
+  Anything.
+  Anything.</programlisting>
+
+          <para>If you don't use the <literal>nested</literal> directive, then
+          the nested content will not be executed. Thus, if you accidentally
+          use the <literal>greet</literal> directive like this:</para>
+
+          <programlisting role="template">&lt;@greet person="Joe"&gt;
+  Anything.
+&lt;/@greet&gt;</programlisting>
+
+          <para>then FreeMarker will not see this as an error, and simply
+          prints:</para>
+
+          <programlisting role="output">&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;</programlisting>
+
+          <para>and the nested content will be ignored, since the
+          <literal>greet</literal> macro never uses <literal>nested</literal>
+          directive.</para>
+
+          <para>The nested content can be anything that is valid FTL,
+          including other user-defined directives. Thus this is OK:</para>
+
+          <programlisting role="template">&lt;@border&gt;
+  &lt;ul&gt;
+  &lt;@do_thrice&gt;
+    &lt;li&gt;&lt;@greet person="Joe"/&gt;
+  &lt;/@do_thrice&gt;
+  &lt;/ul&gt;
+&lt;/@border&gt;</programlisting>
+
+          <para>and will print:</para>
+
+          <programlisting role="output">  &lt;table border=4 cellspacing=0 cellpadding=4&gt;&lt;tr&gt;&lt;td&gt;
+      &lt;ul&gt;
+    &lt;li&gt;&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;
+
+    &lt;li&gt;&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;
+
+    &lt;li&gt;&lt;font size="+2"&gt;Hello Joe!&lt;/font&gt;
+
+  &lt;/ul&gt;
+
+  &lt;/tr&gt;&lt;/td&gt;&lt;/table&gt;</programlisting>
+
+          <para>The <link linkend="dgui_misc_var">local variables</link> of a
+          macro are not visible in the nested content. Say, this:</para>
+
+          <programlisting role="template">&lt;#macro repeat count&gt;
+  &lt;#local y = "test"&gt;
+  &lt;#list 1..count as x&gt;
+    ${y} ${count}/${x}: &lt;#nested&gt;
+  &lt;/#list&gt;
+&lt;/#macro&gt;
+&lt;@repeat count=3&gt;${y!"?"} ${x!"?"} ${count!"?"}&lt;/@repeat&gt;</programlisting>
+
+          <para>will print this:</para>
+
+          <programlisting role="output">    test 3/1: ? ? ?
+    test 3/2: ? ? ?
+    test 3/3: ? ? ?</programlisting>
+
+          <para>because the <literal>y</literal>, <literal>x</literal> and
+          <literal>count</literal> are the local (private) variables of the
+          macro, and are not visible from outside the macro definition.
+          Furthermore, a different set of local variables is used for each
+          macro call, so this will not cause confusion:</para>
+
+          <programlisting role="template">&lt;#macro test foo&gt;${foo} (&lt;#nested&gt;) ${foo}&lt;/#macro&gt;
+&lt;@test foo="A"&gt;&lt;@test foo="B"&gt;&lt;@test foo="C"/&gt;&lt;/@test&gt;&lt;/@test&gt;
+</programlisting>
+
+          <para>and will print this:</para>
+
+          <programlisting role="output">A (B (C () C) B) A</programlisting>
+        </section>
+
+        <section xml:id="dgui_misc_userdefdir_loopvar">
+          <title>Macros with loop variables</title>
+
+          <indexterm>
+            <primary>loop variable</primary>
+          </indexterm>
+
+          <para>Predefined directives like <literal>list</literal> can use
+          so-called loop variables; you should read <xref
+          linkend="dgui_misc_var"/> to understand loop variables.</para>
+
+          <para>User-defined directives can also have loop variables. For
+          example, let's extend the <literal>do_thrice</literal> directive of
+          the earlier examples so it exposes the current repetition number as
+          a loop variable. As with the predefined directives (as
+          <literal>list</literal>) the <emphasis>name</emphasis> of loop
+          variables is given when you call the directive (as
+          <literal>foo</literal> in <literal>&lt;#list foos as
+          foo&gt;<replaceable>...</replaceable>&lt;/#list&gt;</literal>),
+          while the <emphasis>value</emphasis> of the variables is set by the
+          directive itself.</para>
+
+          <programlisting role="template">&lt;#macro do_thrice&gt;
+  &lt;#nested <emphasis>1</emphasis>&gt;
+  &lt;#nested <emphasis>2</emphasis>&gt;
+  &lt;#nested <emphasis>3</emphasis>&gt;
+&lt;/#macro&gt;
+&lt;@do_thrice <emphasis>; x</emphasis>&gt; &lt;#-- user-defined directive uses ";" instead of "as" --&gt;
+  ${<emphasis>x</emphasis>} Anything.
+&lt;/@do_thrice&gt;</programlisting>
+
+          <para>This will print:</para>
+
+          <programlisting role="output">  1 Anything.
+  2 Anything.
+  3 Anything.
+ </programlisting>
+
+          <para>The syntactical rule is that you pass the actual value of the
+          loop variable for a certain "loop" (i.e. repetition of the nested
+          content) as the parameter of <literal>nested</literal> directive (of
+          course the parameter can by arbitrary expression). The name of the
+          loop variable is specified in the user-defined directive open tag
+          (<literal>&lt;@...&gt;</literal>) after the parameters and a
+          semicolon.</para>
+
+          <para>A macro can use more the one loop variable (the order of
+          variables is significant):</para>
+
+          <programlisting role="template">&lt;#macro repeat count&gt;
+  &lt;#list 1..count as x&gt;
+    &lt;#nested <emphasis>x, x/2, x==count</emphasis>&gt;
+  &lt;/#list&gt;
+&lt;/#macro&gt;
+&lt;@repeat count=4 ; <emphasis>c, halfc, last</emphasis>&gt;
+  ${<emphasis>c</emphasis>}. ${<emphasis>halfc</emphasis>}&lt;#if <emphasis>last</emphasis>&gt; Last!&lt;/#if&gt;
+&lt;/@repeat&gt;</programlisting>
+
+          <para>The output will be:</para>
+
+          <programlisting role="output">  1. 0.5
+  2. 1
+  3. 1.5
+  4. 2 Last!
+ </programlisting>
+
+          <para>It is not a problem if you specify different number of loop
+          variables in the user-defined directive start-tag (that is, after
+          the semicolon) than with the <literal>nested</literal> directive. If
+          you specify less loop variables after the semicolon, then simply you
+          will not see the last few values that the <literal>nested</literal>
+          directive provides, since there is no loop variable to hold those
+          values. So these are all OK:</para>
+
+          <programlisting role="template">&lt;@repeat count=4 ; <emphasis>c, halfc, last</emphasis>&gt;
+  ${c}. ${halfc}&lt;#if last&gt; Last!&lt;/#if&gt;
+&lt;/@repeat&gt;
+&lt;@repeat count=4 ; <emphasis>c, halfc</emphasis>&gt;
+  ${c}. ${halfc}
+&lt;/@repeat&gt;
+&lt;@repeat count=4&gt;
+  Just repeat it...
+&lt;/@repeat&gt;</programlisting>
+
+          <para>If you specify more variables after the semicolon than with
+          the <literal>nested</literal> directive, then the last few loop
+          variables will not be created (i.e. will be undefined in the nested
+          content).</para>
+        </section>
+
+        <section>
+          <title>More about user-defined directives and macros</title>
+
+          <para>Now you may read the relevant parts of the FreeMarker
+          Reference:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para><link linkend="ref.directive.userDefined">user-defined
+              directive call</link></para>
+            </listitem>
+
+            <listitem>
+              <para><link
+              linkend="ref.directive.macro"><literal>macro</literal>
+              directive</link></para>
+            </listitem>
+          </itemizedlist>
+
+          <para>You can define methods in FTL as well, see <link
+          linkend="ref.directive.function">the <literal>function</literal>
+          directive</link>.</para>
+
+          <para>Also, you may interested in namespaces: <xref
+          linkend="dgui_misc_namespace"/>. Namespaces help you to organize and
+          reuse your commonly used macros.</para>
+
+          <para>Java programmers might want to know that directives (macros
+          are directives) and methods (function-like things) can also be
+          written in Java language, by<link
+          linkend="pgui_datamodel_directive"> implementing the
+          <literal>TemplateDirectiveModel</literal></link> or
+          <literal>TemplateMethodModelEx</literal> interfaces, respectively.
+          Then you can pull in the Java implementations into the template like
+          <literal>&lt;#assign foo =
+          "com.example.FooDirective"?new()&gt;</literal> or
+          <literal>&lt;#assign foo =
+          "com.example.FooMethod"?new()&gt;</literal> on the same place where
+          you would have <literal>&lt;#macro foo
+          <replaceable>...</replaceable>&gt;</literal> or
+          <literal>&lt;#function foo
+          <replaceable>...</replaceable>&gt;</literal> otherwise.</para>
+        </section>
+      </section>
+
+      <section xml:id="dgui_misc_var">
+        <title>Defining variables in the template</title>
+
+        <indexterm>
+          <primary>variable</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>loop variable</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>local variable</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>temporary variable</primary>
+        </indexterm>
+
+        <para>Most of the variables that a typical template works with comes
+        from the data-model. But templates can also define variables
+        themselves, usually to hold loops variables, temporary results,
+        macros, etc. Such variables are outside the data-model; modifying the
+        data-model from templates is by design unsupported. Note that each
+        <link linkend="gloss.templateProcessingJob">template processing
+        job</link> has its own private set of these variables, which will be
+        thrown away when the template processing job is finished.</para>
+
+        <para>You access variables defined in the template the same way as you
+        access variables defined in the data-model root. For example, if you
+        create a variable called <quote>foo</quote> in the template, you can
+        print its value with <literal>${foo}</literal>. If, coincidently,
+        there's a variable called <quote>foo</quote> in the data-model too,
+        the variable created in the template will hide (not overwrite!)
+        it.</para>
+
+        <para>There are these kinds of variables that are defined in a
+        template:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><emphasis role="term"><quote>plain</quote>
+            variables</emphasis>: They are accessible from everywhere in the
+            template, or from another templates that was inserted with the
+            <link linkend="ref.directive.include"><literal>include</literal>
+            directive</link>. You can create and replace these variables with
+            the <link linkend="ref.directive.assign"><link
+            linkend="ref.directive.assign"><literal>assign</literal></link>
+            directive</link>, or, because macros and functions are just
+            variables, with the <link
+            linkend="ref.directive.macro"><literal>macro</literal>
+            directives</link> and <link
+            linkend="ref.directive.function"><literal>function</literal>
+            directives</link>.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Local variables</emphasis>: They can
+            only be set inside a <link
+            linkend="gloss.macroDefinitionBody">macro definition body</link>
+            or <link linkend="gloss.functionDefinitionBody">function
+            definition body</link>, and are only visible from there, not from
+            other macros or functions called from there. A local variable only
+            exists for the duration of a macro or function call. You can
+            create and replace local variables inside the definition body with
+            the <link linkend="ref.directive.local"><literal>local</literal>
+            directive</link>. <link linkend="ref.directive.macro">Macro</link>
+            and <link linkend="ref.directive.function">function</link>
+            parameters are also local variables.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Loop variables</emphasis>: Loop
+            variables are created automatically by directives like <link
+            linkend="ref.directive.list"><literal>list</literal></link> (like
+            <literal>x</literal> in <literal>&lt;#list xs as
+            x&gt;<replaceable>...</replaceable>&lt;/#list&gt;</literal>), and
+            they only exist between the start-tag and end-tag of the
+            directive. (User defined directives, like macros, can also create
+            loop variables.) They are only visible directly between these
+            tags, not from macros or functions called from there. As such,
+            they are quite similar to local variables, but they can't be
+            assigned to directly.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Global variables</emphasis>: These
+            should be seldom used. Global variables are shared by all
+            templates, even if they belong to different name spaces because of
+            <link
+            linkend="ref.directive.import"><literal>import</literal>-ing</link>.
+            Thus, their visibility is similar to data-model variables. They
+            are set via the <link
+            linkend="ref.directive.global"><literal>global</literal>
+            directive</link>. Global variables hide (but don't overwrite) the
+            data-model variables of the same name.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Example: Create and replace variables with
+        <literal>assign</literal>:</para>
+
+        <programlisting role="template">&lt;#assign x = 1&gt;  &lt;#-- create variable x --&gt;
+${x}
+&lt;#assign x = 2&gt; &lt;#-- replace variable x --&gt;
+${x}
+&lt;#assign x++&gt; &lt;#-- replace variable x --&gt;
+${x}</programlisting>
+
+        <programlisting role="output">1
+2
+3</programlisting>
+
+        <para>In the next example we demonstrate that local variables hide
+        (not overwrite) <quote>plain</quote> variables of the same name, and
+        that loop variables hide (not overwrite) local and
+        <quote>plain</quote> variables of the same name:</para>
+
+        <programlisting role="template">&lt;#assign x = "plain"&gt;
+1. ${x}  &lt;#-- we see the plain var. here --&gt;
+&lt;@test/&gt;
+6. ${x}  &lt;#-- the value of plain var. was not changed --&gt;
+&lt;#list ["loop"] as x&gt;
+    7. ${x}  &lt;#-- now the loop var. hides the plain var. --&gt;
+    &lt;#assign x = "plain2"&gt; &lt;#-- replaces the plain var, not the loop var. --&gt;
+    8. ${x}  &lt;#-- it still hides the plain var. --&gt;
+&lt;/#list&gt;
+9. ${x}  &lt;#-- now the new value of plain var. becomse visible --&gt;
+
+&lt;#macro test&gt;
+  2. ${x}  &lt;#-- we still see the plain var. here --&gt;
+  &lt;#local x = "local"&gt;
+  3. ${x}  &lt;#-- now the local var. hides it --&gt;
+  &lt;#list ["loop"] as x&gt;
+    4. ${x}  &lt;#-- now the loop var. hides the local var. --&gt;
+  &lt;/#list&gt;
+  5. ${x}  &lt;#-- now we see the local var. again --&gt;
+&lt;/#macro&gt;</programlisting>
+
+        <programlisting role="output">1. plain
+  2. plain
+  3. local
+    4. loop
+  5. local
+6. plain
+    7. loop
+    8. loop
+9. plain2 </programlisting>
+
+        <para>In the next example we demonstrate that an inner loop variable
+        can hide (not overwrite) an outer loop variable of the same
+        name:</para>
+
+        <programlisting role="template">&lt;#list ["loop 1"] as x&gt;
+  ${x}
+  &lt;#list ["loop 2"] as x&gt;
+    ${x}
+    &lt;#list ["loop 3"] as x&gt;
+      ${x}
+    &lt;/#list&gt;
+    ${x}
+  &lt;/#list&gt;
+  ${x}
+&lt;/#list&gt;</programlisting>
+
+        <programlisting role="output">  loop 1
+    loop 2
+      loop 3
+    loop 2
+  loop 1</programlisting>
+
+        <para>When a variable hides the variable from the data-model, you can
+        still read that variable from the data-model using <link
+        linkend="dgui_template_exp_var_special">special variable</link>
+        <literal>globals</literal>. For example, assume we have a variable
+        called <literal>user</literal> in the data-model with value <quote>Big
+        Joe</quote>:</para>
+
+        <programlisting role="template">${user}          &lt;#-- prints: Big Joe --&gt;
+&lt;#assign user = "Joe Hider"&gt;
+${user}          &lt;#-- prints: Joe Hider --&gt;
+${.globals.user} &lt;#-- prints: Big Joe --&gt;</programlisting>
+
+        <para>You could also write <literal>.data_model.user</literal>
+        instead, and then not even a <literal>&lt;#global user =
+        "<replaceable>...</replaceable>"&gt;</literal> can hide the value in
+        the data-model. However, global variables are often purposely set to
+        override the value coming from the data-model, so using
+        <literal>globals</literal> is a better practice usually.</para>
+
+        <para>For information about syntax of variables (allowed characters
+        and such) please read: <xref linkend="dgui_template_exp"/></para>
+      </section>
+
+      <section xml:id="dgui_misc_namespace">
+        <title>Namespaces</title>
+
+        <indexterm>
+          <primary>namespaces</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>libraries</primary>
+        </indexterm>
+
+        <para>When you run templates, you have a (possibly empty) set of
+        variables that you have created with <literal>assign</literal> and
+        <literal>macro</literal> and <literal>function</literal> directives
+        (see in the <link linkend="dgui_misc_var">previous chapter</link>). A
+        set of template-made variables like that is called a <emphasis
+        role="term">namespace</emphasis>. In simple cases you use only one
+        namespace, the <emphasis role="term">main namespace</emphasis>.
+        Whenever you define a variable in the main template (macros and
+        functions are also variables, mind you), or in templates <link
+        linkend="ref.directive.include"><literal>include</literal>-d</link> in
+        it, that's where the variable are created. The key property of a
+        namespace is that the variable name uniquely identifies a value in it
+        (i.e, you can't have multiple variables in it with the same name in
+        the same namespace).</para>
+
+        <para>Sometimes you want to build reusable collection of macros,
+        functions, and other variables, which we call a <emphasis
+        role="term">library</emphasis>. It's important that a library can use
+        its own namespace, to avoid accidental name clashes. Consider, you may
+        have many names in that library, and you intend to use the library in
+        many templates, maybe even reuse it in several projects. It becomes
+        impractical to keep track of where the library used in another
+        template accidentally hides variables from the data-model, or what
+        names you shouldn't assign to in the template to avoid overwriting the
+        variables of the library. If you have multiple libraries used in the
+        same template, this becomes even harder to track. So you should use a
+        separate namespace for the variables of each library.</para>
+
+        <section>
+          <title>Creating a library</title>
+
+          <para>Here's a simple library, which contains a
+          <literal>copyright</literal> macro and a <literal>mail</literal>
+          string:</para>
+
+          <programlisting role="template">&lt;#macro copyright date&gt;
+  &lt;p&gt;Copyright (C) ${date} Someone. All rights reserved.&lt;/p&gt;
+&lt;/#macro&gt;
+
+&lt;#assign mail = "user@example.com"&gt;</programlisting>
+
+          <para>Save this into the <literal>lib/example.ftl</literal> file
+          (inside the directory where you store the templates). Then create a
+          template, let's say, <literal>some_web_page.ftl</literal>, and use
+          the library in it:</para>
+
+          <programlisting role="template">&lt;#<emphasis>import</emphasis> "/lib/example.ftl" as <emphasis>e</emphasis>&gt;
+
+Some Web page...
+&lt;@<emphasis>e</emphasis>.copyright date="1999-2002"/&gt;
+${<emphasis>e</emphasis>.mail}</programlisting>
+
+          <programlisting role="output">Some Web page...
+  &lt;p&gt;Copyright (C) 1999-2002 Someone. All rights reserved.&lt;/p&gt;
+user@example.com</programlisting>
+
+          <para>Note the <link
+          linkend="ref.directive.import"><literal>import</literal>
+          directive</link> above, and the subsequent usage of the
+          <quote><literal>e</literal></quote> variable.
+          <literal>import</literal> is similar to the perhaps already familiar
+          <link linkend="ref.directive.include"><literal>include</literal>
+          directive</link>, but it will create an empty namespace and will run
+          <literal>lib/example.ftl</literal> in that namespace. So
+          <literal>lib/example.ftl</literal> will find itself in a clean
+          world, where only the variables of the data-models are visible (and
+          the globals), and will create its two variables
+          (<literal>copyright</literal> and <literal>mail</literal>) in this
+          clean namespace. But you will need to access those two variables
+          from another namespace (the main namespace), thus, the
+          <literal>import</literal> directive creates a hash variable
+          (<literal>e</literal> in this case) to access the namespace it has
+          created . That variable is in the namespace that the
+          <literal>import</literal>-ing template uses, and acts as a window to
+          the namespace of the imported library.</para>
+
+          <para>To demonstrate that the two namespaces are separate, consider
+          the example below. Replace <literal>lib/example.ftl</literal> with
+          this:</para>
+
+          <programlisting role="template">&lt;#macro copyright date&gt;
+  &lt;p&gt;Copyright (C) ${date} Someone. All rights reserved.
+  &lt;br&gt;Email: <emphasis>${mail}</emphasis>&lt;/p&gt;
+&lt;/#macro&gt;
+
+&lt;#assign mail = "user@example.com"&gt;</programlisting>
+
+          <para>and <literal>some_web_page.ftl</literal> with this:</para>
+
+          <programlisting role="template">&lt;#import "/lib/example.ftl" as e&gt;
+<emphasis>&lt;#assign mail="other@example.com"&gt;</emphasis>
+&lt;@e.copyright date="1999-2002"/&gt;
+${e.mail}
+${mail}</programlisting>
+
+          <programlisting role="output">  &lt;p&gt;Copyright (C) 1999-2002 Someone. All rights reserved.
+  &lt;br&gt;Email: <emphasis>user@example.com</emphasis>&lt;/p&gt;
+user@example.com
+other@example.com</programlisting>
+
+          <para>As you can see, the <literal>mail</literal> variable assigned
+          in <literal>some_web_page.ftl</literal> is separate from the
+          <literal>mail</literal> variable assigned in the imported
+          library.</para>
+        </section>
+
+        <section>
+          <title>Writing the variables of imported namespaces</title>
+
+          <para>Sometimes you want to create or replace a variable in an
+          imported namespace. You can do that with the
+          <literal>assign</literal> directive and its
+          <literal>namespace</literal> parameter:</para>
+
+          <programlisting role="template">&lt;#import "/lib/example.ftl" as e&gt;
+${e.mail}
+&lt;#assign mail="other@example.com" <emphasis>in e</emphasis>&gt;
+${e.mail}</programlisting>
+
+          <programlisting role="output">user@example.com
+other@example.com</programlisting>
+        </section>
+
+        <section>
+          <title>Namespaces and data-model</title>
+
+          <para>The variables of the data-model are visible from everywhere.
+          For example, if you have a variable called <literal>user</literal>
+          in the data-model, <literal>lib/example.ftl</literal> will access
+          that, exactly like <literal>some_web_page.ftl</literal> does:</para>
+
+          <programlisting role="template">&lt;#macro copyright date&gt;
+  &lt;p&gt;Copyright (C) ${date} <emphasis>${user}</emphasis>. All rights reserved.&lt;/p&gt;
+&lt;/#macro&gt;</programlisting>
+
+          <para>Assuming <literal>user</literal> is <quote>John
+          Doe</quote>:</para>
+
+          <programlisting role="template">&lt;#import "/lib/my_test.ftl" as my&gt;
+User is: ${user}
+&lt;@my.copyright date="1999-2002"/&gt;
+</programlisting>
+
+          <programlisting role="output">User is: John Doe
+  &lt;p&gt;Copyright (C) 1999-2002 John Doe. All rights reserved.&lt;/p&gt;
+</programlisting>
+
+          <para>Don't forget that the variables in the namespace (the
+          variables you create with <literal>assign</literal>,
+          <literal>macro</literal>, and <literal>function</literal>
+          directives) have precedence over the variables of the data-model
+          when you are in that namespace. So generally, if a library is
+          interested in a data-model variable, it doesn't assign to the same
+          name.</para>
+
+          <note>
+            <para>In some unusual applications you want to create variables in
+            the template that are visible from all namespaces, exactly like
+            the variables of the data-model. While templates can't change the
+            data-model, it's possible to achieve similar effect with the
+            <literal>global</literal> directive; see the <link
+            linkend="ref.directive.global">reference</link>.</para>
+          </note>
+        </section>
+
+        <section>
+          <title>The life-cycle of namespaces</title>
+
+          <para>A namespace is identified by the path used in the
+          <literal>import</literal> directive (after it was normalized to an
+          absolute path). If you try to <literal>import</literal> with
+          equivalent paths for multiple times, it will create the namespace
+          and run the template for only the first invocation of
+          <literal>import</literal>. The later <literal>import</literal>-s
+          with equivalent paths will just assign the same namespace to the
+          variable specified after the <literal>as</literal> keyword. For
+          example:</para>
+
+          <programlisting role="template">&lt;#import "/lib/example.ftl" as e&gt;
+&lt;#import "/lib/example.ftl" as e2&gt;
+&lt;#import "/lib/example.ftl" as e3&gt;
+${e.mail}, ${e2.mail}, ${e3.mail}
+&lt;#assign mail="other@example.com" in e&gt;
+${e.mail}, ${e2.mail}, ${e3.mail}</programlisting>
+
+          <programlisting role="output">user@example.com, user@example.com, user@example.com
+other@example.com, other@example.com, other@example.com</programlisting>
+
+          <para>As you access the same namespace through <literal>e</literal>,
+          <literal>e2</literal>, and <literal>e3</literal>, the
+          <literal>email</literal> has changed in all of them at once. The
+          practical importance of this is that when you import the same
+          library in multiple templates, only one namespace will be
+          initialized and created for the library, which will be shared by all
+          the importing templates.</para>
+
+          <para>Note that namespaces are not hierarchical; it doesn't mater
+          what namespace are you in when <literal>import</literal> creates
+          another namespace. For example, when you <literal>import</literal>
+          namespace N2 while you are in name space N1, N2 will not be inside
+          N1. N1 just gets the same N2 that you get if you
+          <literal>import</literal> N2 when you are in the main
+          namespace.</para>
+
+          <para>Each <link linkend="gloss.templateProcessingJob">template
+          processing job</link> has its own private set of namespaces. Each
+          template processing job is a separate universe that exists only for
+          the short period while the main template is rendered, and then it
+          vanishes with all its populated namespaces. Thus, whenever we say
+          that <quote><literal>import</literal> is called for the first
+          time</quote>, we always mean the first time within the lifespan of a
+          single template processing job.</para>
+        </section>
+
+        <section>
+          <title>Auto-importing</title>
+
+          <para>When you have to import the same libraries again and again in
+          many templates, know that the Java programmers (or whoever is
+          responsible for configuring FreeMarker) can specify auto-imports,
+          which are imports that are automatically done in all templates. Auto
+          imports can also be configured to be <quote>lazy</quote> (since
+          FreeMarker 2.3.25), which means that they are only done when the
+          imported library is actually used in the template. See the Java API
+          documentation for more details: <link
+          xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setAutoImports-java.util.Map-">Configuration.setAutoImports</link>,
+          <link
+          xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setLazyAutoImports-java.lang.Boolean-">Configuration.setLazyAutoImports</link>.</para>
+        </section>
+      </section>
+
+      <section xml:id="dgui_misc_autoescaping">
+        <title>Auto-escaping and output formats</title>
+
+        <indexterm>
+          <primary>escaping</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>auto-escaping</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>MIME type</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>HTML escaping</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>HTML encoding</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>XML escaping</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>XML encoding</primary>
+        </indexterm>
+
+        <para>This is a <emphasis>detailed</emphasis> tutorial to
+        auto-escaping and related concepts; for the bare minimum, <link
+        linkend="dgui_quickstart_template_autoescaping">read this
+        instead</link>.</para>
+
+        <note>
+          <para>The kind of automatic escaping described here requires at
+          least FreeMarker 2.3.24. If you have to use an earlier version, use
+          the deprecated <link
+          linkend="ref_directive_escape"><literal>escape</literal>
+          directive</link> instead.</para>
+        </note>
+
+        <section xml:id="dgui_misc_autoescaping_outputformat">
+          <title>Output formats</title>
+
+          <indexterm>
+            <primary>output format</primary>
+          </indexterm>
+
+          <para>Each template has an associated output format <phrase
+          role="forProgrammers">(a
+          <literal>freemarker.core.OutputFormat</literal> instance)</phrase>.
+          The output format dictates the escaping rules, which is applied on
+          all <literal>${<replaceable>...</replaceable>}</literal>-s (and
+          <literal>#{<replaceable>...</replaceable>}</literal>-s) that aren't
+          <link linkend="dgui_misc_autoescaping_stringliteral">inside a string
+          literal</link>. It also specifies a MIME type (e.g.
+          <literal>"text/HTML"</literal>) and a canonical name (e.g.
+          <literal>"HTML"</literal>) that the embedding application/framework
+          can use for its own purposes.</para>
+
+          <para>It's the programmer's responsibility to <link
+          linkend="pgui_config_outputformatsautoesc">associate output format
+          to templates</link>. Furthermore it's recommended that FreeMarker is
+          configured so that templates with <literal>ftlh</literal> and
+          <literal>ftlx</literal> file extensions are automatically associated
+          with the HTML and XML output formats, respectively.</para>
+
+          <para xml:id="topic.predefinedOutputFormats">The predefined output
+          formats are:</para>
+
+          <informaltable border="1">
+            <thead>
+              <tr>
+                <th>Name</th>
+
+                <th>Description</th>
+
+                <th>MIME Type</th>
+
+                <th>Default implementation
+                (<literal>freemarker.core.*</literal>)</th>
+              </tr>
+            </thead>
+
+            <tbody>
+              <tr>
+                <td><literal>HTML</literal></td>
+
+                <td>Escapes <literal>&lt;</literal>, <literal>&gt;</literal>,
+                <literal>&amp;</literal>, <literal>"</literal>,
+                <literal>'</literal> as <literal>&amp;lt;</literal>,
+                <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;quot;</literal>,
+                <literal>&amp;#39;</literal></td>
+
+                <td><literal>text/html</literal></td>
+
+                <td><literal>HTMLOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>XHTML</literal></td>
+
+                <td>Escapes <literal>&lt;</literal>, <literal>&gt;</literal>,
+                <literal>&amp;</literal>, <literal>"</literal>,
+                <literal>'</literal> as <literal>&amp;lt;</literal>,
+                <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;quot;</literal>,
+                <literal>&amp;#39;</literal></td>
+
+                <td><literal>application/xhtml+xml</literal></td>
+
+                <td><literal>XHTMLOutputFormat.INSTANCE</literal></td>
+              </tr>
+            </tbody>
+
+            <tbody>
+              <tr>
+                <td><literal>XML</literal></td>
+
+                <td>Escapes <literal>&lt;</literal>, <literal>&gt;</literal>,
+                <literal>&amp;</literal>, <literal>"</literal>,
+                <literal>'</literal> as <literal>&amp;lt;</literal>,
+                <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;quot;</literal>,
+                <literal>&amp;apos;</literal></td>
+
+                <td><literal>application/xml</literal></td>
+
+                <td><literal>XMLOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>RTF</literal></td>
+
+                <td>Escapes <literal>{</literal>, <literal>}</literal>,
+                <literal>\</literal> as <literal>\{</literal>,
+                <literal>\}</literal>, <literal>\\</literal></td>
+
+                <td><literal>application/rtf</literal></td>
+
+                <td><literal>RTFOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>undefined</literal></td>
+
+                <td>Doesn't escape. Prints markup output values (concept
+                explained <link
+                linkend="dgui_misc_autoescaping_movalues">later</link>) from
+                other output formats as is. The default output format used
+                when no output format was explicitly set in the
+                configuration.</td>
+
+                <td>None (<literal>null</literal>)</td>
+
+                <td><literal>UndefinedOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>plainText</literal></td>
+
+                <td>Doesn't escape.</td>
+
+                <td><literal>text/plain</literal></td>
+
+                <td><literal>PlainTextOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>JavaScript</literal></td>
+
+                <td>Doesn't escape.</td>
+
+                <td><literal>application/javascript</literal></td>
+
+                <td><literal>JavaScriptOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>JSON</literal></td>
+
+                <td>Doesn't escape.</td>
+
+                <td><literal>application/json</literal></td>
+
+                <td><literal>JSONOutputFormat.INSTANCE</literal></td>
+              </tr>
+
+              <tr>
+                <td><literal>CSS</literal></td>
+
+                <td>Doesn't escape.</td>
+
+                <td><literal>text/css</literal></td>
+
+                <td><literal>CSSOutputFormat.INSTANCE</literal></td>
+              </tr>
+            </tbody>
+          </informaltable>
+
+          <para>The programmers can add their your own output formats, so this
+          is maybe not all the output formats in your application!</para>
+        </section>
+
+        <section xml:id="dgui_misc_autoescaping_overrideoformat">
+          <title>Overriding the output format in templates</title>
+
+          <para>Especially in legacy applications, you will often find that
+          the output format is <literal>undefined</literal> (you can check
+          that with <literal>${.output_format}</literal>), and so no automatic
+          escaping is happening. In other cases, a common output format (like
+          HTML) is set for all templates, but a few templates need a different
+          output format. In any case, the output format of a template can be
+          enforced in the <link linkend="ref_directive_ftl">the
+          <literal>ftl</literal> header</link>:</para>
+
+          <programlisting role="template">&lt;#ftl output_format="XML"&gt;
+${"'"}  &lt;#-- Prints: &amp;apos; --&gt;</programlisting>
+
+          <para>Above, the output format was referred by its name shown in the
+          earlier table <emphasis role="forProgrammers">(looked up via
+          <literal>Configuration.getOutputFormat(String name)</literal>,
+          actually)</emphasis>.</para>
+
+          <note>
+            <para>If escaping doesn't happen after adding the above
+            <literal>ftl</literal> header, then <literal>&lt;#ftl
+            output_format="XML" auto_esc=true&gt;</literal> might helps (and
+            that means that FreeMarker was configured to use
+            <quote>disable</quote> auto-escaping <emphasis>policy</emphasis>,
+            which is generally not recommended).</para>
+          </note>
+
+          <para>The output format can also be applied to only a section of a
+          template, like:</para>
+
+          <programlisting role="template">&lt;#-- Let's assume we have "HTML" output format by default. --&gt;
+${"'"}  &lt;#-- Prints: &amp;#39; --&gt;
+&lt;#outputformat "XML"&gt;
+  ${"'"}  &lt;#-- Prints: &amp;apos; --&gt;
+&lt;/#outputformat&gt;
+${"'"}  &lt;#-- Prints: &amp;#39; --&gt;
+</programlisting>
+
+          <para>Basically, each position in a template has an associated
+          output format, and as you saw above, it might not be the same
+          everywhere in the template. This association sticks to the positions
+          and won't change as the template executes. So if, for example, you
+          call a macro from inside an <literal>outputformat</literal> block
+          and the called macro is defined outside that block, it won't get the
+          output format of it. Or, if you have a macro that's defined in a
+          template with HTML output format, no mater from where you call it,
+          that macro will always execute with HTML output format. This is like
+          if you were coloring each characters of the template files by output
+          format in the text editor, and then later when the templates are
+          executed, it only considers the color of the statement being
+          executed. This gives you firm control over the output format and
+          hence escaping; you don't have to consider the possible execution
+          paths that can lead to a point.</para>
+        </section>
+
+        <section xml:id="dgui_misc_autoescaping_disableautoesc">
+          <title>Disabling auto escaping</title>
+
+          <para>For a single interpolation you can disable auto-escaping with
+          <link
+          linkend="ref_builtin_no_esc"><literal>?no_esc</literal></link>:</para>
+
+          <programlisting role="template">&lt;#-- Let's assume we have "HTML" output format by default. --&gt;
+${'&lt;b&gt;test&lt;/b&gt;'}  &lt;#-- prints: &amp;lt;b&amp;gt;test&amp;lt;/b&amp;gt; --&gt;
+${'&lt;b&gt;test&lt;/b&gt;'<emphasis>?no_esc</emphasis>}  &lt;#-- prints: &lt;b&gt;test&lt;/b&gt; --&gt;</programlisting>
+
+          <para>You can also disable auto escaping for a whole section with
+          the <link
+          linkend="ref_directive_noautoesc"><literal>noautoesc</literal>
+          directive</link>:</para>
+
+          <programlisting role="template">${'&amp;'}  &lt;#-- prints: &amp;amp; --&gt;
+<emphasis>&lt;#noautoesc&gt;</emphasis>
+  ${'&amp;'}  &lt;#-- prints: &amp; --&gt;
+  ...
+  ${'&amp;'}  &lt;#-- prints: &amp; --&gt;
+<emphasis>&lt;/#noautoesc&gt;</emphasis>
+${'&amp;'}  &lt;#-- prints: &amp;amp; --&gt;</programlisting>
+
+          <para>Just like <literal>outputformat</literal>, this only applies
+          to the part that's literally inside the block
+          (<quote>coloring</quote> logic).</para>
+
+          <para>Auto-escaping can also be disabled for the whole template in
+          the <literal>ftl</literal> header. It can then be re-enabled for a
+          section with the <link
+          linkend="ref_directive_autoesc"><literal>autoesc</literal>
+          directive</link>:</para>
+
+          <programlisting role="template">&lt;#ftl <emphasis>autoesc=false</emphasis>&gt;
+${'&amp;'}  &lt;#-- prints: &amp; --&gt;
+<emphasis>&lt;#autoesc&gt;</emphasis>
+  ${'&amp;'}  &lt;#-- prints: &amp;amp; --&gt;
+  ...
+  ${'&amp;'}  &lt;#-- prints: &amp;amp; --&gt;
+<emphasis>&lt;/#autoesc&gt;</emphasis>
+${'&amp;'}  &lt;#-- prints: &amp; --&gt;</programlisting>
+
+          <para>You can also force escaping for an individual interpolation
+          when escaping is disabled, with <link
+          linkend="ref_builtin_esc"><literal>?esc</literal></link>:</para>
+
+          <programlisting role="template">&lt;#ftl <emphasis>autoesc=false</emphasis>&gt;
+${'&amp;'}  &lt;#-- prints: &amp; --&gt;
+${'&amp;'<emphasis>?esc</emphasis>}  &lt;#-- prints: &amp;amp; --&gt;</programlisting>
+
+          <para>Naturally, both <literal>autoesc</literal> and
+          <literal>?esc</literal> works inside <literal>noautoesc</literal>
+          blocks too.</para>
+        </section>
+
+        <section xml:id="dgui_misc_autoescaping_movalues">
+          <title><quote>Markup output</quote> values</title>
+
+          <para>In FTL, <link linkend="dgui_datamodel_basics">values have
+          type</link>, like string, number, boolean, etc. One such type is
+          called <quote>markup output</quote>. A value of that type is a piece
+          of text that's already in the output format (like HTML), and hence
+          needs no further escaping. We have already produced such values
+          earlier:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal><replaceable>s</replaceable>?esc</literal>
+              creates a markup output value out of a string value by escaping
+              all special characters in it.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal><replaceable>s</replaceable>?no_esc</literal>
+              creates a markup output value out of a string value by assuming
+              that the string already stores markup and so needs no further
+              escaping</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>These can be useful outside
+          <literal>${<replaceable>...</replaceable>}</literal> too. For
+          example, here the caller of the <literal>infoBox</literal> macro can
+          decide if the message is plain text (hence needs escaping) or HTML
+          (hence it mustn't be escaped):</para>
+
+          <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
+
+&lt;@infoBox "Foo &amp; bar" /&gt;
+&lt;@infoBox "Foo &lt;b&gt;bar&lt;/b&gt;"?no_esc /&gt;
+
+&lt;#macro infoBox message&gt;
+  &lt;div class="infoBox"&gt;
+    ${message}
+  &lt;/div&gt;
+&lt;/#macro&gt;</programlisting>
+
+          <programlisting role="output">  &lt;div class="infoBox"&gt;
+    Foo &amp;amp; bar
+  &lt;/div&gt;
+  &lt;div class="infoBox"&gt;
+    Foo &lt;b&gt;bar&lt;/b&gt;
+  &lt;/div&gt;</programlisting>
+
+          <para>Another case where you get a markup output value is output
+          capturing:</para>
+
+          <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
+&lt;#assign captured&gt;&lt;b&gt;Test&lt;/b&gt;&lt;/#assign&gt;
+Just a string: ${"&lt;b&gt;Test&lt;/b&gt;"}
+Captured output: ${captured}</programlisting>
+
+          <programlisting role="output">Just a string: &amp;lt;b&amp;gt;Test&amp;lt;/b&amp;gt;
+Captured output: &lt;b&gt;Test&lt;/b&gt;</programlisting>
+
+          <para>Because the captured output is markup output, it wasn't
+          auto-escaped.</para>
+
+          <para>It's important that markup output values aren't strings, and
+          aren't automatically coerced to strings. Thus
+          <literal>?upper_case</literal>, <literal>?starts_with</literal>
+          etc., will give an error with them. You won't be able to pass them
+          to Java methods for <literal>String</literal> parameters either. But
+          sometimes you need the markup that's behind the value as a string,
+          which you can get as
+          <literal><replaceable>markupOutput</replaceable>?markup_string</literal>.
+          Be sure you know what you are doing though. Applying string
+          operations on markup (as opposed to on plain text) can result in
+          invalid markup. Also there's the danger of unintended double
+          escaping.</para>
+
+          <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
+
+&lt;#assign markupOutput1="&lt;b&gt;Test&lt;/b&gt;"?no_esc&gt;
+&lt;#assign markupOutput2="Foo &amp; bar"?esc&gt;
+
+As expected:
+${markupOutput1}
+${markupOutput2}
+
+Possibly unintended double escaping:
+${markupOutput1?markup_string}
+${markupOutput2?markup_string}</programlisting>
+
+          <programlisting role="output">As expected:
+&lt;b&gt;Test&lt;/b&gt;
+Foo &amp;amp; bar
+
+Possibly unintended double escaping:
+&amp;lt;b&amp;gt;Test&amp;lt;/b&amp;gt;
+Foo &amp;amp;amp; bar</programlisting>
+        </section>
+
+        <section>
+          <title>Further details and tricky cases</title>
+
+          <section xml:id="dgui_misc_autoescaping_nonmarkupof">
+            <title>Non-markup output formats</title>
+
+            <para>An output format is said to be a non-markup format if it
+            defines no escaping rules. Examples of such output formats are the
+            <literal>undefined</literal> format and the
+            <literal>plainText</literal> format.</para>
+
+            <para>These formats produce no <link
+            linkend="dgui_misc_autoescaping_movalues">markup output
+            values</link>, hence you can't use <literal>?esc</literal> or
+            <literal>?no_esc</literal> when they are the current format. You
+            can use output capturing (like <literal>&lt;#assign
+            captured&gt;<replaceable>...</replaceable>&lt;/#assign&gt;</literal>),
+            but the resulting value will be a string, not a markup output
+            value.</para>
+
+            <para>Furthermore, you aren't allowed to use the
+            <literal>autoesc</literal> directive or <literal>&lt;#ftl
+            auto_esc=true&gt;</literal> when the current output format is
+            non-markup.</para>
+
+            <para>Using constructs that aren't supported by the current output
+            format will give <link linkend="gloss.parseTimeError">parse-time
+            error</link>.</para>
+          </section>
+
+          <section xml:id="dgui_misc_autoescaping_mixingoutputformats">
+            <title>Inserting markup output values from other markups</title>
+
+            <para>Each <link linkend="dgui_misc_autoescaping_movalues">markup
+            output value</link> has an associated <link
+            linkend="dgui_misc_autoescaping_outputformat">output
+            format</link>. When a markup output value is inserted with
+            <literal>${<replaceable>...</replaceable>}</literal> (or
+            <literal>#{<replaceable>...</replaceable>}</literal>), it has to
+            be converted to the current output format at the point of
+            insertion (if they differ). As of this writing (2.3.24), such
+            output format conversion will only be successful if the value to
+            convert was created by escaping plain text:</para>
+
+            <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
+
+&lt;#assign mo1 = "Foo's bar {}"?esc&gt;
+HTML: ${mo1}
+XML:  &lt;#outputformat 'XML'&gt;${mo1}&lt;/#outputformat&gt;
+RTF:  &lt;#outputformat 'RTF'&gt;${mo1}&lt;/#outputformat&gt;
+
+&lt;#assign mo2&gt;&lt;p&gt;Test&lt;/#assign&gt;
+HTML: ${mo2}
+XML:  &lt;#attempt&gt;&lt;#outputformat 'XML'&gt;${mo2}&lt;/#outputformat&gt;&lt;#recover&gt;Failed&lt;/#attempt&gt;
+RTF:  &lt;#attempt&gt;&lt;#outputformat 'RTF'&gt;${mo2}&lt;/#outputformat&gt;&lt;#recover&gt;Failed&lt;/#attempt&gt;</programlisting>
+
+            <programlisting role="output">HTML: Foo&amp;#39;s bar {}
+XML:  Foo&amp;apos;s bar {}
+RTF:  Foo's bar \{\}
+
+HTML: &lt;p&gt;Test
+XML:  Failed
+RTF:  Failed</programlisting>
+
+            <para>But, an output format can also chose to insert pieces of
+            other output formats as is, without converting them. Among the
+            standard output formats, <literal>undefined</literal> is like
+            that, which is the output format used for templates for which no
+            output format was specified in the configuration:</para>
+
+            <programlisting role="template">&lt;#-- We assume that we have "undefined" output format here. --&gt;
+
+&lt;#outputformat "HTML"&gt;&lt;#assign htmlMO&gt;&lt;p&gt;Test&lt;/#assign&gt;&lt;/#outputformat&gt;
+&lt;#outputformat "XML"&gt;&lt;#assign xmlMO&gt;&lt;p&gt;Test&lt;/p&gt;&lt;/#assign&gt;&lt;/#outputformat&gt;
+&lt;#outputformat "RTF"&gt;&lt;#assign rtfMO&gt;\par Test&lt;/#assign&gt;&lt;/#outputformat&gt;
+HTML: ${htmlMO}
+XML:  ${xmlMO}
+RTF:  ${rtfMO}</programlisting>
+
+            <programlisting role="output">HTML: &lt;p&gt;Test
+XML:  &lt;p&gt;Test&lt;/p&gt;
+RTF:  \par Test</programlisting>
+          </section>
+
+          <section xml:id="dgui_misc_autoescaping_concatenation">
+            <title>Markup output values and the <quote>+</quote>
+            operator</title>
+
+            <para>As you certainly know, if one of the sides of the
+            <literal>+</literal> operator is a string then <link
+            linkend="dgui_template_exp_stringop_concatenation">it does
+            concatenation</link>. If there's a <link
+            linkend="dgui_misc_autoescaping_movalues">markup output
+            value</link> in one side, the other side gets promoted to markup
+            output value of the same output format (if it's not already that),
+            by escaping its string value, and finally the two markups are
+            concatenated to form a new markup output value. Example:</para>
+
+            <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
+${"&lt;h1&gt;"?no_esc + "Foo &amp; bar" + "&lt;/h1&gt;"?no_esc}</programlisting>
+
+            <programlisting role="output">&lt;h1&gt;Foo &amp;amp; bar&lt;/h1&gt;</programlisting>
+
+            <para>If the two sides of the <literal>+</literal> operator are
+            markup values of different output formats, the right side operand
+            is converted to the output format of the left side. If that's not
+            possible, then the left side operand is converted to the output
+            format of the right side. If that isn't possible either, that's an
+            error. (See the <link
+            linkend="dgui_misc_autoescaping_mixingoutputformats">limitations
+            of conversions here</link>.)</para>
+          </section>
+
+          <section xml:id="dgui_misc_autoescaping_stringliteral">
+            <title>${...} inside string literals</title>
+
+            <para>When <literal>${<replaceable>...</replaceable>}</literal> is
+            used inside string <emphasis>expressions</emphasis> (e.g., in
+            <literal>&lt;#assign s = "Hello ${name}!"&gt;</literal>), it's
+            just a shorthand of using the <literal>+</literal> operator
+            (<literal>&lt;#assign s = "Hello" + name + "!"&gt;</literal>).
+            Thus, <literal>${<replaceable>...</replaceable>}</literal>-s
+            inside string expressions aren't auto-escaped, but of course when
+            the resulting concatenated string is printed later, it will be
+            possibly auto-escaped.</para>
+
+            <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
+&lt;#assign name = "Foo &amp; Bar"&gt;
+
+&lt;#assign s = "&lt;p&gt;Hello ${name}!"&gt;
+${s}
+&lt;p&gt;Hello ${name}!
+
+To prove that s didn't contain the value in escaped form:
+${s?replace('&amp;'), 'and'}</programlisting>
+
+            <programlisting role="output">&amp;lt;p&amp;gt;Hello Foo &amp;amp; Bar!
+&lt;p&gt;Hello Foo &amp;amp; Bar!
+
+To prove that "s" didn't contain the value in escaped form:
+&amp;lt;p&amp;gt;Hello Foo and Bar!</programlisting>
+          </section>
+
+          <section>
+            <title>Combined output formats</title>
+
+            <para>Combined output formats are output formats that are created
+            ad-hoc from other output formats by nesting them into each other,
+            so that the escaping of both output formats are applied. <link
+            linkend="topic.combinedOutputFormats">They are discussed
+            here...</link></para>
+          </section>
+        </section>
+      </section>
+
+      <section xml:id="dgui_misc_computer_vs_human_format">
+        <title>Formatting for humans, or for computers</title>
+
+        <para>By default
+        <literal>${<replaceable>someValue</replaceable>}</literal> outputs
+        numbers, date/time/date-time and boolean values in a format that
+        targets normal users (<quote>humans</quote>). You have various
+        settings to specify how that format looks, like
+        <literal>number_format</literal>, <literal>date_format</literal>,
+        <literal>time_format</literal>, <literal>datetime_format</literal>,
+        <literal>boolan_format</literal>. The output also often depends on the
+        <literal>locale</literal> setting (i.e., on the language, and country
+        of the user). So 3000000 is possibly printed as
+        <literal>3,000,000</literal> (i.e., with grouping separators), or
+        <literal>3.14</literal> is possibly printed as <literal>3,14</literal>
+        (i.e., with a different decimal separator).</para>
+
+        <para>At some places you need to output values that will be read
+        (parsed) by some program, in which case always use the <link
+        linkend="ref_builtin_c"><literal>c</literal> built-in</link>, as in
+        <literal>${<replaceable>someValue</replaceable>?c}</literal> (the
+        <quote>c</quote> stands for Computer). <emphasis>Then the formatting
+        depends on the <literal>c_format</literal> <link
+        linkend="pgui_config_settings">setting</link></emphasis>, which
+        usually refers to a computer language, like <literal>"JSON"</literal>.
+        The output of <literal>?c</literal> is not influenced by
+        <literal>locale</literal>, <literal>number_format</literal>,
+        etc.</para>
+
+        <para>The <literal>c</literal> built-in will format string values to
+        string literals. Like if the <literal>c_format</literal> setting is
+        <literal>"JSON"</literal>, then <literal>{"fullName":
+        ${fullName?c}}</literal> will output something like
+        <literal>{"fullName": "John Doe"}</literal>, where the quotation marks
+        (and <literal>\</literal> escaping if needed) were added by
+        <literal>?c</literal>.</para>
+
+        <note>
+          <para>At least as of 2.3.32, the <literal>c</literal> built-in
+          doesn't support date/time/datetime values, only numbers, booleans,
+          and strings.</para>
+        </note>
+
+        <para>When formatting for computers, at some places you want to output
+        a <literal>null</literal> (or its equivalent in the target language)
+        if the value you print is missing/<literal>null</literal>. The
+        convenient shortcut for that is using the <literal>cn</literal>
+        built-in (the <quote>n</quote> stands for Nullable), as in
+        <literal>${<replaceable>someValue</replaceable>?cn}</literal>. It
+        behaves like the <literal>c</literal> built-in, except that if
+        <literal><replaceable>someValue</replaceable></literal> evaluates to
+        <literal>null</literal>/missing, it outputs the
+        <literal>null</literal> literal in the syntax that the
+        <literal>c_format</literal> setting specifies, instead of stopping
+        with missing value error.</para>
+
+        <para>For the templates where the output is obviously only for
+        computer consumption, some prefers setting the
+        <literal>number_format</literal>, and
+        <literal>boolean_format</literal> settings to <literal>"c"</literal>.
+        (Before 2.3.32, for <literal>number_format</literal> you have to use
+        <literal>"computer"</literal> instead.) Then
+        <literal>${<replaceable>someValue</replaceable>}</literal>, for
+        number, and boolean values will format like <literal>?c</literal>
+        does. To output string literals (i.e, to add quotation and escaping),
+        you will still need an explicit <literal>?c</literal>. Also if you
+        need to output <literal>null</literal> literals, you still have to use
+        <literal>?cn</literal>.</para>
+
+        <para>These are the table of supported <literal>c_format</literal>
+        setting values (as of FreeMarker 2.3.32), and their intended
+        use:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><literal>"JSON"</literal>: JSON generation. Generally,
+            <literal>"JavaScript or JSON"</literal> (see later) is recommended
+            over this.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>"JavaScript"</literal>: JavaScript generation.
+            Generally, <literal>"JavaScript or JSON"</literal> (see later) is
+            recommended over this.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>"Java"</literal>: Java source code
+            generation</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>"XS"</literal>: XML Schema compliant XML
+            generation</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>"JavaScript or JSON"</literal>: For generating
+            output that's compatible with both JSON and JavaScript. This setup
+            is therefore resilient against configuration mistakes, where we
+            generate output in one language, but use the
+            <literal>c_format</literal> for the other. The small price to pay
+            is that we can't utilize some language-specific opportunities to
+            make the output a bit shorter, but that hardly matters in
+            practice. This is the default if if the <link
+            linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
+            setting</link> is at least 2.3.32.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>"legacy"</literal>: Default for backward
+            compatibility when the <link
+            linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
+            setting</link> is less than 2.3.32. Avoid! Can have rounding
+            losses, and formatting glitches for infinity and NaN.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>The behaviour of these is documented at the <literal>c</literal>
+        built-in: <link linkend="ref_builtin_c">for numbers</link>, <link
+        linkend="ref_builtin_c_boolean">for boolean</link>, <link
+        linkend="ref_builtin_c_string">for strings</link>, <link
+        linkend="ref_builtin_cn">for null-s</link>.</para>
+      </section>
+
+      <section xml:id="dgui_misc_whitespace">
+        <title>White-space handling</title>
+
+        <indexterm>
+          <primary>white-space removal</primary>
+        </indexterm>
+
+        <para>The control of the <link
+        linkend="gloss.whiteSpace">white-space</link> in a template is a
+        problem that to some extent haunts every template engine in the
+        business.</para>
+
+        <para>Let see this template. I have marked the components of template
+        with colors: <phrase role="markedText">text</phrase>, <phrase
+        role="markedInterpolation">interpolation</phrase>, <phrase
+        role="markedFTLTag">FTL tag</phrase>. With the <phrase
+        role="markedInvisibleText">[BR]</phrase>-s I visualize the <link
+        linkend="gloss.lineBreak">line breaks</link>.</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;p&gt;List of users:<phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;#assign users = [{"name":"Joe",        "hidden":false},<phrase
+                role="markedInvisibleText">[BR]</phrase>
+                  {"name":"James Bond", "hidden":true},<phrase
+                role="markedInvisibleText">[BR]</phrase>
+                  {"name":"Julia",      "hidden":false}]&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;#list users as user&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;#if !user.hidden&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;li&gt;<phrase role="markedInterpolation">${user.name}</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;/#if&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;That's all.</phrase></programlisting>
+
+        <para>If FreeMarker were to output all <phrase
+        role="markedText">text</phrase> as is, the output would be:</para>
+
+        <programlisting role="output"><phrase role="markedText">&lt;p&gt;List of users:<phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;li&gt;</phrase>Joe<phrase role="markedText"><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;li&gt;</phrase>Julia<phrase role="markedText"><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;That's all.</phrase></programlisting>
+
+        <para>You have a lot of unwanted spaces and line breaks here.
+        Fortunately neither HTML nor XML is typically white-space sensitive,
+        but this amount of superfluous white-space can be annoying, and
+        needlessly increases the size of produced HTML. Of course, it is even
+        bigger problem when outputting white-space-sensitive formats.</para>
+
+        <para>FreeMarker provides the following tools to cope with this
+        problem:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>Tools to ignore certain white-space of the template files
+            <phrase role="forProgrammers">(parse time white-space
+            removal)</phrase>:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>White-space stripping: This feature automatically
+                ignores typical superfluous white-space around FTL tags. It
+                can be enabled or disabled on per template manner.</para>
+              </listitem>
+
+              <listitem>
+                <para>Trimmer directives: <literal>t</literal>,
+                <literal>rt</literal>, <literal>lt</literal>. With these
+                directives you can explicitly tell FreeMarker to ignore
+                certain white-space. Read <link linkend="ref.directive.t">the
+                reference</link> for more information.</para>
+              </listitem>
+
+              <listitem>
+                <para><link
+                linkend="ref.directive.ftl"><literal>ftl</literal></link>
+                parameter <literal>strip_text</literal>: This removes all
+                top-level text from the template. It is useful for templates
+                that contain macro definitions only (and some other
+                non-outputting directives), because it removes the line-breaks
+                that you use between the macro definitions and between the
+                other top-level directives to improve the readability of the
+                template.</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Tools that remove white-space from the output <phrase
+            role="forProgrammers">(on-the-fly white-space
+            removal)</phrase>:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal>compress</literal> directive.</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="dgui_misc_whitespace_stripping">
+          <title>White-space stripping</title>
+
+          <indexterm>
+            <primary>white-space removal</primary>
+
+            <secondary>stripping</secondary>
+          </indexterm>
+
+          <para>If this feature is enabled for a template, then it
+          automatically ignores (i.e. does not print to the output) two kind
+          of typical superfluous white-space:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Indentation white-space, and trailing white-space at the
+              end of the line (includes the line break) will be ignored in
+              lines that contains only FTL tags (e.g.
+              <literal>&lt;@myMacro/&gt;</literal>, <literal>&lt;#if
+              <replaceable>...</replaceable>&gt;</literal>) and/or FTL
+              comments (e.g. <literal>&lt;#-- blah --&gt;</literal>), apart
+              from the the ignored white-space itself. For example, if a line
+              contains only an <literal>&lt;#if
+              <replaceable>...</replaceable>&gt;</literal>, then the
+              indentation before the tag and the line break after the tag will
+              be ignored. However, if the line contains <literal>&lt;#if
+              <replaceable>...</replaceable>&gt;x</literal>, then the
+              white-space in that line will not be ignored, because of the
+              <literal>x</literal>, as that is not FTL tag. Note that
+              according these rules, a line that contains <literal>&lt;#if
+              <replaceable>...</replaceable>&gt;&lt;#list
+              <replaceable>...</replaceable>&gt;</literal> is subject to
+              white-space ignoring, while a line that contains
+              <literal>&lt;#if <replaceable>...</replaceable>&gt; &lt;#list
+              <replaceable>...</replaceable>&gt;</literal> is not, because the
+              white-space between the two FTL tags is embedded white-space,
+              not indentation or trailing white-space.</para>
+            </listitem>
+
+            <listitem>
+              <para>White-space sandwiched between the following directives is
+              ignored: <literal>macro</literal>, <literal>function</literal>,
+              <literal>assign</literal>, <literal>global</literal>,
+              <literal>local</literal>, <literal>ftl</literal>,
+              <literal>import</literal>, but only if there is
+              <emphasis>only</emphasis> white-space and/or FTL comments
+              between the directives. In practice it means that you can put
+              empty lines between macro definitions and assignments as spacing
+              for better readability, without printing needless empty lines
+              (line breaks) to the output.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>The output of the last example with white-space stripping
+          enabled will be:</para>
+
+          <programlisting role="output"><phrase role="markedText">&lt;p&gt;List of users:<phrase
+                role="markedInvisibleText">[BR]</phrase>
+&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;li&gt;</phrase>Joe<phrase role="markedText"><phrase
+                role="markedInvisibleText">[BR]</phrase>
+  &lt;li&gt;</phrase>Julia<phrase role="markedText"><phrase
+                role="markedInvisibleText">[BR]</phrase>
+&lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;That's all.</phrase></programlisting>
+
+          <para>This is because after stripping the template becomes the
+          following; the ignored text is not <phrase
+          role="markedText">colored</phrase>:</para>
+
+          <programlisting role="template"><phrase role="markedText">&lt;p&gt;List of users:<phrase
+                role="markedInvisibleText">[BR]</phrase></phrase>
+<phrase role="markedFTLTag">&lt;#assign users = [{"name":"Joe",        "hidden":false},<phrase
+                role="markedInvisibleText">[BR]</phrase>
+                  {"name":"James Bond", "hidden":true},<phrase
+                role="markedInvisibleText">[BR]</phrase>
+                  {"name":"Julia",      "hidden":false}]&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedText">&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase></phrase>
+<phrase role="markedFTLTag">&lt;#list users as user&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;#if !user.hidden&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedText">  &lt;li&gt;<phrase role="markedInterpolation">${user.name}</phrase><phrase
+                role="markedInvisibleText">[BR]</phrase></phrase>
+  <phrase role="markedFTLTag">&lt;/#if&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedText">&lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;That's all.</phrase></programlisting>
+
+          <para>White-space stripping can be enabled/disabled in per template
+          manner with the <link
+          linkend="ref.directive.ftl"><literal>ftl</literal> directive</link>.
+          If you don't specify this with the <literal>ftl</literal> directive,
+          then white-space stripping will be enabled or disabled depending on
+          how the programmer has configured FreeMarker. The factory default is
+          white-space stripping enabled, and the programmers probably left it
+          so (<phrase role="forProgrammers">recommended</phrase>). <phrase
+          role="forProgrammers">Note that enabling white-space stripping does
+          <emphasis>not</emphasis> degrade the performance of template
+          execution; white-space stripping is done during template
+          loading.</phrase></para>
+
+          <para>White-space stripping can be disabled for a single line with
+          the <link linkend="ref.directive.nt"><literal>nt</literal></link>
+          directive (for No Trim).</para>
+        </section>
+
+        <section>
+          <title>Using compress directive</title>
+
+          <indexterm>
+            <primary>white-space removal</primary>
+
+            <secondary>compress</secondary>
+          </indexterm>
+
+          <para>Another solution is to use the <link
+          linkend="ref.directive.compress"><literal>compress</literal>
+          directive</link>. As opposed to white-space stripping, this works
+          directly on the generated output, not on the template. That is, it
+          will investigate the printed output on the fly, and does not
+          investigate the FTL program that creates the output. It aggressively
+          removes indentations, empty lines and repeated spaces/tabs (for more
+          information read the <link
+          linkend="ref.directive.compress">reference</link>). So the output
+          of:</para>
+
+          <programlisting role="template"><emphasis>&lt;#compress&gt;</emphasis>
+&lt;#assign users = [{"name":"Joe",        "hidden":false},
+                  {"name":"James Bond", "hidden":true},
+                  {"name":"Julia",      "hidden":false}]&gt;
+List of users:
+&lt;#list users as user&gt;
+  &lt;#if !user.hidden&gt;
+  - ${user.name}
+  &lt;/#if&gt;
+&lt;/#list&gt;
+That's all.
+<emphasis>&lt;/#compress&gt;</emphasis></programlisting>
+
+          <para>will be:</para>
+
+          <programlisting role="output">List of users:
+- Joe
+- Julia
+That's all.</programlisting>
+
+          <para>Note that <literal>compress</literal> is totally independent
+          of white-space stripping. So it is possible that the white-space of
+          template is stripped, and later the produced output is
+          <literal>compress</literal>-ed.</para>
+
+          <para>Also, by default a user-defined directve called
+          <literal>compress</literal> is available in the data-model (due to
+          backward compatibility). This is the same as the directive, except
+          that you may optionally set the <literal>single_line</literal>
+          parameter, which will remove all intervening line breaks. If you
+          replace
+          <literal>&lt;#compress&gt;<replaceable>...</replaceable>&lt;/#compress&gt;</literal>
+          on the last example with <literal>&lt;@compress
+          single_line=true&gt;<replaceable>...</replaceable>&lt;/@compress&gt;</literal>,
+          then you get this output:</para>
+
+          <programlisting role="output">List of users: - Joe - Julia That's all.</programlisting>
+        </section>
+      </section>
+
+      <section xml:id="dgui_misc_alternativesyntax">
+        <title>Alternative (square bracket) syntax</title>
+
+        <indexterm>
+          <primary>alternative syntax</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>square bracket syntax</primary>
+        </indexterm>
+
+        <para>Sometimes the generated content uses symbols that clashes with
+        the default FreeMarker syntax (typically,
+        <literal>${<replaceable>...</replaceable>}</literal>-s that FreeMarker
+        should print as is, without interpretation), or you use some tool that
+        is confused by the default FreeMarker syntax (typically by
+        <literal>&lt;</literal> and <literal>&gt;</literal>). While usually
+        there are tricks to work those cases around (like you can use
+        <literal>${'$'}{x}</literal> to print <literal>${x}</literal> as is) ,
+        they are often too inconvenient. Thus, the interpolation syntax can be
+        configured to be like <literal>[=x]</literal> instead of
+        <literal>${x}</literal>. Also, independently of that, the FreeMarker
+        tag syntax can be configured to use <literal>[]</literal>, like in
+        <literal>[#if x]<replaceable>...</replaceable>[/#if]</literal>.</para>
+
+        <note>
+          <para>While both the <quote>tag syntax</quote> and
+          <quote>interpolation syntax</quote> can be configured to use square
+          brackets, they are totally independent configuration settings. Thus,
+          the overall syntax can be like <literal>[#if x]${y}[/#if]</literal>,
+          or like <literal>&lt;#if x&gt;[=y]&lt;/#if&gt;</literal> as
+          well.</para>
+        </note>
+
+        <section xml:id="dgui_misc_alternativesyntax_tag">
+          <title>Square bracket tag syntax</title>
+
+          <note>
+            <para>This section is about the <emphasis>tag</emphasis> syntax,
+            not the <link
+            linkend="dgui_misc_alternativesyntax_interpolation"><emphasis>interpolation</emphasis>
+            syntax</link>. Don't confuse the two, they are independent.</para>
+          </note>
+
+          <note>
+            <para>This feature exists since FreeMarker 2.3.4.</para>
+          </note>
+
+          <para>FreeMarker supports an alternative tag syntax, where
+          <literal>[</literal> and <literal>]</literal> is used instead of
+          <literal>&lt;</literal> and <literal>&gt;</literal> in FreeMarker
+          directives and comments, for example:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para>Calling predefined directive: <literal>[#list animals as
+              animal]<replaceable>...</replaceable>[/#list]</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Calling user-defined directive: <literal>[@myMacro
+              /]</literal></para>
+            </listitem>
+
+            <listitem>
+              <para>Comment: <literal>[#-- the comment --]</literal></para>
+            </listitem>
+          </itemizedlist>
+
+          <para>To use square tag syntax instead of the default one, the
+          programmers should configure FreeMarker so <phrase
+          role="forProgrammers">(see
+          <literal>Configuraton.setTagSyntax</literal>, or the
+          <literal>tag_syntax</literal> setting)</phrase>. However, the tag
+          syntax can also be enforced in the template, with the <link
+          linkend="ref_directive_ftl"><literal>ftl</literal> directive</link>
+          (see later).</para>
+
+          <para>For example, this is how the last example of the <link
+          linkend="dgui_quickstart_template">Getting Started</link> looks with
+          the alternative syntax:</para>
+
+          <programlisting role="template">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+  &lt;tr&gt;&lt;th&gt;Name&lt;th&gt;Price
+  <emphasis>[#list animals as animal]</emphasis>
+  &lt;tr&gt;
+    &lt;td&gt;
+      <emphasis>[#if animal.size == "large"]</emphasis>&lt;b&gt;<emphasis>[/#if]</emphasis>
+      ${animal.name}
+      <emphasis>[#if animal.size == "large"]</emphasis>&lt;/b&gt;<emphasis>[/#if]</emphasis>
+    &lt;td&gt;${animal.price} Euros
+  <emphasis>[/#list]</emphasis>
+&lt;/table&gt;</programlisting>
+
+          <para>The square bracket and the default (angle bracket) syntax are
+          mutually exclusive within a template; they can't be mixed. If the
+          template uses square bracket tag syntax, then things like
+          <literal>&lt;#if <replaceable>...</replaceable>&gt;</literal> will
+          be just static text, not FTL tags. Similarly, if the template uses
+          the angle brackets tag syntax, things like <literal>[#if
+          <replaceable>...</replaceable>]</literal> are static text, not FTL
+          tags.</para>
+
+          <para>If you start the file with <literal>[#ftl
+          <replaceable>...</replaceable>]</literal> (where the
+          <literal><replaceable>...</replaceable></literal> stands for the
+          optional parameters; of course <literal>[#ftl]</literal> works too)
+          the file will use square bracket <emphasis>tag</emphasis> syntax
+          regardless of the configuration settings (but that does
+          <emphasis>not</emphasis> change the interpolation syntax to
+          <literal>[=...]</literal>). Similarly, if you start the file with
+          <literal>&lt;#ftl <replaceable>...</replaceable>&gt;</literal> the
+          file will use the normal (angle bracket) tag syntax. If there is no
+          <literal>ftl</literal> directive in the file, then the programmer
+          decides what the tag <emphasis>syntax</emphasis> will be by
+          configuring FreeMarker <phrase role="forProgrammers">(programmers
+          see <literal>Configuration.setTagSyntax(int)</literal> in the API
+          javadocs)</phrase>. Most probably the programmers use the factory
+          default.</para>
+        </section>
+
+        <section xml:id="dgui_misc_alternativesyntax_interpolation">
+          <title>Square bracket interpolation syntax</title>
+
+          <note>
+            <para>This section is about the <emphasis>interpolation</emphasis>
+            syntax, not the <link
+            linkend="dgui_misc_alternativesyntax_tag"><emphasis>tag</emphasis>
+            syntax</link>. Don't confuse the two, they are independent.</para>
+          </note>
+
+          <note>
+            <para>This feature exists since FreeMarker 2.3.28</para>
+          </note>
+
+          <para>In this case instead of
+          <literal>${<replaceable>expression</replaceable>}</literal> (and the
+          deprecated
+          <literal>#{<replaceable>expression</replaceable>}</literal>) you
+          write <literal>[=<replaceable>expression</replaceable>]</literal>.
+          This syntax is activated by the programmers from the configuration
+          <phrase role="forProgrammers">(see
+          <literal>Configuration.setInterpolationSyntax</literal> in the Java
+          API)</phrase>; unlike the tag syntax, it can't be specified inside
+          the template. It can be used both together with, and without the
+          <link linkend="dgui_misc_alternativesyntax_tag">square bracket
+          <emphasis>tag</emphasis> syntax</link>, as they are technically
+          unrelated, but it's probably more aesthetic to use square bracket
+          tag syntax when you use square bracket interpolation syntax:</para>
+
+          <programlisting role="template">[#--
+  Note:
+  This example uses both interpolation_syntax=squareBracket and tag_syntax=squareBracket,
+  but you can also use interpolation_syntax=squareBracket and tag_syntax=angleBracket.
+--]
+&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+  &lt;tr&gt;&lt;th&gt;Name&lt;th&gt;Price
+  [#list animals as animal]
+  &lt;tr&gt;
+    &lt;td&gt;
+      [#if animal.size == "large"]&lt;b&gt;[/#if]
+      <emphasis>[=animal.name]</emphasis>
+      [#if animal.size == "large"]&lt;/b&gt;[/#if]
+    &lt;td&gt;<emphasis>[=animal.price]</emphasis> Euros
+  [/#list]
+&lt;/table&gt;</programlisting>
+
+          <para>When square bracket interpolation syntax is used,
+          <literal>${<replaceable>expression</replaceable>}</literal> and
+          <literal>#{<replaceable>expression</replaceable>}</literal> in the
+          template will be just static text, which is printed as is. This is
+          mostly useful if you generate output that should contain those
+          (especially
+          <literal>${<replaceable>expression</replaceable>}</literal> is
+          frequent), such as when generating JSP files.</para>
+
+          <para>There's also a third tag syntax, <quote>dollar</quote>, where
+          only the interpolation syntax is
+          <literal>${<replaceable>expression</replaceable>}</literal>, and the
+          deprecated
+          <literal>#{<replaceable>expression</replaceable>}</literal> is just
+          static text. (The one where
+          <literal>#{<replaceable>expression</replaceable>}</literal> is still
+          an interpolation is called the <quote>legacy</quote> interpolation
+          syntax, and is the default for backward compatibility.)</para>
+        </section>
+      </section>
+    </chapter>
+  </part>
+
+  <part xml:id="pgui">
+    <title>Programmer's Guide</title>
+
+    <chapter xml:id="pgui_quickstart">
+      <title>Getting Started</title>
+
+      <para>If you are new to FreeMarker, you should read at least the <xref
+      linkend="dgui_quickstart_basics"/> before this chapter.</para>
+
+      <section xml:id="pgui_quickstart_createconfiguration">
+        <title>Create a configuration instance</title>
+
+        <indexterm>
+          <primary>configuration</primary>
+        </indexterm>
+
+        <para>First you have to create a
+        <literal>freemarker.template.Configuration</literal> instance and
+        adjust its settings. A <literal>Configuration</literal> instance is
+        the central place to store the application level settings of
+        FreeMarker. Also, it deals with the creation and
+        <emphasis>caching</emphasis> of pre-parsed templates (i.e.,
+        <literal>Template</literal> objects).</para>
+
+        <para>Normally you will <emphasis>do this only once</emphasis> at the
+        beginning of the application (possibly servlet) life-cycle:</para>
+
+        <programlisting role="unspecified">// Create your Configuration instance, and specify if up to what FreeMarker
+// version (here 2.3.29) do you want to apply the fixes that are not 100%
+// backward-compatible. See the Configuration JavaDoc for details.
+Configuration cfg = new Configuration(Configuration.VERSION_2_3_29);
+
+// Specify the source where the template files come from. Here I set a
+// plain directory for it, but non-file-system sources are possible too:
+cfg.setDirectoryForTemplateLoading(new File("<replaceable>/where/you/store/templates</replaceable>"));
+
+// From here we will set the settings recommended for new projects. These
+// aren't the defaults for backward compatibilty.
+
+// Set the preferred charset template files are stored in. UTF-8 is
+// a good choice in most applications:
+cfg.setDefaultEncoding("UTF-8");
+
+// Sets how errors will appear.
+// During web page *development* TemplateExceptionHandler.HTML_DEBUG_HANDLER is better.
+cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+
+// Don't log exceptions inside FreeMarker that it will thrown at you anyway:
+cfg.setLogTemplateExceptions(false);
+
+// Wrap unchecked exceptions thrown during template processing into TemplateException-s:
+cfg.setWrapUncheckedExceptions(true);
+
+// Do not fall back to higher scopes when reading a null loop variable:
+cfg.setFallbackOnNullLoopVariable(false);</programlisting>
+
+        <para>From now you should use this <emphasis>single</emphasis>
+        configuration instance (i.e., its a singleton). Note however that if a
+        system has multiple independent components that use FreeMarker, then
+        of course they will use their own private
+        <literal>Configuration</literal> instances.</para>
+
+        <warning>
+          <para>Do not needlessly re-create <literal>Configuration</literal>
+          instances; it's expensive, among others because you lose the
+          template cache. <literal>Configuration</literal> instances meant to
+          be application-level singletons.</para>
+        </warning>
+
+        <para>In multi-threaded applications (like Web sites) the settings in
+        the <literal>Configuration</literal> instance must not be modified
+        anymore after this point. Thus it can be treated as <quote>effectively
+        immutable</quote> object, so you can continue with <emphasis>safe
+        publishing</emphasis> techniques (see JSR 133 and related literature)
+        to make the instance available for other threads. Like, publish the
+        instance through a final or volatile filed, or through a thread-safe
+        IoC container (like the one provided by Spring).
+        <literal>Configuration</literal> methods that don't deal with
+        modifying settings are thread-safe.</para>
+      </section>
+
+      <section xml:id="pgui_quickstart_createdatamodel">
+        <title>Create a data-model</title>
+
+        <indexterm>
+          <primary>data-model</primary>
+
+          <secondary>assembling with Java</secondary>
+        </indexterm>
+
+        <para>In simple cases you can build data-models using
+        <literal>java.lang</literal> and <literal>java.util</literal> classes
+        and custom JavaBeans:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>Use <literal>java.lang.String</literal> for strings.</para>
+          </listitem>
+
+          <listitem>
+            <para>Use <literal>java.lang.Number</literal> subclasses for
+            numbers.</para>
+          </listitem>
+
+          <listitem>
+            <para>Use <literal>java.lang.Boolean</literal> for boolean
+            values.</para>
+          </listitem>
+
+          <listitem>
+            <para>Use <literal>java.util.Date</literal> and its subclasses for
+            date/time values</para>
+          </listitem>
+
+          <listitem>
+            <para>Use <literal>java.util.List</literal> or Java arrays for
+            sequences.</para>
+          </listitem>
+
+          <listitem>
+            <para>Use <literal>java.util.Map</literal> with
+            <literal>String</literal> keys for hashes.</para>
+          </listitem>
+
+          <listitem>
+            <para>Use your custom bean class for hashes where the items
+            correspond to the bean properties. For example the
+            <literal>price</literal> property (<literal>getPrice()</literal>)
+            of <literal>product</literal> can be get as
+            <literal>product.price</literal>. (The actions of the beans can be
+            exposed as well; see much later <link
+            linkend="pgui_misc_beanwrapper">here</link>)</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>For example, let's build the data-model of the <link
+        linkend="example.first">first example of the Template Author's
+        Guide</link>. For convenience, here it is again:</para>
+
+        <programlisting role="dataModel">(root)
+  |
+  +- user = "Big Joe"
+  |
+  +- latestProduct
+      |
+      +- url = "products/greenmouse.html"
+      |
+      +- name = "green mouse"</programlisting>
+
+        <para>This Java code fragment that builds this data-model:</para>
+
+        <programlisting role="unspecified">// Create the root hash. We use a Map here, but it could be a JavaBean too.
+Map&lt;String, Object&gt; root = new HashMap&lt;&gt;();
+
+// Put string "user" into the root
+root.put("user", "Big Joe");
+
+// Create the "latestProduct" hash. We use a JavaBean here, but it could be a Map too.
+Product latest = new Product();
+latest.setUrl("products/greenmouse.html");
+latest.setName("green mouse");
+// and put it into the root
+root.put("latestProduct", latest);
+</programlisting>
+
+        <para>As demonstrated above, for hashes (something that stores other
+        named items) you can use either a <literal>Map</literal> or any kind
+        of public class that has public
+        <literal>get<replaceable>Xxx</replaceable></literal>/<literal>is<replaceable>Xxx</replaceable></literal>
+        methods as prescribed by the JavaBeans specification. Like the above
+        <literal>Product</literal> class could be something like:</para>
+
+        <programlisting role="unspecified">/**
+ * Product bean; note that it must be a public class!
+ */
+public class Product {
+
+    private String url;
+    private String name;
+
+    // As per the JavaBeans spec., this defines the "url" bean property
+    // It must be public!
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    // As per the JavaBean spec., this defines the "name" bean property
+    // It must be public!
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+}</programlisting>
+
+        <para>Regardless if <literal>latestProduct</literal> is a
+        <literal>Map</literal> that contains the <literal>"name"</literal> and
+        <literal>"url"</literal> keys, or it's a JavaBean as shown above, in
+        the template you can use <literal>${latestProduct.name}</literal>. The
+        root itself need not be a <literal>Map</literal> either; it could be
+        an object with <literal>getUser()</literal> and
+        <literal>getLastestProduct()</literal> methods too.</para>
+
+        <note>
+          <para>The behavior described here only stands if the value of the
+          <literal>object_wrapper</literal> configuration setting is something
+          that's used in almost all real world setups anyway. Anything that
+          the <literal>ObjectWrapper</literal> wraps to be a hash (something
+          that implements the <literal>TemplateHashModel</literal> interface)
+          can be used as the root, and can be traversed in templates with the
+          dot and <literal>[]</literal> operators. Something that it doesn't
+          wrap to be a hash can't be used as the root or be traversed like
+          that.</para>
+        </note>
+      </section>
+
+      <section xml:id="pgui_quickstart_gettemplate">
+        <title>Get the template</title>
+
+        <indexterm>
+          <primary>template</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <para>Templates are represented by
+        <literal>freemarker.template.Template</literal> instances. Typically
+        you obtain a <literal>Template</literal> instance from the
+        <literal>Configuration</literal> instance, using its.
+        <literal>getTemplate</literal> method. If you store <link
+        linkend="example.first">the example template</link> in the
+        <literal>test.ftlh</literal> file of the <link
+        linkend="pgui_quickstart_createconfiguration">earlier</link> set
+        directory, then you can do this:</para>
+
+        <programlisting role="unspecified">Template temp = cfg.getTemplate("test.ftlh");</programlisting>
+
+        <para>This gives you a <literal>Template</literal> instance that was
+        created by reading
+        <literal><replaceable>/where/you/store/templates/</replaceable>test.ftlh</literal>
+        and parsing it. The <literal>Template</literal> instance stores the
+        template in parsed form, and not as text. If the template is missing
+        or syntactically incorrect, <literal>getTemplate</literal> will throw
+        exception instead.</para>
+
+        <para><literal>Configuration</literal> caches
+        <literal>Template</literal> instances, so when you call
+        <literal>cfg.getTemplate("test.ftlh")</literal> next time, it probably
+        won't read and parse the template file again, just returns the same
+        <literal>Template</literal> instance as for the first time.</para>
+      </section>
+
+      <section xml:id="pgui_quickstart_merge">
+        <title>Merging the template with the data-model</title>
+
+        <indexterm>
+          <primary>output</primary>
+
+          <secondary>generate with Java</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>merging</primary>
+        </indexterm>
+
+        <para>As you might already know, data-model + template = output. We
+        already have a data-model (<literal>root</literal>) and a template
+        (<literal>temp</literal>), so to get the output we have to merge them.
+        This is done by the <literal>process</literal> method of the template.
+        It takes the data-model root and a <literal>Writer</literal> as
+        parameters. It writes the produced output to the
+        <literal>Writer</literal>. For the sake of simplicity here I write to
+        the standard output:</para>
+
+        <programlisting role="unspecified">Writer out = new OutputStreamWriter(System.out);
+temp.process(root, out);</programlisting>
+
+        <para>This will print to your terminal the output you have seen in the
+        <link linkend="example.first">first example</link> of the Template
+        Author's Guide.</para>
+
+        <para>Java I/O related notes: Depending on what <literal>out</literal>
+        is, you may need to ensure that <literal>out.close()</literal> is
+        called. This is typically needed when <literal>out</literal> writes
+        into a file that was opened to store the output of the template. In
+        other times, like in typical Web applications, you must
+        <emphasis>not</emphasis> close <literal>out</literal>. FreeMarker
+        calls <literal>out.flush()</literal> after a successful template
+        execution (but tis can be disabled in
+        <literal>Configuration</literal>), so you don't need to worry about
+        that.</para>
+
+        <para>Note that once you have obtained a <literal>Template</literal>
+        instance, you can merge it with different data-models for unlimited
+        times (<literal>Template</literal> instances are stateless). Also, the
+        <literal>test.ftlh</literal> file is accessed only while the
+        <literal>Template</literal> instance is created, not when you call the
+        process method.</para>
+      </section>
+
+      <section xml:id="pgui_quickstart_all">
+        <title>Putting all together</title>
+
+        <para>This is a working source file assembled from the previous
+        fragments. Don't forget to put <literal>freemarker.jar</literal> into
+        the <literal>CLASSPATH</literal>.</para>
+
+        <programlisting role="unspecified">import freemarker.template.*;
+import java.util.*;
+import java.io.*;
+
+public class Test {
+
+    public static void main(String[] args) throws Exception {
+
+        /* ------------------------------------------------------------------------ */
+        /* You should do this ONLY ONCE in the whole application life-cycle:        */
+
+        /* Create and adjust the configuration singleton */
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_29);
+        cfg.setDirectoryForTemplateLoading(new File("<replaceable>/where/you/store/templates</replaceable>"));
+        // Recommended settings for new projects:
+        cfg.setDefaultEncoding("UTF-8");
+        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+        cfg.setLogTemplateExceptions(false);
+        cfg.setWrapUncheckedExceptions(true);
+        cfg.setFallbackOnNullLoopVariable(false);
+
+        /* ------------------------------------------------------------------------ */
+        /* You usually do these for MULTIPLE TIMES in the application life-cycle:   */
+
+        /* Create a data-model */
+        Map root = new HashMap();
+        root.put("user", "Big Joe");
+        Product latest = new Product();
+        latest.setUrl("products/greenmouse.html");
+        latest.setName("green mouse");
+        root.put("latestProduct", latest);
+
+        /* Get the template (uses cache internally) */
+        Template temp = cfg.getTemplate("test.ftlh");
+
+        /* Merge data-model with template */
+        Writer out = new OutputStreamWriter(System.out);
+        temp.process(root, out);
+        // Note: Depending on what `out` is, you may need to call `out.close()`.
+        // This is usually the case for file output, but not for servlet output.
+    }
+}</programlisting>
+
+        <note>
+          <para>I have suppressed the exceptions for the sake of simplicity.
+          Don't do it in real products.</para>
+        </note>
+
+        <para>For the sake completeness, here's the the Product class used in
+        the data model:</para>
+
+        <programlisting role="unspecified">/**
+ * Product bean; note that it must be a public class!
+ */
+public class Product {
+
+    private String url;
+    private String name;
+
+    // As per the JavaBeans spec., this defines the "url" bean property
+    // It must be public!
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    // As per the JavaBean spec., this defines the "name" bean property
+    // It must be public!
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+}</programlisting>
+
+        <para>and the template:</para>
+
+        <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome ${user}!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+      </section>
+    </chapter>
+
+    <chapter xml:id="pgui_datamodel">
+      <title>The Data Model</title>
+
+      <para>This is just an introductory explanation. See the <olink
+      targetdoc="api">FreeMarker Java API documentation</olink> for more
+      detailed information.</para>
+
+      <section xml:id="pgui_datamodel_basics">
+        <title>Basics</title>
+
+        <indexterm>
+          <primary>object wrapper</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>wrapper</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>data-model</primary>
+
+          <secondary>assembling with Java, without object wrapper</secondary>
+        </indexterm>
+
+        <para>You have seen how to build a data-model in the <link
+        linkend="pgui_quickstart">Getting Started</link> using the standard
+        Java classes (<literal>Map</literal>, <literal>String</literal>,
+        etc.). Internally, the variables available in the template are Java
+        objects that implement the
+        <literal>freemarker.template.TemplateModel</literal> interface. But
+        you could use standard Java collections as variables in your
+        data-model, because these were replaced with the appropriate
+        <literal>TemplateModel</literal> instances behind the scenes. This
+        facility is called <emphasis role="term">object wrapping</emphasis>.
+        The object wrapping facility can convert <emphasis>any</emphasis> kind
+        of object transparently to the instances of classes that implement
+        <literal>TemplateModel</literal> interface. This makes it possible,
+        for example, to access <literal>java.sql.ResultSet</literal> as
+        sequence variable in templates, or to access
+        <literal>javax.servlet.ServletRequest</literal> objects as a hash
+        variable that contains the request attributes, or even to traverse XML
+        documents as FTL variables (<link linkend="xgui">see here</link>). To
+        wrap (convert) these objects, however, you need to plug the proper
+        <literal>ObjectWrapper</literal> implementation (possibly your custom
+        implementation); this will be discussed <link
+        linkend="pgui_datamodel_objectWrapper">later</link>. The point for now
+        is that any object that you want to access from the templates, sooner
+        or later must be converted to an object that implements
+        <literal>TemplateModel</literal> interface. So first you should
+        familiarize yourself with writing of <literal>TemplateModel</literal>
+        implementations.</para>
+
+        <para>There is roughly one
+        <literal>freemarker.template.TemplateModel</literal> descendant
+        interface corresponding to each basic type of variable
+        (<literal>TemplateHashModel</literal> for hashes,
+        <literal>TemplateSequenceModel</literal> sequences,
+        <literal>TemplateNumberModel</literal> for numbers, etc.). For
+        example, if you want to expose a <literal>java.sql.ResultSet</literal>
+        as a sequence for the templates, then you have to write a
+        <literal>TemplateSequenceModel</literal> implementation that can read
+        <literal>java.sql.ResultSet</literal>-s. We used to say on this, that
+        you <emphasis>wrap</emphasis> the
+        <literal>java.sql.ResultSet</literal> with your
+        <literal>TemplateModel</literal> implementation, as basically you just
+        encapsulate the <literal>java.sql.ResultSet</literal> to provide
+        access to it with the common <literal>TemplateSequenceModel</literal>
+        interface. Note that a class can implement multiple
+        <literal>TemplateModel</literal> interfaces; this is why FTL variables
+        can have multiple types (see: <xref
+        linkend="dgui_datamodel_basics"/>)</para>
+
+        <para>Note that a trivial implementation of these interfaces is
+        provided with the <literal>freemarker.template</literal> package. For
+        example, to convert a <literal>String</literal> to FTL string
+        variable, you can use <literal>SimpleScalar</literal>, to convert a
+        <literal>java.util.Map</literal> to FTL hash variable, you can use
+        <literal>SimpleHash</literal>, etc.</para>
+
+        <para>An easy way to try your own <literal>TemplateModel</literal>
+        implementation, is to create an instance of that, and drop it directly
+        into the data-model (as <literal>put</literal> it into the root hash).
+        The object wrapper will expose it untouched for the template, as it
+        already implements <literal>TemplateModel</literal>, so no conversion
+        (wrapping) needed. (This trick is also useful in cases when you do not
+        want the object wrapper to try to wrap (convert) a certain
+        object.)</para>
+      </section>
+
+      <section xml:id="pgui_datamodel_scalar">
+        <title>Scalars</title>
+
+        <indexterm>
+          <primary>scalar</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>string</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>number</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>boolean</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>date</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>time</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <para>There are 4 scalar types:</para>
+
+        <itemizedlist spacing="compact">
+          <listitem>
+            <para>Boolean</para>
+          </listitem>
+
+          <listitem>
+            <para>Number</para>
+          </listitem>
+
+          <listitem>
+            <para>String</para>
+          </listitem>
+
+          <listitem>
+            <para>Date-like (subtypes: date (no time part), time or
+            date-time)</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>For each scalar type is a
+        <literal>Template<replaceable>Type</replaceable>Model</literal>
+        interface, where <literal><replaceable>Type</replaceable></literal> is
+        the name of the type. These interfaces define only one method:
+        <literal><replaceable>type</replaceable>
+        getAs<replaceable>Type</replaceable>();</literal>. This returns the
+        value of the variable with the Java type (<literal>boolean</literal>,
+        <literal>Number</literal>, <literal>String</literal> and
+        <literal>Date</literal> respectively).</para>
+
+        <note>
+          <para>For historical reasons the interface for string scalars is
+          called <literal>TemplateScalarModel</literal>, not
+          <literal>TemplateStringModel</literal>. (It's because in early
+          FreeMarker strings were the only kind of scalars.)</para>
+        </note>
+
+        <para>A trivial implementation of these interfaces are available in
+        <literal>freemarker.template</literal> package with
+        <literal>Simple<replaceable>Type</replaceable></literal> class name.
+        However, there is no <literal>SimpleBooleanModel</literal>; to
+        represent the boolean values you can use the
+        <literal>TemplateBooleanModel.TRUE</literal> and
+        <literal>TemplateBooleanModel.FALSE</literal> singletons.</para>
+
+        <note>
+          <para>For historical reasons the class for string scalars is called
+          <literal>SimpleScalar</literal>, not
+          <literal>SimpleString</literal>.</para>
+        </note>
+
+        <para>Scalars are immutable within FTL. When you set the value of a
+        variable in a template, then you replace the
+        <literal>Template<replaceable>Type</replaceable>Model</literal>
+        instance with another instance, and don't change the value stored in
+        the original instance.</para>
+
+        <section>
+          <title>Difficulties with the <quote>date-like</quote> types</title>
+
+          <indexterm>
+            <primary>date</primary>
+
+            <secondary>Java API related difficulties</secondary>
+          </indexterm>
+
+          <indexterm>
+            <primary>time</primary>
+
+            <secondary>Java API related difficulties</secondary>
+          </indexterm>
+
+          <para>There is a complication around date-like types, because Java
+          API usually does not differentiate
+          <literal>java.util.Date</literal>-s that store only the date part
+          (April 4, 2003), only the time part (10:19:18 PM), or both (April 4,
+          2003 10:19:18 PM). To display the value as text correctly (or to do
+          certain other operations), FreeMarker must know what parts of the
+          <literal>java.util.Date</literal> stores meaningful information, and
+          what parts are unused (usually 0-ed out). Unfortunately, this
+          information is usually only available when the value comes from a
+          database, because most databases have separate date, time and
+          date-time (aka. timestap) types, and <literal>java.sql</literal> has
+          3 corresponding <literal>java.util.Date</literal> subclasses for
+          them.</para>
+
+          <para><literal>TemplateDateModel</literal> interface has two
+          methods: <literal>java.util.Date getAsDate()</literal> and
+          <literal>int getDateType()</literal>. A typical implementation of
+          this interface, stores a <literal>java.util.Date</literal> object,
+          plus an integer that tells the subtype. The value of this integer
+          must be a constant from the <literal>TemplateDateModel</literal>
+          interface: <literal>DATE</literal>, <literal>TIME</literal>,
+          <literal>DATETIME</literal> and <literal>UNKNOWN</literal>.</para>
+
+          <para>About <literal>UNKNOWN</literal>: <literal>java.lang</literal>
+          and <literal>java.util</literal> classes are usually converted
+          automatically into <literal>TemplateModel</literal> implementations
+          be the <literal>ObjectWrapper</literal> (see object wrapping
+          earlier). If the object wrapper has to wrap a
+          <literal>java.util.Date</literal>, that is not an instance of a
+          <literal>java.sql</literal> date class, it can't decide what the
+          subtype is, so it uses <literal>UNKNOWN</literal>. Later, if the
+          template has to use this variable, and the subtype is needed for the
+          operation, it will stop with error. To prevent this, for the
+          problematic variables the template author must specify the subtype
+          explicitly using the <link
+          linkend="ref_builtin_date_datetype"><literal>date</literal>,
+          <literal>time</literal> or <literal>datetime</literal>
+          built-ins</link> (like <literal>lastUpdated?datetime</literal>).
+          Note that if you use <literal>string</literal> built-in with format
+          parameter, as <literal>foo?string["MM/dd/yyyy"]</literal>, then
+          FreeMarker doesn't need to know the subtype.</para>
+        </section>
+      </section>
+
+      <section xml:id="pgui_datamodel_parent">
+        <title>Containers</title>
+
+        <indexterm>
+          <primary>containers</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <para>These are hashes, sequences, and collections.</para>
+
+        <section>
+          <title>Hashes</title>
+
+          <indexterm>
+            <primary>hash</primary>
+
+            <secondary>Java side</secondary>
+          </indexterm>
+
+          <para>Hashes are java objects that implement
+          <literal>TemplateHashModel</literal> interface.
+          <literal>TemplateHashModel</literal> contains two methods:
+          <literal>TemplateModel get(String key)</literal>, which returns the
+          subvariable of the given name, and <literal>boolean
+          isEmpty()</literal>, which indicates if the hash has zero
+          subvariable or not. The <literal>get</literal> method returns null
+          if no subvariable with the given name exists.</para>
+
+          <para>The <literal>TemplateHashModelEx</literal> interface extends
+          <literal>TemplateHashModel</literal>. It adds methods by which <link
+          linkend="ref_builtin_values">values</link> and <link
+          linkend="ref_builtin_keys">keys</link> built-ins can enumerate the
+          sub variables of the hash.</para>
+
+          <para>The commonly used implementation is
+          <literal>SimpleHash</literal>, which implements
+          <literal>TemplateHashModelEx</literal>. Internally it uses a
+          <literal>java.util.Hash</literal> to store the sub variables.
+          <literal>SimpleHash</literal> has methods by which you can add and
+          remove subvariable. These methods should be used to initialize the
+          variable directly after its creation.</para>
+
+          <para>Containers are immutable within FTL. That is, you can't add,
+          replace or remove the sub variables they contain.</para>
+        </section>
+
+        <section>
+          <title>Sequences</title>
+
+          <indexterm>
+            <primary>sequence</primary>
+
+            <secondary>Java side</secondary>
+          </indexterm>
+
+          <para>Sequences are java objects that implement
+          <literal>TemplateSequenceModel</literal>. It contains two methods:
+          <literal>TemplateModel get(int index)</literal> and <literal>int
+          size()</literal>.</para>
+
+          <para>The commonly used implementation is
+          <literal>SimpleSequence</literal>. It uses internally a
+          <literal>java.util.List</literal> to store its sub variables.
+          <literal>SimpleSequence</literal> has methods by which you can add
+          sub variables. These methods should be used to populate the sequence
+          directly after its creation.</para>
+        </section>
+
+        <section>
+          <title>Collections</title>
+
+          <indexterm>
+            <primary>collection</primary>
+
+            <secondary>Java side</secondary>
+          </indexterm>
+
+          <para>Collections are java objects that implement the
+          <literal>TemplateCollectionModel</literal> interface. That interface
+          has one method: <literal>TemplateModelIterator iterator()</literal>.
+          The <literal>TemplateModelIterator</literal> interface is similar to
+          <literal>java.util.Iterator</literal>, but it returns
+          <literal>TemplateModels</literal> instead of
+          <literal>Object</literal>-s, and it can throw
+          <literal>TemplateModelException</literal>s.</para>
+
+          <para>The commonly used implementation is
+          <literal>SimpleCollection</literal>.</para>
+        </section>
+      </section>
+
+      <section xml:id="pgui_datamodel_method">
+        <title>Methods</title>
+
+        <indexterm>
+          <primary>method</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <para>Method variables exposed to a template implement the
+        <literal>TemplateMethodModel</literal> interface. This contains one
+        method: <literal>TemplateModel exec(java.util.List
+        arguments)</literal>. When you call a method with a <link
+        linkend="dgui_template_exp_methodcall">method call expression</link>,
+        then the <literal>exec</literal> method will be called. The arguments
+        parameter will contain the values of the FTL method call arguments.
+        The return value of <literal>exec</literal> gives the value of the FTL
+        method call expression.</para>
+
+        <para>The <literal>TemplateMethodModelEx</literal> interface extends
+        <literal>TemplateMethodModel</literal>. It does not add any new
+        methods. The fact that the object implements this
+        <emphasis>marker</emphasis> interface indicates to the FTL engine that
+        the arguments should be put to the <literal>java.util.List</literal>
+        directly as <literal>TemplateModel</literal>-s. Otherwise they will be
+        put to the list as <literal>String</literal>-s.</para>
+
+        <para>For obvious reasons there is no default implementation for these
+        interfaces.</para>
+
+        <para>Example: This is a method, which returns the index within the
+        second string of the first occurrence of the first string, or -1 if
+        the second string doesn't contains the first.</para>
+
+        <programlisting role="unspecified">public class IndexOfMethod implements TemplateMethodModel {
+
+    public TemplateModel exec(List args) throws TemplateModelException {
+        if (args.size() != 2) {
+            throw new TemplateModelException("Wrong arguments");
+        }
+        return new SimpleNumber(
+            ((String) args.get(1)).indexOf((String) args.get(0)));
+    }
+}</programlisting>
+
+        <para>If you put an instance of this, say, into the root:</para>
+
+        <programlisting role="unspecified">root.put("indexOf", new IndexOfMethod());</programlisting>
+
+        <para>then you can call it in the template:</para>
+
+        <programlisting role="template">&lt;#assign x = "something"&gt;
+${indexOf("met", x)}
+${indexOf("foo", x)}</programlisting>
+
+        <para>and then the output will be:</para>
+
+        <programlisting role="output">2
+-1</programlisting>
+
+        <para>If you need to access the runtime FTL environment (read/write
+        variables, get the current locale, etc.), you can get it with
+        <literal>Environment.getCurrentEnvironment()</literal>.</para>
+      </section>
+
+      <section xml:id="pgui_datamodel_directive">
+        <title>Directives</title>
+
+        <indexterm>
+          <primary>directives</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <para>Java programmers can implement user-defined directives in Java
+        using the <literal>TemplateDirectiveModel</literal> interface. See in
+        the API documentation.</para>
+
+        <note>
+          <para><literal>TemplateDirectiveModel</literal> was introduced in
+          FreeMarker 2.3.11, replacing the soon to be depreciated
+          <literal>TemplateTransformModel</literal>.</para>
+        </note>
+
+        <section>
+          <title>Example 1</title>
+
+          <para>We will implement a directive which converts all output
+          between its start-tag and end-tag to upper case. Like, this
+          template:</para>
+
+          <programlisting role="template">foo
+<emphasis>&lt;@upper&gt;</emphasis>
+  bar
+  &lt;#-- All kind of FTL is allowed here --&gt;
+  &lt;#list ["red", "green", "blue"] as color&gt;
+    ${color}
+  &lt;/#list&gt;
+  baaz
+<emphasis>&lt;/@upper&gt;</emphasis>
+wombat</programlisting>
+
+          <para>will output this:</para>
+
+          <programlisting role="output">foo
+  BAR
+    RED
+    GREEN
+    BLUE
+  BAAZ
+wombat</programlisting>
+
+          <para>This is the source code of the directive class:</para>
+
+          <programlisting role="unspecified">package com.example;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+/**
+ *  FreeMarker user-defined directive that progressively transforms
+ *  the output of its nested content to upper-case.
+ *
+ *
+ *  &lt;p&gt;&lt;b&gt;Directive info&lt;/b&gt;&lt;/p&gt;
+ *
+ *  &lt;p&gt;Directive parameters: None
+ *  &lt;p&gt;Loop variables: None
+ *  &lt;p&gt;Directive nested content: Yes
+ */
+public class UpperDirective implements TemplateDirectiveModel {
+
+    public void execute(Environment env,
+            Map params, TemplateModel[] loopVars,
+            TemplateDirectiveBody body)
+            throws TemplateException, IOException {
+        // Check if no parameters were given:
+        if (!params.isEmpty()) {
+            throw new TemplateModelException(
+                    "This directive doesn't allow parameters.");
+        }
+        if (loopVars.length != 0) {
+                throw new TemplateModelException(
+                    "This directive doesn't allow loop variables.");
+        }
+
+        // If there is non-empty nested content:
+        if (body != null) {
+            // Executes the nested body. Same as &lt;#nested&gt; in FTL, except
+            // that we use our own writer instead of the current output writer.
+            body.render(new UpperCaseFilterWriter(env.getOut()));
+        } else {
+            throw new RuntimeException("missing body");
+        }
+    }
+
+    /**
+     * A {@link Writer} that transforms the character stream to upper case
+     * and forwards it to another {@link Writer}.
+     */
+    private static class UpperCaseFilterWriter extends Writer {
+
+        private final Writer out;
+
+        UpperCaseFilterWriter (Writer out) {
+            this.out = out;
+        }
+
+        public void write(char[] cbuf, int off, int len)
+                throws IOException {
+            char[] transformedCbuf = new char[len];
+            for (int i = 0; i &lt; len; i++) {
+                transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);
+            }
+            out.write(transformedCbuf);
+        }
+
+        public void flush() throws IOException {
+            out.flush();
+        }
+
+        public void close() throws IOException {
+            out.close();
+        }
+    }
+
+}</programlisting>
+
+          <para>Now we still need to create an instance of this class, and
+          make this directive available to the template with the name "upper"
+          (or with whatever name we want) somehow. A possible solution is to
+          put the directive in the data-model:</para>
+
+          <programlisting role="unspecified">root.put("upper", new com.example.UpperDirective());</programlisting>
+
+          <para>But typically it is better practice to put commonly used
+          directives into the <literal>Configuration</literal> as <link
+          linkend="pgui_config_sharedvariables">shared
+          variables</link>.</para>
+
+          <para>It is also possible to put the directive into an FTL library
+          (collection of macros and like in a template, that you
+          <literal>include</literal> or <literal>import</literal> in other
+          templates) using the <link
+          linkend="ref_builtin_new"><literal>new</literal>
+          built-in</link>:</para>
+
+          <programlisting role="template">&lt;#-- Maybe you have directives that you have implemented in FTL --&gt;
+&lt;#macro something&gt;
+  ...
+&lt;/#macro&gt;
+
+&lt;#-- Now you can't use &lt;#macro upper&gt;, but instead you can: --&gt;
+&lt;#assign upper = "com.example.UpperDirective"?new()&gt;
+</programlisting>
+        </section>
+
+        <section>
+          <title>Example 2</title>
+
+          <para>We will create a directive that executes its nested content
+          again and again for the specified number of times (similarly to
+          <literal>list</literal> directive), optionally separating the the
+          output of the repetations with a <literal>&lt;hr&gt;</literal>-s.
+          Let's call this directive "repeat". Example template:</para>
+
+          <programlisting role="template">&lt;#assign x = 1&gt;
+
+<emphasis>&lt;@repeat count=4&gt;</emphasis>
+  Test ${x}
+  &lt;#assign x++&gt;
+<emphasis>&lt;/@repeat&gt;</emphasis>
+
+<emphasis>&lt;@repeat count=3 hr=true&gt;</emphasis>
+  Test
+<emphasis>&lt;/@repeat&gt;</emphasis>
+
+<emphasis>&lt;@repeat count=3; cnt&gt;</emphasis>
+  ${cnt}. Test
+<emphasis>&lt;/@repeat&gt;</emphasis></programlisting>
+
+          <para>Output:</para>
+
+          <programlisting role="output">  Test 1
+  Test 2
+  Test 3
+  Test 4
+
+  Test
+&lt;hr&gt;  Test
+&lt;hr&gt;  Test
+
+  1. Test
+  2. Test
+  3. Test
+ </programlisting>
+
+          <para>The class:</para>
+
+          <programlisting role="unspecified">package com.example;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.Map;
+
+import freemarker.core.Environment;
+import freemarker.template.SimpleNumber;
+import freemarker.template.TemplateBooleanModel;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+/**
+ * FreeMarker user-defined directive for repeating a section of a template,
+ * optionally with separating the output of the repetations with
+ * &lt;tt&gt;&amp;lt;hr&gt;&lt;/tt&gt;-s.
+ *
+ *
+ * &lt;p&gt;&lt;b&gt;Directive info&lt;/b&gt;&lt;/p&gt;
+ *
+ * &lt;p&gt;Parameters:
+ * &lt;ul&gt;
+ *   &lt;li&gt;&lt;code&gt;count&lt;/code&gt;: The number of repetations. Required!
+ *       Must be a non-negative number. If it is not a whole number then it will
+ *       be rounded &lt;em&gt;down&lt;/em&gt;.
+ *   &lt;li&gt;&lt;code&gt;hr&lt;/code&gt;: Tells if a HTML "hr" element could be printed between
+ *       repetations. Boolean. Optional, defaults to &lt;code&gt;false&lt;/code&gt;.
+ * &lt;/ul&gt;
+ *
+ * &lt;p&gt;Loop variables: One, optional. It gives the number of the current
+ *    repetation, starting from 1.
+ *
+ * &lt;p&gt;Nested content: Yes
+ */
+public class RepeatDirective implements TemplateDirectiveModel {
+
+    private static final String PARAM_NAME_COUNT = "count";
+    private static final String PARAM_NAME_HR = "hr";
+
+    public void execute(Environment env,
+            Map params, TemplateModel[] loopVars,
+            TemplateDirectiveBody body)
+            throws TemplateException, IOException {
+
+        // ---------------------------------------------------------------------
+        // Processing the parameters:
+
+        int countParam = 0;
+        boolean countParamSet = false;
+        boolean hrParam = false;
+
+        Iterator paramIter = params.entrySet().iterator();
+        while (paramIter.hasNext()) {
+            Map.Entry ent = (Map.Entry) paramIter.next();
+
+            String paramName = (String) ent.getKey();
+            TemplateModel paramValue = (TemplateModel) ent.getValue();
+
+            if (paramName.equals(PARAM_NAME_COUNT)) {
+                if (!(paramValue instanceof TemplateNumberModel)) {
+                    throw new TemplateModelException(
+                            "The \"" + PARAM_NAME_HR + "\" parameter "
+                            + "must be a number.");
+                }
+                countParam = ((TemplateNumberModel) paramValue)
+                        .getAsNumber().intValue();
+                countParamSet = true;
+                if (countParam &lt; 0) {
+                    throw new TemplateModelException(
+                            "The \"" + PARAM_NAME_HR + "\" parameter "
+                            + "can't be negative.");
+                }
+            } else if (paramName.equals(PARAM_NAME_HR)) {
+                if (!(paramValue instanceof TemplateBooleanModel)) {
+                    throw new TemplateModelException(
+                            "The \"" + PARAM_NAME_HR + "\" parameter "
+                            + "must be a boolean.");
+                }
+                hrParam = ((TemplateBooleanModel) paramValue)
+                        .getAsBoolean();
+            } else {
+                throw new TemplateModelException(
+                        "Unsupported parameter: " + paramName);
+            }
+        }
+        if (!countParamSet) {
+                throw new TemplateModelException(
+                        "The required \"" + PARAM_NAME_COUNT + "\" paramter"
+                        + "is missing.");
+        }
+
+        if (loopVars.length &gt; 1) {
+                throw new TemplateModelException(
+                        "At most one loop variable is allowed.");
+        }
+
+        // Yeah, it was long and boring...
+
+        // ---------------------------------------------------------------------
+        // Do the actual directive execution:
+
+        Writer out = env.getOut();
+        if (body != null) {
+            for (int i = 0; i &lt; countParam; i++) {
+                // Prints a &lt;hr&gt; between all repetations if the "hr" parameter
+                // was true:
+                if (hrParam &amp;&amp; i != 0) {
+                    out.write("&lt;hr&gt;");
+                }
+
+                // Set the loop variable, if there is one:
+                if (loopVars.length &gt; 0) {
+                    loopVars[0] = new SimpleNumber(i + 1);
+                }
+
+                // Executes the nested body (same as &lt;#nested&gt; in FTL). In this
+                // case we don't provide a special writer as the parameter:
+                body.render(env.getOut());
+            }
+        }
+    }
+
+}</programlisting>
+        </section>
+
+        <section>
+          <title>Notices</title>
+
+          <para>It's important that a
+          <literal>TemplateDirectiveModel</literal> object usually should not
+          be stateful. The typical mistake is the storing of the state of the
+          directive call execution in the fields of the object. Think of
+          nested calls of the same directive, or directive objects used as
+          shared variables accessed by multiple threads concurrently.</para>
+
+          <para>Unfortunately, <literal>TemplateDirectiveModel</literal>-s
+          don't support passing parameters by position (rather than by name).
+          This is fixed starting from FreeMarker 2.4.</para>
+        </section>
+      </section>
+
+      <section xml:id="pgui_datamodel_node">
+        <title>Node variables</title>
+
+        <indexterm>
+          <primary>node</primary>
+
+          <secondary>Java side</secondary>
+        </indexterm>
+
+        <indexterm>
+          <primary>tree nodes</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>trees</primary>
+        </indexterm>
+
+        <para>A node variable embodies a node in a tree structure. Node
+        variables were introduced to help <link linkend="xgui">the handling of
+        XML documents in the data-model</link>, but they can be used for the
+        modeling of other tree structures as well. For more information about
+        nodes from the point of view of the template language <link
+        linkend="dgui_datamodel_node">read this earlier section</link>.</para>
+
+        <para>A node variable has the following properties, provided by the
+        methods of <literal>TemplateNodeModel</literal> interface:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>Basic properties:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal>TemplateSequenceModel
+                getChildNodes()</literal>: A node has sequence of children
+                (except if the node is a leaf node, in which case the method
+                return an empty sequence or null). The child nodes should be
+                node variables as well.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>TemplateNodeModel getParentNode()</literal>: A
+                node has exactly 1 parent node, except if the node is root
+                node of the tree, in which case the method returns
+                <literal>null</literal>.</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Optional properties. If a property does not make sense in
+            the concrete use case, the corresponding method should return
+            <literal>null</literal>:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal>String getNodeName()</literal>: The node name
+                is the name of the macro, that handles the node when you use
+                <link
+                linkend="ref.directive.recurse"><literal>recurse</literal></link>
+                and <link
+                linkend="ref.directive.visit"><literal>visit</literal></link>
+                directives. Thus, if you want to use these directives with the
+                node, the node name is <emphasis>required</emphasis>.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>String getNodeType()</literal>: In the case of
+                XML: <literal>"element"</literal>, <literal>"text"</literal>,
+                <literal>"comment"</literal>, ...etc. This information, if
+                available, is used by the <literal>recurse</literal> and
+                <literal>visit</literal> directives to find the default
+                handler macro for a node. Also it can be useful for other
+                application specific purposes.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>String getNamespaceURI()</literal>: The node
+                namespace (has nothing to do with FTL namespaces used for
+                libraries) this node belongs to. For example, in the case of
+                XML, this is the URI of the XML namespace the element or
+                attribute belongs to. This information, if available, is used
+                by the <literal>recurse</literal> and <literal>visit</literal>
+                directives to find the FTL namespaces that store the handler
+                macros.</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+        </itemizedlist>
+
+        <para>On the FTL side, the direct utilization of node properties is
+        done with <link linkend="ref_builtins_node">node built-ins</link>, and
+        with the <literal>visit</literal> and <literal>recurse</literal>
+        macros.</para>
+
+        <para>In most use cases, variables that implement
+        <literal>TemplateNodeModel</literal>, implement other interfaces as
+        well, since node variable properties just provide the basic
+        infrastructure for navigating between nodes. For a concrete example,
+        see <link linkend="xgui">how FreeMarker deals with XML</link>.</para>
+      </section>
+
+      <section xml:id="pgui_datamodel_objectWrapper">
+        <title>Object wrappers</title>
+
+        <indexterm>
+          <primary>object wrapper</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>wrapper</primary>
+        </indexterm>
+
+        <para>The object wrapper is an object that implements the
+        <literal>freemarker.template.ObjectWrapper</literal> interface. It's
+        purpose is to implement a mapping between Java objects (like
+        <literal>String</literal>-s, <literal>Map</literal>-s,
+        <literal>List</literal>-s, instances of your application specific
+        classes, etc.) and FTL's type system. With other words, it specifies
+        how the templates will see the Java objects of the data-model
+        (including the return value of Java methods called from the template).
+        The object wrapper is plugged into the
+        <literal>Configuration</literal> as its
+        <literal>object_wrapper</literal> setting (or with
+        <literal>Configuration.setObjectWrapper</literal>).</para>
+
+        <para>FTL's type system is technically represented by the
+        <literal>TemplateModel</literal> sub-interfaces that were introduced
+        earlier (<literal>TemplateScalarModel</literal>,
+        <literal>TemplateHashMode</literal>,
+        <literal>TemplateSequenceModel</literal>, etc). To map a Java object
+        to FTL's type system, object wrapper's <literal>TemplateModel
+        wrap(java.lang.Object obj)</literal> method will be called.</para>
+
+        <para>Sometimes FreeMarker needs to reverse this mapping, in which
+        case the <literal>ObjectWrapper</literal>'s <literal>Object
+        unwrap(TemplateModel)</literal> method is called (or some other
+        variation of that, but see the API documentation for such details).
+        This last operation is in
+        <literal>ObjectWrapperAndUnwrapper</literal>, the subinterface of
+        <literal>ObjectWrapper</literal>. Most real world object wrappers will
+        implement <literal>ObjectWrapperAndUnwrapper</literal>.</para>
+
+        <para>Here's how wrapping Java objects that contain other objects
+        (like a <literal>Map</literal>, a <literal>List</literal>, an array,
+        or an object with some JavaBean properties) usually work. Let's say,
+        an object wrapper wraps an <literal>Object[]</literal> array into some
+        implementation of the <literal>TemplateSquenceModel</literal>
+        interface. When FreeMarker needs an item from that FTL sequence, it
+        will call <literal>TemplateSquenceModel.get(int index)</literal>. The
+        return type of this method is <literal>TemplateModel</literal>, that
+        is, the <literal>TemplateSquenceModel</literal> implementation not
+        only have to get the <literal>Object</literal> from the given index of
+        the array, it's also responsible for wrapping that value before
+        returning it. To solve that, a typical
+        <literal>TemplateSquenceModel</literal> implementation will store the
+        <literal>ObjectWrapper</literal> that has cerated it, and then invoke
+        that <literal>ObjectWrapper</literal> to wrap the contained value. The
+        same logic stands for <literal>TemplateHashModel</literal> or for any
+        other <literal>TemplateModel</literal> that's a container for further
+        <literal>TemplateModel</literal>-s. Hence, usually, no mater how deep
+        the value hierarchy is, all values will be wrapped by the same single
+        <literal>ObjectWrapper</literal>. (To create
+        <literal>TemplateModel</literal> implementations that follow this
+        idiom, you can use the
+        <literal>freemarker.template.WrappingTemplateModel</literal> as base
+        class.)</para>
+
+        <para>The data-model itself (the root variable) is a
+        <literal>TemplateHashModel</literal>. The root object that you specify
+        to <literal>Template.process</literal> will be wrapped with the object
+        wrapper specified in the <literal>object_wrapper</literal>
+        configuration setting, which must yield a
+        <literal>TemplateHashModel</literal>. From then on, the wrapping of
+        the contained values follow the logic described earlier (i.e., the
+        container is responsible for wrapping its children).</para>
+
+        <para>Well behaving object wrappers bypass objects that already
+        implement <literal>TemplateModel</literal> as is. So if you put an
+        object into the data-model that already implements
+        <literal>TemplateModel</literal> (or you return as such object from a
+        Java method that's called from the template, etc.), then you can avoid
+        actual object wrapping. You do this usually when you are creating a
+        value specifically to be accessed from a template. Thus, you avoid
+        much of the object wrapping performance overhead, also you can control
+        exactly what will the template see (not depending on the mapping
+        strategy of the current object wrapper). A frequent application of
+        this trick is using a
+        <literal>freemarker.template.SimpleHash</literal> as the data-model
+        root (rather than a <literal>Map</literal>), by filling it with
+        <literal>SimpleHash</literal>'s <literal>put</literal> method (that's
+        important, so it won't have to copy an existing <literal>Map</literal>
+        that you have already filled). This speeds up top-level data-model
+        variable access.</para>
+
+        <section xml:id="pgui_datamodel_defaultObjectWrapper">
+          <title>The default object wrapper</title>
+
+          <indexterm>
+            <primary>object wrapper</primary>
+
+            <secondary>default</secondary>
+          </indexterm>
+
+          <indexterm>
+            <primary>DefaultObjectWrapper</primary>
+          </indexterm>
+
+          <para>The default of the <literal>object_wrapper</literal>
+          <literal>Configuration</literal> setting is a
+          <literal>freemarker.template.DefaultObjectWrapper</literal>
+          singleton. Unless you have very special requirements, it's
+          recommended to use this object wrapper, or an instance of a
+          <literal>DefaultObjectWrapper</literal> subclass of yours.</para>
+
+          <para>It recognizes most basic Java types, like
+          <literal>String</literal>, <literal>Number</literal>,
+          <literal>Boolean</literal>, <literal>Date</literal>,
+          <literal>List</literal> (and in general all kind of
+          <literal>java.util.Collection</literal>-s), arrays,
+          <literal>Map</literal>, etc., and wraps them into the naturally
+          matching <literal>TemplateModel</literal> interfaces. It will also
+          wrap W3C DOM nodes with
+          <literal>freemarker.ext.dom.NodeModel</literal>, so you can
+          conveniently traverse XML as <link linkend="xgui">described in its
+          own chapter</link>). For Jython objects, it will delegate to
+          <literal>freemarker.ext.jython.JythonWrapper</literal>. For all
+          other objects, it will invoke <literal>BeansWrapper.wrap</literal>
+          (the super class's method), which will expose the JavaBean
+          properties of the objects as hash items (like
+          <literal>myObj.foo</literal> in FTL will call
+          <literal>getFoo()</literal> behind the scenes), and will also expose
+          the public methods (JavaBean actions) of the object (like
+          <literal>myObj.bar(1, 2)</literal> in FTL will call a method). (For
+          more information about BeansWrapper, <link
+          linkend="pgui_misc_beanwrapper">see its own section</link>.)</para>
+
+          <para>Some further details that's worth mentioning about
+          <literal>DefaultObjectWrapper</literal>:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>You shouldn't use its constructor usually, instead create
+              it using a <literal>DefaultObjectWrapperBuilder</literal>. This
+              allows FreeMarker to use singletons.</para>
+            </listitem>
+
+            <listitem xml:id="topic.defaultObjectWrapperIcI">
+              <para><literal>DefaultObjectWrapper</literal> has an
+              <literal>incompatibleImprovements</literal> property, that's
+              highly recommended to set it to a high value (see the <link
+              xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/DefaultObjectWrapper.html#DefaultObjectWrapper-freemarker.template.Version-">API
+              documentation</link> for the effects). How to set it:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para>If you have set the
+                  <literal>incompatible_improvements</literal> setting
+                  <emphasis>of the <literal>Configuration</literal></emphasis>
+                  to 2.3.22 or higher, and you didn't set the
+                  <literal>object_wrapper</literal> setting (so it had
+                  remained on its default value), then you have to do nothing,
+                  as it already uses a <literal>DefaultObjectWrapper</literal>
+                  singleton with the equivalent
+                  <literal>incompatibleImprovements</literal> property
+                  value.</para>
+                </listitem>
+
+                <listitem xml:id="topic.setDefaultObjectWrapperIcIIndividually">
+                  <para>Otherwise you have to set the
+                  <literal>incompatibleImprovements</literal> independently of
+                  the <literal>Configuration</literal>. Depending on how you
+                  create/set the <literal>ObjectWrapper</literal>, it can be
+                  done like this:</para>
+
+                  <itemizedlist>
+                    <listitem>
+                      <para>If you are using the builder API:</para>
+
+                      <programlisting role="unspecified">... = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_27).build()</programlisting>
+                    </listitem>
+
+                    <listitem>
+                      <para>Or, if you are using the constructor:</para>
+
+                      <programlisting role="unspecified">... = new DefaultObjectWrapper(Configuration.VERSION_2_3_27)</programlisting>
+                    </listitem>
+
+                    <listitem>
+                      <para>Or, if you are using the
+                      <literal>object_wrapper</literal> property
+                      (<literal>*.properties</literal> file or
+                      <literal>java.util.Properties</literal> object):</para>
+
+                      <programlisting role="unspecified">object_wrapper=DefaultObjectWrapper(2.3.27)</programlisting>
+                    </listitem>
+
+                    <listitem>
+                      <para>Or, if you are configuring the
+                      <literal>object_wrapper</literal> through a
+                      <literal>FreemarkerServlet</literal> with an
+                      <literal>init-param</literal> in
+                      <literal>web.xml</literal>:</para>
+
+                      <programlisting role="unspecified">&lt;init-param&gt;
+    &lt;param-name&gt;object_wrapper&lt;/param-name&gt;
+    &lt;param-value&gt;DefaultObjectWrapper(2.3.27)&lt;/param-value&gt;
+&lt;/init-param&gt;</programlisting>
+                    </listitem>
+                  </itemizedlist>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para>In new or properly test-covered projects it's also
+              recommended to set the
+              <literal>forceLegacyNonListCollections</literal> property to
+              <literal>false</literal>. If you are using
+              <literal>.properties</literal> or
+              <literal>FreemarkerServlet</literal> init-params or such, that
+              will look like <literal>DefaultObjectWrapper(2.3.22,
+              forceLegacyNonListCollections=false)</literal>, while with the
+              Java API you call
+              <literal>setForceLegacyNonListCollections(false)</literal> on
+              the <literal>DefaultObjectWrapperBuilder</literal> object before
+              calling <literal>build()</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para>The most common way of customizing
+              <literal>DefaultObjectWrapper</literal> is overriding its
+              <literal>handleUnknownType</literal> method.</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section xml:id="pgui_datamodel_customObjectWrappingExample">
+          <title>Custom object wrapping example</title>
+
+          <indexterm>
+            <primary>object wrapper</primary>
+
+            <secondary>custom</secondary>
+          </indexterm>
+
+          <indexterm>
+            <primary>custom object wrapper</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>DefaultObjectWrapper</primary>
+
+            <secondary>extending</secondary>
+          </indexterm>
+
+          <para>Let's say you have an application-specific class like
+          this:</para>
+
+          <programlisting role="unspecified">package com.example.myapp;
+
+public class Tupple&lt;E1, E2&gt; {
+    public Tupple(E1 e1, E2 e2) { ... }
+    public E1 getE1() { ... }
+    public E2 getE2() { ... }
+}</programlisting>
+
+          <para>You want templates to see this as a sequence of length 2, so
+          that you can do things like <literal>someTupple[1]</literal>,
+          <literal>&lt;#list someTupple
+          <replaceable>...</replaceable>&gt;</literal>, or
+          <literal>someTupple?size</literal>. For that you need to create a
+          <literal>TemplateSequenceModel</literal> implementation that adapts
+          a <literal>Tupple</literal> to the
+          <literal>TempateSequenceMoldel</literal> interface:</para>
+
+          <programlisting role="unspecified">package com.example.myapp.freemarker;
+
+...
+
+public class TuppleAdapter extends WrappingTemplateModel implements TemplateSequenceModel,
+        AdapterTemplateModel {
+
+    private final Tupple&lt;?, ?&gt; tupple;
+
+    public TuppleAdapter(Tupple&lt;?, ?&gt; tupple, ObjectWrapper ow) {
+        super(ow);  // coming from WrappingTemplateModel
+        this.tupple = tupple;
+    }
+
+    @Override  // coming from TemplateSequenceModel
+    public int size() throws TemplateModelException {
+        return 2;
+    }
+
+    @Override  // coming from TemplateSequenceModel
+    public TemplateModel get(int index) throws TemplateModelException {
+        switch (index) {
+        case 0: return wrap(tupple.getE1());
+        case 1: return wrap(tupple.getE2());
+        default: return null;
+        }
+    }
+
+    @Override  // coming from AdapterTemplateModel
+    public Object getAdaptedObject(Class hint) {
+        return tupple;
+    }
+
+}</programlisting>
+
+          <para>Regarding the classes and interfaces:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>TemplateSequenceModel</literal>: This is why the
+              template will see this as a sequence</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>WrappingTemplateModel</literal>: Just a
+              convenience class, used for <literal>TemplateModel</literal>-s
+              that do object wrapping themselves. That's normally only needed
+              for objects that contain other objects. See the
+              <literal>wrap(<replaceable>...</replaceable>)</literal> calls
+              above.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>AdapterTemplateModel</literal>: Indicates that
+              this template model adapts an already existing object to a
+              <literal>TemplateModel</literal> interface, thus unwrapping
+              should give back that original object.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Lastly, we tell FreeMarker to wrap <literal>Tupple</literal>-s
+          with the <literal>TuppleAdapter</literal> (alternatively, you could
+          wrap them manually before passing them to FreeMarker). For that,
+          first we create a custom object wrapper:</para>
+
+          <programlisting role="unspecified">package com.example.myapp.freemarker;
+
+...
+
+public class MyAppObjectWrapper extends DefaultObjectWrapper {
+
+    public MyAppObjectWrapper(Version incompatibleImprovements) {
+        super(incompatibleImprovements);
+    }
+
+    @Override
+    protected TemplateModel handleUnknownType(final Object obj) throws TemplateModelException {
+        if (obj instanceof Tupple) {
+            return new TuppleAdapter((Tupple&lt;?, ?&gt;) obj, this);
+        }
+
+        return super.handleUnknownType(obj);
+    }
+
+}</programlisting>
+
+          <para>and then where you configure FreeMarker (<link
+          linkend="pgui_config">about configuring, see here...</link>) we plug
+          our object wrapper in:</para>
+
+          <programlisting role="unspecified">// Where you initialize the cfg *singleton* (happens just once in the application life-cycle):
+cfg = new Configuration(Configuration.VERSION_2_3_27);
+...
+cfg.setObjectWrapper(new MyAppObjectWrapper(cfg.getIncompatibleImprovements()));</programlisting>
+
+          <para>or if you are configuring FreeMarker with
+          <literal>java.util.Properties</literal> instead (and let's say it's
+          also a <literal>.properties</literal> file):</para>
+
+          <programlisting role="unspecified">object_wrapper=com.example.myapp.freemarker.MyAppObjectWrapper(2.3.27)</programlisting>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="pgui_config">
+      <title>The Configuration</title>
+
+      <indexterm>
+        <primary>Configuration</primary>
+      </indexterm>
+
+      <para>This is just an overview. See the <olink
+      targetdoc="api">FreeMarker Java API documentation</olink> for the
+      details.</para>
+
+      <section xml:id="pgui_config_basics">
+        <title>Basics</title>
+
+        <para>First of all, be sure you have read the <link
+        linkend="pgui_quickstart_createconfiguration">Getting Started</link>
+        chapter.</para>
+
+        <para>A configuration is a
+        <literal>freemarker.template.Configuration</literal> object that
+        stores your common (global, application level) settings and defines
+        variables that you want to be available in all templates (so called
+        shared variables). Also, it deals with the creation and caching of
+        <literal>Template</literal> instances.</para>
+
+        <para>An application typically uses only a single shared
+        <literal>Configuration</literal> instance. More precisely, typically
+        you have one <literal>Configuration</literal> instance per
+        independently developed component that internally uses FreeMarker, so
+        they can be configured independently of each other. For example, your
+        e-mail sender component and your report generator component (service)
+        probably want to use their own <literal>Configuration</literal>-s, as
+        their needs differ.</para>
+
+        <para>As the behavior of templates depends on the configuration
+        settings, each <literal>Template</literal> instance has an associated
+        <literal>Configuration</literal> instance. If you obtain the
+        <literal>Template</literal> instances with
+        <literal>Configuration.getTemplate</literal>, the associated
+        <literal>Configuration</literal> instance will be the one whose
+        <literal>getTemplate</literal> method was called. If you create the
+        <literal>Template</literal> instances directly with the
+        <literal>Template</literal> constructor, the
+        <literal>Configuration</literal> should be specified as constructor
+        parameter.</para>
+      </section>
+
+      <section xml:id="pgui_config_sharedvariables">
+        <title>Shared variables</title>
+
+        <indexterm>
+          <primary>shared variable</primary>
+        </indexterm>
+
+        <para><emphasis role="term">Shared variables</emphasis> are variables
+        that are defined for all templates. You can add shared variables to
+        the configuration with the <literal>setSharedVariable</literal>
+        methods:</para>
+
+        <programlisting role="unspecified">Configuration cfg = new Configuration(Configuration.VERSION_2_3_27);
+<replaceable>..</replaceable>.
+cfg.setSharedVariable("warp", new WarpDirective());
+cfg.setSharedVariable("company", "Foo Inc.");</programlisting>
+
+        <para>In all templates that use this configuration, an user-defined
+        directive with name <literal>wrap</literal> and a string with name
+        <literal>company</literal> will be visible in the data-model root, so
+        you don't have to add them to the root hash again and again. A
+        variable in the root object that you pass to the
+        <literal>Template.process</literal> will hide the shared variable with
+        the same name.</para>
+
+        <warning>
+          <para>Never use <literal>TemplateModel</literal> implementation that
+          is not <link linkend="gloss.threadSafe">thread-safe</link> for
+          shared variables, if the configuration is used by multiple threads!
+          This is the typical situation for Servlet based applications.</para>
+        </warning>
+
+        <para>Due to backward compatibility heritage, the set of shared
+        variables is initially (i.e., for a new
+        <literal>Configuration</literal> instance) not empty. It contains the
+        following user-defined directives (they are "user-defined" in the
+        sense that you use <literal>@</literal> to call them instead of
+        <literal>#</literal>):</para>
+
+        <informaltable border="1">
+          <thead>
+            <tr>
+              <th>name</th>
+
+              <th>class</th>
+            </tr>
+          </thead>
+
+          <tbody>
+            <tr>
+              <td><literal>capture_output</literal></td>
+
+              <td><literal>freemarker.template.utility.CaptureOutput</literal></td>
+            </tr>
+
+            <tr>
+              <td><literal>compress</literal></td>
+
+              <td><literal>freemarker.template.utility.StandardCompress</literal></td>
+            </tr>
+
+            <tr>
+              <td><literal>html_escape</literal></td>
+
+              <td><literal>freemarker.template.utility.HtmlEscape</literal></td>
+            </tr>
+
+            <tr>
+              <td><literal>normalize_newlines</literal></td>
+
+              <td><literal>freemarker.template.utility.NormalizeNewlines</literal></td>
+            </tr>
+
+            <tr>
+              <td><literal>xml_escape</literal></td>
+
+              <td><literal>freemarker.template.utility.XmlEscape</literal></td>
+            </tr>
+          </tbody>
+        </informaltable>
+      </section>
+
+      <section xml:id="pgui_config_settings">
+        <title>Settings</title>
+
+        <indexterm>
+          <primary>setting</primary>
+        </indexterm>
+
+        <para><emphasis role="term">Settings</emphasis> are named values that
+        influence the behavior of FreeMarker. Examples of settings are:
+        <literal>locale</literal>, <literal>number_format</literal>,
+        <literal>default_encoding</literal>,
+        <literal>template_exception_handler</literal>. The full list of
+        settings can be found in the <olink
+        targetdoc="apiConfigurationSettings">Java API documentation of
+        <literal>Configuration.setSetting(...)</literal></olink>.</para>
+
+        <para>The settings coming from the <literal>Configuration</literal>
+        can be overridden in a <literal>Template</literal> instance. For
+        example, if you set the <literal>locale</literal> setting to
+        <literal>"en_US"</literal> in the configuration, then the
+        <literal>locale</literal> in all templates that use this configuration
+        will be <literal>"en_US"</literal>, except in templates where the
+        <literal>locale</literal> was explicitly specified differently (see
+        <link linkend="ref_directive_include_localized">localization</link>).
+        Thus, the setting values in the <literal>Configuration</literal> serve
+        as defaults that can be overridden in a per template manner. The value
+        coming from the <literal>Configuration</literal> instance or
+        <literal>Template</literal> instance can be further overridden for a
+        single <literal>Template.process</literal> call. For each such call a
+        <literal>freemarker.core.Environment</literal> object is created
+        internally that holds the runtime environment of the template
+        processing, including the setting values that were overridden on that
+        level. The values stored there can even be changed during the template
+        processing, so a template can set settings itself, like switching
+        <literal>locale</literal> at the middle of the ongoing
+        processing.</para>
+
+        <para>This can be imagined as 3 layers
+        (<literal>Configuration</literal>, <literal>Template</literal>,
+        <literal>Environment</literal>) of settings, where the topmost layer
+        that contains the value for a certain setting provides the effective
+        value of that setting. For example (settings A to F are just imaginary
+        settings for this example):</para>
+
+        <informaltable border="1">
+          <col align="left"/>
+
+          <col align="center" span="6"/>
+
+          <thead>
+            <tr>
+              <th/>
+
+              <th>Setting A</th>
+
+              <th>Setting B</th>
+
+              <th>Setting C</th>
+
+              <th>Setting D</th>
+
+              <th>Setting E</th>
+
+              <th>Setting F</th>
+            </tr>
+          </thead>
+
+          <tbody>
+            <tr>
+              <td>Layer 3: <literal>Environment</literal></td>
+
+              <td>1</td>
+
+              <td>-</td>
+
+              <td>-</td>
+
+              <td>1</td>
+
+              <td>-</td>
+
+              <td>-</td>
+            </tr>
+
+            <tr>
+              <td>Layer 2: <literal>Template</literal></td>
+
+              <td>2</td>
+
+              <td>2</td>
+
+              <td>-</td>
+
+              <td>-</td>
+
+              <td>2</td>
+
+              <td>-</td>
+            </tr>
+
+            <tr>
+              <td>Layer 1: <literal>Configuration</literal></td>
+
+              <td>3</td>
+
+              <td>3</td>
+
+              <td>3</td>
+
+              <td>3</td>
+
+              <td>-</td>
+
+              <td>-</td>
+            </tr>
+          </tbody>
+        </informaltable>
+
+        <para>The effective value of settings will be: A = 1, B = 2, C = 3, D
+        = 1, E = 2. The F setting is probably <literal>null</literal>, or it
+        throws exception when you try to get it.</para>
+
+        <para>Let's see exactly how to set settings:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><literal>Configuration</literal> layer: In principle you set
+            the settings with the setter methods of the
+            <literal>Configuration</literal> object, fore example:</para>
+
+            <programlisting role="unspecified">Configuration myCfg = new Configuration(Configuration.VERSION_2_3_27);
+myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+myCfg.setDefaultEncoding("UTF-8");
+DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_27);
+owb.setForceLegacyNonListCollections(false);
+owb.setDefaultDateType(TemplateDateModel.DATETIME);
+myCfg.setObjectWrapper(owb.build());</programlisting>
+
+            <para>You do this before you start to actually use the
+            <literal>Configuration</literal> object (typically, when you
+            initialize the application); you should treat the object as
+            read-only after that.</para>
+
+            <para>In practice, in most frameworks you have to specify the
+            settings in some kind of framework-specific configuration file
+            that require specifying settings as <literal>String</literal>
+            name-value pairs (like in a <literal>.properties</literal> file).
+            In that case the authors of the frameworks most probably use the
+            <literal>Confguration.setSetting(String name, String
+            value)</literal> method; see available setting names and the
+            format of the values in the <link
+            xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setSetting-java.lang.String-java.lang.String-">API
+            documentation of <literal>setSetting</literal></link>. Example for
+            Spring Framework:</para>
+
+            <programlisting role="unspecified">&lt;bean id="freemarkerConfig"
+    class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"&gt;
+  &lt;property name="freemarkerSettings"&gt;
+    &lt;props&gt;
+      &lt;prop key="incompatible_improvements"&gt;2.3.27&lt;/prop&gt;
+      &lt;prop key="template_exception_handler"&gt;rethrow&lt;/prop&gt;
+      &lt;prop key="default_encoding"&gt;UTF-8&lt;/prop&gt;
+      &lt;prop key="object_wrapper"&gt;
+        DefaultObjectWrapper(
+                2.3.27,
+                forceLegacyNonListCollections = false,
+                defaultDateType = freemarker.template.TemplateDateModel.DATETIME)
+      &lt;/prop&gt;
+    &lt;/props&gt;
+  &lt;/property&gt;
+&lt;/bean&gt;</programlisting>
+
+            <para>Here's the same when configuring FreeMarker for Struts,
+            which looks for a <literal>freemarker.properties</literal> in the
+            classpath:</para>
+
+            <programlisting role="unspecified">incompatible_improvements=2.3.27
+template_exception_handler=rethrow
+default_encoding=UTF-8
+object_wrapper=DefaultObjectWrapper( \
+        2.3.27, \
+        forceLegacyNonListCollections = false, \
+        defaultDateType = freemarker.template.TemplateDateModel.DATETIME)</programlisting>
+
+            <para>As demonstrated above with
+            <literal>object_wrapper</literal>, some settings can accept quite
+            complex values, which can be used to instantiate objects of
+            arbitrary classes and set their properties. Still, configuring
+            with <literal>String</literal> key-value pairs is limited compared
+            to directly using the Java API, so in some cases you have to find
+            a way to do this in Java.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>Template</literal> layer: Settings on individual
+            templates are normally set by <link
+            linkend="pgui_config_templateconfigurations">template
+            configurations (see them in their own chapter)</link>, which
+            basically associate setting assignments to template name (template
+            path) patterns. There's a deviation from this approach with the
+            <literal>locale</literal> setting, because that you can also
+            specify to <literal>Configuration.getTemplate(...)</literal> as
+            parameter, to get the template for the requested locale (so called
+            localized lookup).</para>
+
+            <warning>
+              <para>You should never set settings directly on the
+              <literal>Template</literal> object that you get from
+              <literal>Configuration.getTemplate(...)</literal>! Those objects
+              should be treated as already initialized and read-only.</para>
+            </warning>
+
+            <para>When a template includes or imports another template, most
+            of the settings (like <literal>locale</literal>,
+            <literal>number_format</literal>, etc.) will remain those
+            specified by the top-level template. The exceptions are the
+            settings that affect the parsing of the template (like
+            <literal>tag_syntax</literal>,
+            <literal>whitespace_stripping</literal>, etc.), as these are not
+            inherited from the top-level template, instead each template
+            always uses its own values, no mater how it was invoked.</para>
+
+            <note>
+              <para>If you are going to use template layer settings, you
+              should set <link
+              linkend="pgui_config_incompatible_improvements">the
+              <literal>incompatible_improvements</literal> setting</link> to
+              2.3.22 or higher, to avoid some confusing legacy bugs.</para>
+            </note>
+          </listitem>
+
+          <listitem>
+            <para><literal>Environment </literal>layer: There are two ways of
+            doing it:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>With Java API: Use the setter methods of the
+                <literal>Environment</literal> object. You may run into the
+                API problem that <literal>myTemplate.process(...)</literal>
+                both creates the <literal>Environment</literal> object
+                internally and processes the template, so you have no
+                opportunity to adjust the <literal>Environment</literal> in
+                between. The solution is that those two steps can be separated
+                like this:</para>
+
+                <programlisting role="unspecified">Environment env = myTemplate.createProcessingEnvironment(root, out);
+env.setLocale(java.util.Locale.ITALY);
+env.setNumberFormat("0.####");
+env.process();  // process the template</programlisting>
+              </listitem>
+
+              <listitem>
+                <para>Directly in the Template (considered as bad style,
+                usually): Use the <link
+                linkend="ref.directive.setting"><literal>setting</literal>
+                directive</link>, for example:</para>
+
+                <programlisting role="template">&lt;#setting locale="it_IT"&gt;
+&lt;#setting number_format="0.####"&gt;</programlisting>
+              </listitem>
+            </itemizedlist>
+
+            <para>There are no restriction regarding when can you change the
+            settings in this layer.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>To see the list of supported settings and their meaning, please
+        read the following parts of the FreeMarker Java API
+        documentation:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>Setter methods of
+            <literal>freemarker.core.Configurable</literal> for the settings
+            that are in all three layers</para>
+          </listitem>
+
+          <listitem>
+            <para>Setter methods of
+            <literal>freemarker.template.Configuration</literal> for the
+            settings that are available only in the
+            <literal>Configuration</literal> layer</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>freemarker.core.Configurable.setSetting(String,
+            String)</literal> for settings that are available in all three
+            layers and are writable with <literal>String</literal> key-value
+            pairs.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>freemarker.template.Configuration.setSetting(String,
+            String)</literal> for settings that are available only in the
+            <literal>Configuration</literal> layer and are writable with
+            <literal>String</literal> key-value pairs.</para>
+          </listitem>
+        </itemizedlist>
+      </section>
+
+      <section xml:id="pgui_config_templateloading">
+        <title>Template loading</title>
+
+        <indexterm>
+          <primary>loading templates</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>template loading</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>storing templates</primary>
+        </indexterm>
+
+        <section>
+          <title>Template loaders</title>
+
+          <indexterm>
+            <primary>template loaders</primary>
+          </indexterm>
+
+          <para>Template loaders are objects that load raw textual data based
+          on abstract template paths like <literal>"index.ftl"</literal> or
+          <literal>"products/catalog.ftl"</literal>. It's up to the concrete
+          template loader if from where and how the template
+          <quote>files</quote> are loaded. They could be real files inside a
+          specified directory, or values in a data base table, or
+          <literal>String</literal>-s in a Java Map, etc. When you call
+          <literal>cfg.getTemplate</literal> (where <literal>cfg</literal> is
+          a <literal>Configuration</literal> instance), FreeMarker asks the
+          template loader (<literal>cfg.getTemplateLoader</literal>) to return
+          the text for the given template path, and then FreeMarker parses
+          that text as template. It doesn't care or even know if the template
+          is a real file or not, and where it is physically; those details are
+          only known by the template loader.</para>
+
+          <section>
+            <title>Built-in template loaders</title>
+
+            <para>You can set up the three most common template loading
+            mechanism in the <literal>Configuration</literal> using the
+            following <emphasis>convenience</emphasis> methods:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal>void setDirectoryForTemplateLoading(File
+                dir)</literal>: Sets a directory on the file system from which
+                to load templates. Template names (template paths) will be
+                interpreted relatively to this physical directory. It won't
+                let you load files outside this directory.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>void setClassForTemplateLoading(Class cl,
+                String basePackagePath)</literal> and <literal>void
+                setClassLoaderForTemplateLoading(ClassLoader classLoader,
+                String basePackagePath)</literal>: These are for when you want
+                to load templates via the same mechanism with which Java loads
+                classes (from the class-path, as they used to say vaguely).
+                This is very likely be the preferred means of loading
+                templates for production code, as it allows you to keep
+                everything inside the deployment <literal>jar</literal> files.
+                The first parameter decides which Java
+                <literal>ClassLoader</literal> will be used. The second
+                parameter specifies the package that contains the templates,
+                in <literal>/</literal>-separated format. Note that if you
+                don't start it with <literal>/</literal>, it will be
+                interpreted relatively to the package of the
+                <literal>Class</literal> parameter.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>void setServletContextForTemplateLoading(Object
+                servletContext, String path)</literal>: Takes the context of
+                your Servlet-based web application, and a base path, which is
+                interpreted relative to the web application root directory
+                (that's the parent of the <literal>WEB-INF</literal>
+                directory). Note that we refer to "directory" here although
+                this loading method works even for unpacked
+                <literal>.war</literal> files, since it uses
+                <literal>ServletContext.getResource()</literal> to access the
+                templates. If you omit the second parameter (or use
+                <literal>""</literal>), you can simply store the static files
+                (<literal>.html</literal>, <literal>.jpg</literal>, etc.)
+                mixed with the <literal>.ftl</literal> files. Of course, you
+                must set up a Servlet for the <literal>*.ftl</literal>,
+                <literal>*.ftlh</literal>, <literal>*.ftlx</literal>
+                uri-patterns in <literal>WEB-INF/web.xml</literal> for this,
+                otherwise the client will get the raw templates as is! To
+                avoid a such accident, many prefers storing the templates
+                somewhere inside the <literal>WEB-INF</literal> directory,
+                which is never visitable directly. This mechanism will very
+                likely be the preferred means of loading templates for servlet
+                applications, since the templates can be updated without
+                restarting the web application, while this often doesn't work
+                with the class-loader mechanism.</para>
+              </listitem>
+            </itemizedlist>
+
+            <para>If you want to use a custom
+            <literal>TemplateLoader</literal> implementation, or need to set
+            up some extra settings of a built-in template loader, you need to
+            instantiate the <literal>TemplateLoader</literal> object yourself,
+            and then call
+            <literal>Configuration.setTemplateLoader(TemplateLoader)</literal>:</para>
+
+            <programlisting role="unspecified">WebappTemplateLoader templateLoader = new WebappTemplateLoader(servletContext, "WEB-INF/templates");
+templateLoader.setURLConnectionUsesCaches(false);
+templateLoader.setAttemptFileAccess(false);
+cfg.setTemplateLoader(templateLoader);</programlisting>
+          </section>
+
+          <section>
+            <title>Loading templates from multiple locations</title>
+
+            <para>If you need to load templates from multiple locations, you
+            have to instantiate the template loader objects for every
+            location, wrap them into a <literal>MultiTemplateLoader</literal>,
+            and finally pass that loader to the
+            <literal>setTemplateLoader(TemplateLoader loader)</literal> method
+            of <literal>Configuration</literal>. Here's an example for loading
+            templates from two distinct directories and with the
+            class-loader:</para>
+
+            <programlisting role="unspecified">import freemarker.cache.*; // template loaders live in this package
+
+<replaceable>...</replaceable>
+
+FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates"));
+FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates"));
+ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "/com/example/templates");
+
+MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { ftl1, ftl2, ctl });
+
+cfg.setTemplateLoader(mtl);</programlisting>
+
+            <para>Now FreeMarker will try to load templates from
+            <literal>/tmp/templates</literal> directory, and if it does not
+            find the requested template there, it will try to load that from
+            <literal>/usr/data/templates</literal>, and if it still does not
+            find the requested template, then it tries to load it from the
+            <literal>com.example.templates</literal> Java package.</para>
+          </section>
+
+          <section>
+            <title>Loading templates from other sources</title>
+
+            <para>If none of the built-in class loaders fit your needs, you
+            can write your own class that implements the
+            <literal>freemarker.cache.TemplateLoader</literal> interface and
+            pass it to the <literal>setTemplateLoader(TemplateLoader
+            loader)</literal> method of <literal>Configuration</literal>.
+            Please read the API JavaDoc for more information.</para>
+
+            <para>If your template source accesses the templates through an
+            URL, you needn't implement a <literal>TemplateLoader</literal>
+            from scratch; you can choose to subclass
+            <literal>freemarker.cache.URLTemplateLoader</literal> instead and
+            just implement the <literal>URL getURL(String
+            templateName)</literal> method.</para>
+          </section>
+
+          <section>
+            <title>The template name (template path)</title>
+
+            <indexterm>
+              <primary>path</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>template path</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>template name</primary>
+            </indexterm>
+
+            <para>It is up to the template loader how it interprets template
+            names (also known as template paths). But to work together with
+            other components there are restrictions regarding the format of
+            the path. In general, it is strongly recommended that template
+            loaders use URL-style paths. The path must not use
+            <literal>/</literal> (path step separator) character, nor the
+            <literal>.</literal> (same-directory) and <literal>..</literal>
+            (parent directory) path steps with other meaning than they have in
+            URL paths (or in UN*X paths). The <literal>*</literal> (asterisk)
+            step is also reserved, and used for <quote>template
+            acquisition</quote> feature of FreeMarker.</para>
+
+            <para><literal>://</literal> (or with
+            <literal>template_name_format</literal> setting set to
+            <literal>DEFAULT_2_4_0</literal>, the <literal>:</literal> (colon)
+            character) is reserved for specifying a scheme part, similarly as
+            it works with URI-s. For example
+            <literal>someModule://foo/bar.ftl</literal> uses the
+            <literal>someModule</literal>, or assuming the
+            <literal>DEFAULT_2_4_0</literal> format,
+            <literal>classpath:foo/bar.ftl</literal> uses the
+            <literal>classpath</literal> scheme. Interpreting the scheme part
+            is completely up to the <literal>TemplateLoader</literal>. (The
+            FreeMarker core is only aware of the idea of schemes because
+            otherwise it couldn't resolve relative template names
+            properly.)</para>
+
+            <para>FreeMarker always normalizes the paths before passing them
+            to the <literal>TemplateLoader</literal>, so the paths don't
+            contain <literal>/../</literal> or such, and are relative to the
+            imaginary template root directory (that is, they don't start with
+            <literal>/</literal>). They don't contain the <literal>*</literal>
+            step either, as template acquisition happens in an earlier stage.
+            Furthermore, with <literal>template_name_format</literal> setting
+            set to <literal>DEFAULT_2_4_0</literal>, multiple consecutive
+            <literal>/</literal>-s will be normalized to a single
+            <literal>/</literal> (unless they are part of the
+            <literal>://</literal> scheme separator).</para>
+
+            <para>Note that FreeMarker template path should always uses slash
+            (not backslash) regardless of the host OS.</para>
+          </section>
+        </section>
+
+        <section xml:id="pgui_config_templateloading_caching">
+          <title>Template caching</title>
+
+          <indexterm>
+            <primary>caching</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>template caching</primary>
+          </indexterm>
+
+          <para>FreeMarker caches templates (assuming you use the
+          <literal>Configuration</literal> methods to create
+          <literal>Template</literal> objects). This means that when you call
+          <literal>getTemplate</literal>, FreeMarker not only returns the
+          resulting <literal>Template</literal> object, but stores it in a
+          cache, so when next time you call <literal>getTemplate</literal>
+          with the same (or equivalent) path, it just returns the cached
+          <literal>Template</literal> instance, and will not load and parse
+          the template file again.</para>
+
+          <para>If you change the template file, then FreeMarker will re-load
+          and re-parse the template automatically when you get the template
+          next time. However, since always checking for changes can be burden
+          for a system that processes lot of templates, there is a
+          <literal>Configuration</literal> level setting called <quote>update
+          delay</quote> (defaults is 5 seconds). Until this much time has
+          elapsed since the last checking for a newer version, FreeMarker will
+          not check again if the template was changed. If you want to see the
+          changes without delay, set this setting to 0. Note that some
+          template loaders won't see that a template was changed because of
+          the underlying storage mechanism doesn't support that; for example,
+          class-loader based template loaders may have this problem.</para>
+
+          <para>A template will be removed from the cache if you call
+          <literal>getTemplate</literal> and FreeMarker realizes that the
+          template file has been removed meanwhile. Also, if the JVM thinks
+          that it begins to run out of memory, by default it can arbitrarily
+          drop templates from the cache. Furthermore, you can empty the cache
+          manually with the <literal>clearTemplateCache</literal> method of
+          <literal>Configuration</literal>. You can also drop selected
+          template from the cache with
+          <literal>removeTemplateFromCache</literal>; this can be also
+          utilized to force re-loading a template regardless of the
+          <quote>update delay</quote> setting.</para>
+
+          <para>The actual strategy of when a cached template should be thrown
+          away is pluggable with the <literal>cache_storage</literal> setting,
+          by which you can plug any <literal>CacheStorage</literal>
+          implementation. For most users
+          <literal>freemarker.cache.MruCacheStorage</literal> will be
+          sufficient. This cache storage implements a two-level Most Recently
+          Used cache. In the first level, items are strongly referenced up to
+          the specified maximum (strongly referenced items can't be dropped by
+          the JVM, as opposed to softly referenced items). When the maximum is
+          exceeded, the least recently used item is moved into the second
+          level cache, where they are softly referenced, up to another
+          specified maximum. The size of the strong and soft parts can be
+          specified with the constructor. For example, set the size of the
+          strong part to 20, and the size of soft part to 250:</para>
+
+          <programlisting role="unspecified">cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250))</programlisting>
+
+          <para>Or, since <literal>MruCacheStorage</literal> is the default
+          cache storage implementation:</para>
+
+          <programlisting role="unspecified">cfg.setSetting(Configuration.CACHE_STORAGE_KEY, "strong:20, soft:250");</programlisting>
+
+          <para>When you create a new <literal>Configuration</literal> object,
+          initially it uses an <literal>MruCacheStorage</literal> where
+          <literal>strongSizeLimit</literal> is 0, and
+          <literal>softSizeLimit</literal> is
+          <literal>Integer.MAX_VALUE</literal> (that is, in practice,
+          infinite). Depending on how smart the JVM is, using non-0
+          <literal>strongSizeLimit</literal> is maybe a safer option, as with
+          only softly referenced items the JVM could even throw the most
+          frequently used templates when there's a resource shortage, which
+          then have to be re-loaded and re-parsed, burdening the system even
+          more.</para>
+        </section>
+      </section>
+
+      <section xml:id="pgui_config_errorhandling">
+        <title>Error handling</title>
+
+        <indexterm>
+          <primary>error handling</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>exception handling</primary>
+        </indexterm>
+
+        <section>
+          <title>The possible exceptions</title>
+
+          <para>The exceptions that can occur regarding FreeMarker could be
+          classified like this:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Exceptions occurring when you configure FreeMarker:
+              Typically you configure FreeMarker only once in your
+              application, when your application initializes itself. Of
+              course, during this, exceptions can occur.</para>
+            </listitem>
+
+            <listitem>
+              <para>Exceptions occurring when loading and parsing templates:
+              When you call
+              <literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>,
+              FreeMarker has to load the template into the memory and parse it
+              (unless the template is already <link
+              linkend="pgui_config_templateloading_caching">cached</link> in
+              that <literal>Configuration</literal> object). During this,
+              these kind of exceptions can occur:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para><literal>TemplateNotFoundException</literal> because
+                  the requested template doesn't exist. Note this extends
+                  <literal>IOException</literal>.</para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>freemarker.core.ParseException</literal>
+                  because the template is syntactically incorrect according
+                  the rules of the FTL language. Note that this error occurs
+                  when you obtain the <literal>Template</literal> object
+                  (<literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>),
+                  not later when you execute
+                  (<literal>Template.process(<replaceable>...</replaceable>)</literal>)
+                  the template. . Note this extends
+                  <literal>IOException</literal> (legacy).</para>
+                </listitem>
+
+                <listitem>
+                  <para>Any other kind of <literal>IOException</literal>
+                  because an error has occurred while reading an existing
+                  template. For example you have no right to read the file, or
+                  the connection through which you read the template is
+                  broken. The emitter of these is the <link
+                  linkend="pgui_config_templateloading"><literal>TemplateLoader</literal>
+                  object</link>, which is plugged into the
+                  <literal>Configuration</literal> object.</para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para>Exceptions occurring when executing (processing)
+              templates, that is, when you call
+              <literal>Template.process(<replaceable>...</replaceable>)</literal>.
+              Two kind of exceptions can occur:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para><literal>IOException</literal> because there was an
+                  error when trying to write into the output writer.</para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>freemarker.template.TemplateException</literal>
+                  because other problem occurred while executing the template.
+                  For example, a frequent error is referring to a variable
+                  that doesn't exist in the data-model. By default, when a
+                  <literal>TemplateException</literal> occurs, FreeMarker
+                  prints the FTL error message and the stack trace to the
+                  output writer with plain text format, and then aborts the
+                  template execution by re-throwing the
+                  <literal>TemplateException</literal>, which then you can
+                  catch as
+                  <literal>Template.process(<replaceable>...</replaceable>)</literal>
+                  throws it. This behavior can be customized, and in fact, it
+                  should be; see the recommended configuration <link
+                  linkend="pgui_quickstart_createconfiguration">here</link>.
+                  By default FreeMarker also <link
+                  linkend="pgui_misc_logging">logs</link>
+                  <literal>TemplateException</literal>-s.</para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section>
+          <title>Customizing the behavior regarding
+          TemplateException-s</title>
+
+          <para><literal>TemplateException</literal>-s thrown during the
+          template processing are handled by the
+          <literal>freemarker.template.TemplateExceptionHandler</literal>
+          object, which is plugged into the <literal>Configuration</literal>
+          object with its
+          <literal>setTemplateExceptionHandler(<replaceable>...</replaceable>)</literal>
+          method. These are the <literal>TemplateExceptionHandler</literal>
+          implementations with FreeMarker comes with:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>TemplateExceptionHandler.DEBUG_HANDLER</literal>:
+              Prints stack trace (includes FTL error message and FTL stack
+              trace) and re-throws the exception. This is the default handler,
+              however, you should be careful not using it in production
+              environment, as it shows technical information about your
+              system.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>TemplateExceptionHandler.HTML_DEBUG_HANDLER</literal>:
+              Same as <literal>DEBUG_HANDLER</literal>, but it formats the
+              stack trace so that it will be readable with Web browsers.
+              Recommended over <literal>DEBUG_HANDLER</literal> when you
+              generate HTML pages, but it should only be used for development
+              as it shows technical information about your system.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>TemplateExceptionHandler.IGNORE_HANDLER</literal>:
+              Simply suppresses all exceptions (though FreeMarker will still
+              log them if
+              <literal>Configuration.getLogTemplateExceptions</literal> is
+              <literal>true</literal>). It does nothing to handle the event.
+              It does not re-throw the exception.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>TemplateExceptionHandler.RETHROW_HANDLER</literal>:
+              Simply re-throws all exceptions; it doesn't do anything else.
+              This should be used in most applications today. It doesn't print
+              anything to the output about the error, which makes it safe, and
+              the developers can still get the error details from the logs.
+              It's not as convenient during template development as
+              <literal>HTML_DEBUG_HANDLER</literal> or
+              <literal>DEBUG_HANDLER</literal> though. For more information
+              about handling errors in Web applications <link
+              linkend="misc.faq.niceErrorPage">see the FAQ</link>.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>You can also write a custom
+          <literal>TemplateExceptionHandler</literal> by implementing that
+          interface, which contains this method:</para>
+
+          <programlisting role="unspecified">void handleTemplateException(TemplateException te, Environment env, Writer out)
+        throws TemplateException;</programlisting>
+
+          <para>Whenever a <literal>TemplateException</literal> occurs, this
+          method will be called. The exception to handle is in the
+          <literal>te</literal> argument, the runtime environment of the
+          template processing is in the <literal>env</literal> argument, and
+          the handler can print to the output using the <literal>out</literal>
+          argument. If this method throws exception (usually it re-throws
+          <literal>te</literal>), then the template processing will be
+          aborted, and
+          <literal>Template.process(<replaceable>...</replaceable>)</literal>
+          will throw the same exception. If
+          <literal>handleTemplateException</literal> doesn't throw exception,
+          then template processing continues as if nothing had happen, but the
+          statement that caused the exception will be skipped (see more
+          later). Of course, the handler can still print an error indicator to
+          the output.</para>
+
+          <para>Let's see how FreeMarker skips statements when the error
+          handler doesn't throw exception, through examples. Assume we are
+          using this template exception handler:</para>
+
+          <programlisting role="unspecified">class MyTemplateExceptionHandler implements TemplateExceptionHandler {
+    public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
+            throws TemplateException {
+        try {
+            out.write("[ERROR: " + te.getMessage() + "]");
+        } catch (IOException e) {
+            throw new TemplateException("Failed to print error message. Cause: " + e, env);
+        }
+    }
+}
+
+<replaceable>...</replaceable>
+
+cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());</programlisting>
+
+          <para>If an error occurs in an interpolation which is not inside an
+          FTL tag (that is, not enclosed into
+          <literal>&lt;#<replaceable>...</replaceable>&gt;</literal> or
+          <literal>&lt;@<replaceable>...</replaceable>&gt;</literal>), then
+          the whole interpolation will be skipped. So this template (assuming
+          that <literal>badVar</literal> is missing from the
+          data-model):</para>
+
+          <programlisting role="template">a${badVar}b</programlisting>
+
+          <para>will print this if we use the
+          <literal>MyTemplateExceptionHandler</literal>:</para>
+
+          <programlisting role="output">a[ERROR: Expression badVar is undefined on line 1, column 4 in test.ftl.]b</programlisting>
+
+          <para>This template will print the same (except that the column
+          number will differ...):</para>
+
+          <programlisting role="template">a${"moo" + badVar}b</programlisting>
+
+          <para>because the whole interpolation is skipped if any error occurs
+          inside it.</para>
+
+          <para>If an error occurs when evaluating the value of a parameter
+          for a directive call, or if there are other problems with the
+          parameter list, or if an error occurs when evaluating
+          <literal><replaceable>exp</replaceable></literal> in
+          <literal>&lt;@<replaceable>exp</replaceable>
+          <replaceable>...</replaceable>&gt;</literal>, or if the value of
+          <literal><replaceable>exp</replaceable></literal> is not an
+          user-defined directive, then the whole directive call is skipped.
+          For example this:</para>
+
+          <programlisting role="template">a&lt;#if badVar&gt;Foo&lt;/#if&gt;b</programlisting>
+
+          <para>will print this:</para>
+
+          <programlisting role="output">a[ERROR: Expression badVar is undefined on line 1, column 7 in test.ftlh.]b</programlisting>
+
+          <para>Note that the error occurred in the <literal>if</literal>
+          start-tag (<literal>&lt;#if badVar&gt;</literal>), but the whole
+          directive call was skipped. Logically, the nested content
+          (<literal>Foo</literal>) was skipped with this, since the nested
+          content is handled (printed) by the enclosing directive
+          (<literal>if</literal>).</para>
+
+          <para>The output will be the same with this (except that the column
+          number will differ...):</para>
+
+          <programlisting role="template">a&lt;#if "foo${badVar}" == "foobar"&gt;Foo&lt;/#if&gt;b</programlisting>
+
+          <para>because whole directive calling will be skipped if any error
+          occurs during the parameter evaluation.</para>
+
+          <para>The directive call will not be skipped if the error occurs
+          after the execution of the directive was already started. That is,
+          if an error occurs in the nested content:</para>
+
+          <programlisting role="template">a
+&lt;#if true&gt;
+  Foo
+  ${badVar}
+  Bar
+&lt;/#if&gt;
+c</programlisting>
+
+          <para>or in the macro definition body:</para>
+
+          <programlisting role="template">a
+&lt;@test /&gt;
+b
+&lt;#macro test&gt;
+  Foo
+  ${badVar}
+  Bar
+&lt;/#macro&gt;</programlisting>
+
+          <para>the output will be something like:</para>
+
+          <programlisting role="output">a
+  Foo
+  [ERROR: Expression badVar is undefined on line 4, column 5 in test.ftlh.]
+  Bar
+c</programlisting>
+        </section>
+
+        <section>
+          <title>TemplateException logging</title>
+
+          <para>By default FreeMarker <link
+          linkend="pgui_misc_logging">logs</link> all
+          <literal>TemplateException</literal>-s under the
+          <literal>freemarker.runtime</literal> log category, even when it
+          will throw it at you from its public API. As logging has become
+          common practice in Java applications, this usually leads to double
+          logging of exceptions now, so it's recommended to disable this
+          legacy behavior by
+          <literal>cfg.setLogTemplateExceptions(false)</literal> (or
+          <literal>log_template_exceptions=false</literal>) where you
+          configure FreeMarker.</para>
+        </section>
+
+        <section>
+          <title>Explicit error handling in templates</title>
+
+          <para>Although it has nothing to do with the FreeMarker
+          configuration (the topic of this chapter), for the sake of
+          completeness it's mentioned here that you can handle errors directly
+          inside the templates as well:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Handling missing/null variables: <xref
+              linkend="dgui_template_exp_missing"/></para>
+            </listitem>
+
+            <listitem>
+              <para>Substituting failing but expendable page sections: <xref
+              linkend="ref_directive_attempt"/></para>
+            </listitem>
+          </itemizedlist>
+        </section>
+      </section>
+
+      <section xml:id="pgui_config_templateconfigurations">
+        <title>Template configurations</title>
+
+        <para><quote>Template configurations</quote> refers to the
+        <literal>template_configurations</literal> setting of
+        <literal>Configuration</literal>
+        (<literal>Configuration.setTemplateConfigurations(<replaceable>...</replaceable>)</literal>).
+        This setting lets you override individual settings coming from the
+        common <literal>Configuration</literal> object, depending on the name
+        (path) of the template.</para>
+
+        <para>It's important to understand, however, that this setting only
+        has effect if you get templates with
+        <literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>,
+        not when you create templates directly with the
+        <literal>Template</literal> constructors. In that case it's up to you
+        to invoke this mechanism (see <literal>TemplateCache</literal> source
+        code as an example).</para>
+
+        <para>You will use these kind of objects to declare your template
+        configuration rules:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><literal>TemplateConfiguration</literal>-s: These store the
+            actual setting assignments that you want to apply. For example,
+            this <literal>TemplateConfiguration</literal> will set the
+            encoding and the output format of the matched template (and leave
+            all other settings of it alone):</para>
+
+            <programlisting role="unspecified">TemplateConfiguration tcUTF8XML = new TemplateConfiguration();
+tc.setEncoding("utf-8");
+tc.setOutputFormat(XMLOutputFormat.INSTANCE);</programlisting>
+          </listitem>
+
+          <listitem>
+            <para><literal>TemplateSourceMatcher</literal> (abstract)
+            subclasses: These define a rule that matches templates based on
+            their source name (their source path; as in
+            <literal>Template.getSourceName()</literal>), and possibly on
+            other <literal>TemplateLoader</literal>-dependent properties. For
+            example, <literal>new FileExtensionMatcher("xml")</literal>
+            matches templates that has <literal>xml</literal> file extension.
+            See all the subclasses in the Java API documentation.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>TemplateConfigurationFactory</literal>-es: This is
+            what connects <literal>TemplateConfiguration</literal>-s and
+            <literal>TemplateSourceMatcher</literal>-s together. This is the
+            Java type of the <literal>template_configurations</literal>
+            setting. See the examples below for more.</para>
+          </listitem>
+        </itemizedlist>
+
+        <simplesect>
+          <title>Example 1</title>
+
+          <para>This setup combines our earlier two example objects with a
+          <literal>ConditionalTemplateConfigurationFactory</literal>, causing
+          all templates with <literal>xml</literal> extension to get UTF-8
+          encoding and XML output format:</para>
+
+          <programlisting role="unspecified">cfg.setTemplateConfigurations(
+        new ConditionalTemplateConfigurationFactory(
+                new FileExtensionMatcher("xml"),
+                tcUTF8XML));</programlisting>
+
+          <para>The same configuring is also doable if you don't have access
+          to the configuring Java code, but only to a Java
+          <literal>*.properties</literal> file, or other kind of string-string
+          key value pairs (the <literal>\</literal>-s are prescribed by the
+          Java Properties file format for multi-line values, so omit them
+          elsewhere):</para>
+
+          <programlisting role="unspecified">templateConfigurations = \
+    ConditionalTemplateConfigurationFactory( \
+        FileExtensionMatcher("xml"), \
+        TemplateConfiguration( \
+            encoding = "utf-8", \
+            outputFormat = XMLOutputFormat() \
+        ) \
+    )</programlisting>
+        </simplesect>
+
+        <simplesect>
+          <title>Example 2</title>
+
+          <para>Let's say you only need to handle templates in the
+          <literal>mail</literal> directory specially, other templates can use
+          the setting coming from the shared <literal>Configuration</literal>
+          singleton. The names of templates there must contain
+          <literal>".subject."</literal> or <literal>".body."</literal>.
+          Subject templates must get <literal>plainText</literal> output
+          format, while body templates must get <literal>HTML</literal> output
+          format. So we have to make a choice here, and that's when you need a
+          <literal>FirstMatchTemplateConfigurationFactory</literal>.</para>
+
+          <para>Assuming <literal>cfg</literal> stores the shared
+          <literal>Configuration</literal> singleton, you set this up like
+          this:</para>
+
+          <programlisting role="unspecified">TemplateConfiguration tcSubject = new TemplateConfiguration();
+tcSubject.setOutputFormat(PlainTextOutputFormat.INSTANCE);
+        
+TemplateConfiguration tcBody = new TemplateConfiguration();
+tcBody.setOutputFormat(HTMLOutputFormat.INSTANCE);
+
+cfg.setTemplateConfigurations(
+        new ConditionalTemplateConfigurationFactory(
+                new PathGlobMatcher("mail/**"),
+                new FirstMatchTemplateConfigurationFactory(
+                        new ConditionalTemplateConfigurationFactory(
+                                new FileNameGlobMatcher("*.subject.*"),
+                                tcSubject),
+                        new ConditionalTemplateConfigurationFactory(
+                                new FileNameGlobMatcher("*.body.*"),
+                                tcBody)
+                        )
+                        .noMatchErrorDetails(
+                                "Mail template names must contain \".subject.\" or \".body.\"!")
+                ));</programlisting>
+
+          <para>The equivalent configuration using a Java
+          <literal>*.properties</literal> file or other kind of string-string
+          key value pairs (the <literal>\</literal>-s are prescribed by the
+          Java Properties file format only, so omit them elsewhere):</para>
+
+          <programlisting role="unspecified">templateConfigurations = \
+    ConditionalTemplateConfigurationFactory( \
+        PathGlobMatcher("mail/**"), \
+        FirstMatchTemplateConfigurationFactory( \
+            ConditionalTemplateConfigurationFactory( \
+                FileNameGlobMatcher("*.subject.*"), \
+                TemplateConfiguration(outputFormat = PlainTextOutputFormat()) \
+            ), \
+            ConditionalTemplateConfigurationFactory( \
+                FileNameGlobMatcher("*.body.*"), \
+                TemplateConfiguration(outputFormat = HTMLOutputFormat()) \
+            ), \
+            noMatchErrorDetails = 'Mail template names must contain ".subject." or ".body."!' \
+        ) \
+    )</programlisting>
+        </simplesect>
+
+        <simplesect>
+          <title>Example 3</title>
+
+          <para>Let's say you want the following deviations from the shared
+          <literal>Configuration</literal> settings in your
+          application:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>All templates whose name contains
+              <literal>".stats."</literal> should use ISO date/time format and
+              UTC time zone</para>
+            </listitem>
+
+            <listitem>
+              <para>All templates inside the <literal>mail</literal> directory
+              should use UTF-8 encoding</para>
+            </listitem>
+
+            <listitem>
+              <para>Templates with <literal>xml</literal> file extension
+              should use XML <literal>output_format</literal>, templates with
+              <literal>html</literal> or <literal>htm</literal> extension
+              should use HTML output format. For other templates, the shared
+              <literal>Configuration</literal> can dictate the
+              <literal>output_format</literal>.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Here we have 3 independent concerns, and possibly multiple (or
+          none) of those apply to a template; that's when you need a
+          <literal>MergingTemplateConfigurationFactory</literal>. In file
+          extension related rule above you have mutually exclusive choices, so
+          you need a
+          <literal>FirstMatchTemplateConfigurationFactory</literal>, but this
+          time no choice is also allowed. Here's the source code, assuming
+          <literal>cfg</literal> stores the shared
+          <literal>Configuration</literal> instance:</para>
+
+          <programlisting role="unspecified">TemplateConfiguration tcStats = new TemplateConfiguration();
+tcStats.setDateTimeFormat("iso");
+tcStats.setDateFormat("iso");
+tcStats.setTimeFormat("iso");
+tcStats.setTimeZone(DateUtil.UTC);
+
+TemplateConfiguration tcMail = new TemplateConfiguration();
+tcMail.setEncoding("utf-8");
+
+TemplateConfiguration tcHTML = new TemplateConfiguration();
+tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
+
+TemplateConfiguration tcXML = new TemplateConfiguration();
+tcXML.setOutputFormat(XMLOutputFormat.INSTANCE);
+
+cfg.setTemplateConfigurations(
+        new MergingTemplateConfigurationFactory(
+                new ConditionalTemplateConfigurationFactory(
+                        new FileNameGlobMatcher("*.stats.*"),
+                        tcStats),
+                new ConditionalTemplateConfigurationFactory(
+                        new PathGlobMatcher("mail/**"),
+                        tcMail),
+                new FirstMatchTemplateConfigurationFactory(
+                        new ConditionalTemplateConfigurationFactory(
+                                new FileExtensionMatcher("xml"),
+                                tcXML),
+                        new ConditionalTemplateConfigurationFactory(
+                                new OrMatcher(
+                                        new FileExtensionMatcher("html"),
+                                        new FileExtensionMatcher("htm")),
+                                tcHTML)
+                ).allowNoMatch(true)
+        )
+);</programlisting>
+
+          <para>The equivalent configuration using a Java
+          <literal>*.properties</literal> file or other kind of string-string
+          key value pairs (the <literal>\</literal>-s are prescribed by the
+          Java Properties file format only):</para>
+
+          <programlisting role="unspecified">templateConfigurations = \
+    MergingTemplateConfigurationFactory( \
+        ConditionalTemplateConfigurationFactory( \
+            FileNameGlobMatcher("*.stats.*"), \
+            TemplateConfiguration( \
+                dateTimeFormat = "iso", \
+                dateFormat = "iso", \
+                timeFormat = "iso", \
+                timeZone = TimeZone("UTC") \
+            ) \
+        ), \
+        ConditionalTemplateConfigurationFactory( \
+            PathGlobMatcher("mail/**"), \
+            TemplateConfiguration(encoding = "utf-8") \
+        ), \
+        FirstMatchTemplateConfigurationFactory( \
+            ConditionalTemplateConfigurationFactory( \
+                FileExtensionMatcher("xml"), \
+                TemplateConfiguration(outputFormat = XMLOutputFormat()) \
+            ), \
+            ConditionalTemplateConfigurationFactory( \
+                OrMatcher( \
+                    FileExtensionMatcher("html"), \
+                    FileExtensionMatcher("htm") \
+                ), \
+                TemplateConfiguration(outputFormat = HTMLOutputFormat()) \
+            ), \
+            allowNoMatch = true \
+        ) \
+    )</programlisting>
+        </simplesect>
+      </section>
+
+      <section xml:id="pgui_config_outputformatsautoesc">
+        <title>Associating output formats with templates</title>
+
+        <indexterm>
+          <primary>auto-escaping</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>output format</primary>
+        </indexterm>
+
+        <para>The output format associated to a template decides if and what
+        kind of auto-escaping is used in that template (unless the template
+        <link linkend="dgui_misc_autoescaping_overrideoformat">overrides that
+        with directives</link>). By default, templates have
+        <quote>undefined</quote> output format associated, which does no
+        escaping, and in general gives the behavior that you would expect from
+        a template engine that doesn't care about output formats and escaping.
+        However, if the <literal>recognize_standard_file_extensions</literal>
+        <link linkend="pgui_config_settings">setting</link> is
+        <literal>true</literal> (which is the default with <link
+        linkend="pgui_config_incompatible_improvements">the
+        <literal>incompatible_improvements</literal> setting</link> set to
+        2.3.24 or higher), templates whose source name ends with
+        <literal>".ftlh"</literal> gets <quote>HTML</quote> output format, and
+        those with <literal>".ftlx"</literal> get <quote>XML</quote> output
+        format. Using the <literal>ftlh</literal> and <literal>ftlx</literal>
+        file extensions is the recommended way of activating HTML and XML
+        auto-escaping. You can also associate output formats to templates
+        based on arbitrary name patterns with the <link
+        linkend="pgui_config_templateconfigurations"><literal>template_configurations</literal>
+        setting</link>; see some examples of that below.</para>
+
+        <para>There's another a related setting, called
+        <literal>auto_escaping_policy</literal>, which can be used to disable
+        auto-escaping even if the current output format supports it, or enable
+        auto-escaping even if the format by default doesn't escape (but it
+        supports it). Using this setting rarely advisable, as it's potentially
+        confusing for the template authors. (Instead, escaping can be turned
+        on/off explicitly inside the templates with the
+        <literal>auto_esc</literal> parameter of the <link
+        linkend="ref_directive_ftl"><literal>ftl</literal> directive</link>,
+        or with the <link
+        linkend="ref_directive_autoesc"><literal>noautoesc</literal></link>
+        and <link linkend="ref_directive_autoesc"><literal>autoesc</literal>
+        directive</link>s.)</para>
+
+        <para>To check if you have configured FreeMarker properly, you can use
+        this template:</para>
+
+        <programlisting role="template">&lt;p&gt;Output format: ${.output_format}
+&lt;p&gt;Auto-escaping: ${.auto_esc?c}</programlisting>
+
+        <para>See the <link linkend="topic.predefinedOutputFormats">table of
+        predefined output formats here...</link></para>
+
+        <para>Configuration examples:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>To enable automatic output format associations to
+            <literal>*.ftlh</literal> and <literal>*.ftlx</literal>,
+            either:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>Use <literal>incompatible_improvements</literal> 2.3.24
+                or higher; see <link
+                linkend="pgui_config_incompatible_improvements_how_to_set">how
+                to set
+                <literal>incompatible_improvements</literal></link></para>
+              </listitem>
+
+              <listitem>
+                <para>Or, enable standard file extension recognizing
+                explicitly:</para>
+
+                <programlisting role="unspecified">// Where you initalize the Configuration singletion, add:
+cfg.setRecognizeStandardFileExtensions(true);</programlisting>
+
+                <para>or if you configure FreeMarker with Java
+                <literal>*.properties</literal> file:</para>
+
+                <programlisting role="unspecified">recognizeStandardFileExtensions = true</programlisting>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Let's say that you want to associate all templates in the
+            <literal>mail</literal> directory to the HTML output format. You
+            could achieve that like this (assuming that you are getting the
+            templates with
+            <literal>cfg.getTemplate(<replaceable>...</replaceable>)</literal>,
+            and not instantiating them yourself):</para>
+
+            <programlisting role="unspecified">// Where you initalize the Configuration singletion, add:
+
+TemplateConfiguration tcHTML = new TemplateConfiguration();
+tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
+
+cfg.setTemplateConfigurations(
+        new ConditionalTemplateConfigurationFactory(
+                new PathGlobMatcher("mail/**"),
+                tcHTML));</programlisting>
+
+            <para>or if you are configuring FreeMarker from Java
+            <literal>*.properties</literal> file (the <literal>\</literal>-s
+            are required for the Java Properties file format only):</para>
+
+            <programlisting role="unspecified">templateConfigurations = \
+    ConditionalTemplateConfigurationFactory( \
+        PathGlobMatcher("mail/**"), \
+        TemplateConfiguration(outputFormat = HTMLOutputFormat()))</programlisting>
+          </listitem>
+
+          <listitem>
+            <para>Let's say you want to associate templates with
+            <literal>xml</literal> file extension to the XML output format,
+            templates with <literal>html</literal> and <literal>htm</literal>
+            extension to the HTML output format, and templates with
+            <literal>rtf</literal> extension to the <literal>RTF</literal>
+            output format. You could achieve that like this (assuming that you
+            are getting the templates with
+            <literal>cfg.getTemplate(<replaceable>...</replaceable>)</literal>,
+            and not instantiating them yourself):</para>
+
+            <programlisting role="unspecified">TemplateConfiguration tcHTML = new TemplateConfiguration();
+tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
+
+TemplateConfiguration tcXML = new TemplateConfiguration();
+tcXML.setOutputFormat(XMLOutputFormat.INSTANCE);
+
+TemplateConfiguration tcRTF = new TemplateConfiguration();
+tcRTF.setOutputFormat(RTFOutputFormat.INSTANCE);
+
+cfg.setTemplateConfigurations(
+        new FirstMatchTemplateConfigurationFactory(
+                new ConditionalTemplateConfigurationFactory(
+                        new FileExtensionMatcher("xml"),
+                        tcXML),
+                new ConditionalTemplateConfigurationFactory(
+                        new OrMatcher(
+                                new FileExtensionMatcher("html"),
+                                new FileExtensionMatcher("htm")),
+                        tcHTML),
+                new ConditionalTemplateConfigurationFactory(
+                        new FileExtensionMatcher("rtf"),
+                        tcRTF)
+        ).allowNoMatch(true)
+);</programlisting>
+
+            <para>or if you are configuring FreeMarker from Java
+            <literal>*.properties</literal> file (the <literal>\</literal>-s
+            are required for the Java Properties file format only):</para>
+
+            <programlisting role="unspecified">templateConfigurations = \
+    FirstMatchTemplateConfigurationFactory( \
+        ConditionalTemplateConfigurationFactory( \
+            FileExtensionMatcher("xml"), \
+            TemplateConfiguration(outputFormat = XMLOutputFormat())), \
+        ConditionalTemplateConfigurationFactory( \
+            OrMatcher( \
+                FileExtensionMatcher("html"), \
+                FileExtensionMatcher("htm")), \
+            TemplateConfiguration(outputFormat = HTMLOutputFormat())), \
+        ConditionalTemplateConfigurationFactory( \
+            FileExtensionMatcher("rtf"), \
+            TemplateConfiguration(outputFormat = RTFOutputFormat())), \
+        allowNoMatch = true)</programlisting>
+          </listitem>
+        </itemizedlist>
+
+        <para>(You can find some more complex
+        <literal>template_configurations</literal> setups <link
+        linkend="pgui_config_templateconfigurations">here...</link>)</para>
+      </section>
+
+      <section xml:id="pgui_config_custom_formats">
+        <title>Custom number and date/time formats</title>
+
+        <section>
+          <title>Overview</title>
+
+          <note>
+            <para>Custom formats (of the kind described here) exists since
+            FreeMarker 2.3.24.</para>
+          </note>
+
+          <para>FreeMarker allows you to define your own number and
+          date/time/datetime formats, and associate a name to them. This
+          mechanism has several applications:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Custom formatter algorithms: You can use your own
+              formatter algorithm instead of relying on those provided by
+              FreeMarker. For this, implement
+              <literal>freemarker.core.TemplateNumberFormatFactory</literal>
+              or <literal>freemarker.core.TemplateDateFormatFactory</literal>.
+              You will find a few examples of this <link
+              linkend="pgui_config_custom_formats_ex_cust_alg_simple">below</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Aliasing: You can give application-specific names (like
+              <quote>price</quote>, <quote>weight</quote>,
+              <quote>fileDate</quote>, <quote>logEventTime</quote>, etc.) to
+              other formats by using
+              <literal>AliasTemplateNumberFormatFactory</literal> and
+              <literal>AliasTemplateDateFormatFactory</literal>. Thus
+              templates can just refer to that name, like in
+              <literal>${lastModified?string.@fileDate}</literal>, instead of
+              specifying the format directly. Thus the formats can be
+              specified on a single central place (where you configure
+              FreeMarker), instead of being specified repeatedly in templates.
+              Also thus template authors don't have to enter complex and hard
+              to remember formatting patterns. <link
+              linkend="pgui_config_custom_formats_ex_alias">See example
+              below</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Model-sensitive formatting: Applications can put custom
+              <literal>freemarker.TemplateModel</literal>-s into the
+              data-model instead of dropping plain values (like
+              <literal>int</literal>-s, <literal>double</literal>-s, etc.)
+              into it, to attach rendering-related information to the value.
+              Custom formatters can utilize this information (for example, to
+              show the unit after numbers), as they receive the
+              <literal>TemplateModel</literal> itself, not the wrapped raw
+              value. <link
+              linkend="pgui_config_custom_formats_ex_model_aware">See example
+              below</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Format that prints markup instead of plain text: You might
+              want to use HTML tags (or other markup) in the formatted values,
+              such as coloring negative numbers to red or using HTML
+              <literal>sup</literal> element for exponents. This is possible
+              if you write a custom format as shown in previous cases, but
+              override the <literal>format</literal> method in the formatter
+              class so that it returns a
+              <literal>TemplateMarkupOutputModel</literal> instead of a
+              <literal>String</literal>. (You shouldn't just return the markup
+              as <literal>String</literal>, as then it might will be escaped;
+              see <link
+              linkend="dgui_misc_autoescaping">auto-escaping</link>.)</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Custom formats can be registered with the
+          <literal>custom_number_formats</literal> and
+          <literal>custom_date_formats</literal> configuration settings. After
+          that, anywhere where you can specify formats with a
+          <literal>String</literal>, now you can refer to your custom format
+          as <literal>"@<replaceable>name</replaceable>"</literal>. So for
+          example, if you have registered your number format implementation
+          with name <literal>"smart"</literal>, then you could set the
+          <literal>number_format</literal> setting
+          (<literal>Configurable.setNumberFormat(String)</literal>) to
+          <literal>"@smart"</literal>, or issue
+          <literal>${n?string.@smart}</literal> or <literal>&lt;#setting
+          number_format="@smart"&gt;</literal> in a template. Furthermore, you
+          can define parameters for your custom format, like <literal>"@smart
+          2"</literal>, and the interpretation of the parameters is up to your
+          formatter implementation.</para>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_cust_alg_simple">
+          <title>Simple custom number format example</title>
+
+          <para>This custom number format shows numbers in hexadecimal
+          form:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import java.util.Locale;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+import freemarker.template.utility.NumberUtil;
+
+public class HexTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    public static final HexTemplateNumberFormatFactory INSTANCE
+            = new HexTemplateNumberFormatFactory();
+
+    private HexTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws InvalidFormatParametersException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return HexTemplateNumberFormat.INSTANCE;
+    }
+
+    private static class HexTemplateNumberFormat extends TemplateNumberFormat {
+
+        private static final HexTemplateNumberFormat INSTANCE = new HexTemplateNumberFormat();
+
+        private HexTemplateNumberFormat() { }
+
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws UnformattableValueException, TemplateModelException {
+            Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
+            try {
+                return Integer.toHexString(NumberUtil.toIntExact(n));
+            } catch (ArithmeticException e) {
+                throw new UnformattableValueException(n + " doesn't fit into an int");
+            }
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        public String getDescription() {
+            return "hexadecimal int";
+        }
+
+    }
+
+}</programlisting>
+
+          <para>We register the above format with name
+          <quote>hex</quote>:</para>
+
+          <programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
+Configuration cfg = ...;
+...
+Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats = ...;
+...
+customNumberFormats.put("hex", HexTemplateNumberFormatFactory.INSTANCE);
+...
+cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
+
+          <para>Now we can use this format in templates:</para>
+
+          <programlisting role="template">${x?string.@hex}</programlisting>
+
+          <para>or even set it as the default number format:</para>
+
+          <programlisting role="unspecified">cfg.setNumberFormat("@hex");</programlisting>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_cust_algo_advanced">
+          <title>Advanced custom number format example</title>
+
+          <para>This is a more complex custom number format that shows how to
+          deal with parameters in the format string, also how to delegate to
+          another format:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import java.util.Locale;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+import freemarker.template.utility.NumberUtil;
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Shows a number in base N number system. Can only format numbers that fit into an {@code int},
+ * however, optionally you can specify a fallback format. This format has one required parameter,
+ * the numerical system base. That can be optionally followed by "|" and a fallback format.
+ */
+public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    public static final BaseNTemplateNumberFormatFactory INSTANCE
+            = new BaseNTemplateNumberFormatFactory();
+
+    private BaseNTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws InvalidFormatParametersException {
+        TemplateNumberFormat fallbackFormat;
+        {
+            int barIdx = params.indexOf('|');
+            if (barIdx != -1) {
+                String fallbackFormatStr = params.substring(barIdx + 1);
+                params = params.substring(0, barIdx);
+                try {
+                    fallbackFormat = env.getTemplateNumberFormat(fallbackFormatStr, locale);
+                } catch (TemplateValueFormatException e) {
+                    throw new InvalidFormatParametersException(
+                            "Couldn't get the fallback number format (specified after the \"|\"), "
+                            + StringUtil.jQuote(fallbackFormatStr) + ". Reason: " + e.getMessage(),
+                            e);
+                }
+            } else {
+                fallbackFormat = null;
+            }
+        }
+
+        int base;
+        try {
+            base = Integer.parseInt(params);
+        } catch (NumberFormatException e) {
+            if (params.length() == 0) {
+                throw new InvalidFormatParametersException(
... 33954 lines suppressed ...


[freemarker] 09/09: Forward ported from 2.3-gae: Fix HTLM typos (PR #73)

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit cfb0651b2cf80a2d1572c9a12a9331ac0ca6cf91
Author: ddekany <dd...@apache.org>
AuthorDate: Sun Jan 1 00:13:12 2023 +0100

    Forward ported from 2.3-gae: Fix HTLM typos (PR #73)
---
 FM3-CHANGE-LOG.txt                                                      | 2 +-
 .../apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah  | 2 +-
 .../freemarker/manual/examples/AutoEscapingExample-convert.f3ah.out     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt
index 8db37885..3b655a96 100644
--- a/FM3-CHANGE-LOG.txt
+++ b/FM3-CHANGE-LOG.txt
@@ -317,7 +317,7 @@ Core / Configuration
   to UNRESTRICTED and ALLOW_NOTHING. Also the String setting name "allows_nothing" and
   "allowsNothing" were renamed to "allowNothing".
 - TemplateExceptionHandler.IGNORE_HANDLER, RETHROW_HANDLER, DEBUG_HANDLER and
-  HTLM_DEBUG_HANDLER was renamed to IGNORE, RETHROW, DEBUG and HTML_DEBUG
+  HTML_DEBUG_HANDLER was renamed to IGNORE, RETHROW, DEBUG and HTML_DEBUG
 - AttemptExceptionReporter.LOG_ERROR_REPORTER and LOG_WARN_REPORTER was renamed to
   LOG_ERROR and LOG_WARN (to be consistent with the new TemplateExceptionHandler names)
 - Removed TemplateClassResolver.SAFER_RESOLVER, because the classes it has blocked were removed from FreeMarker, so it's
diff --git a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah
index 5d608794..b23e56f5 100644
--- a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah
+++ b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah
@@ -17,7 +17,7 @@
   under the License.
 -->
 <#assign mo1 = "Foo's bar {}"?esc>
-HTLM: ${mo1}
+HTML: ${mo1}
 XML:  <#outputFormat 'XML'>${mo1}</#outputFormat>
 RTF:  <#outputFormat 'RTF'>${mo1}</#outputFormat>
 
diff --git a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah.out b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah.out
index 65be2a00..1edf4033 100644
--- a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah.out
+++ b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AutoEscapingExample-convert.f3ah.out
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-HTLM: Foo&#39;s bar {}
+HTML: Foo&#39;s bar {}
 XML:  Foo&apos;s bar {}
 RTF:  Foo's bar \{\}
 


[freemarker] 08/09: Forward ported from 2.3-gae: Fix: Typos "clalc." in TemplateException (PR #76)

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit d2773c44ac7ec2806d5cda89e92cc32f2b811d8a
Author: ddekany <dd...@apache.org>
AuthorDate: Sun Jan 1 00:10:47 2023 +0100

    Forward ported from 2.3-gae: Fix: Typos "clalc." in TemplateException (PR #76)
---
 .../org/apache/freemarker/core/TemplateException.java     | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateException.java b/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateException.java
index 56b87948..eee4506e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateException.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateException.java
@@ -19,16 +19,11 @@
 
 package org.apache.freemarker.core;
 
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.Method;
-
 import org.apache.freemarker.core.util._CollectionUtils;
 
+import java.io.*;
+import java.lang.reflect.Method;
+
 /**
  * Runtime exception in a template (as opposed to a parsing-time exception: {@link ParseException}).
  * It prints a special stack trace that contains the template-language stack trace along the usual Java stack trace.
@@ -46,8 +41,8 @@ public class TemplateException extends Exception {
     private transient ASTElement[] ftlInstructionStackSnapshot;
     
     // Calculated on demand:
-    private String renderedFtlInstructionStackSnapshot;  // clalc. from ftlInstructionStackSnapshot 
-    private String renderedFtlInstructionStackSnapshotTop; // clalc. from ftlInstructionStackSnapshot
+    private String renderedFtlInstructionStackSnapshot;  // calc. from ftlInstructionStackSnapshot 
+    private String renderedFtlInstructionStackSnapshotTop; // calc. from ftlInstructionStackSnapshot
     private String description;  // calc. from descriptionBuilder, or set by the construcor
     private transient String messageWithoutStackTop;
     private transient String message;


[freemarker] 05/09: Forward ported from 2.3-gae: PR #77

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 6c535b8f30e008e8de9eb60f53fcf600a15adc11
Author: ddekany <dd...@apache.org>
AuthorDate: Sun Jan 1 00:02:09 2023 +0100

    Forward ported from 2.3-gae: PR #77
---
 .../src/test/resources/META-INF/malformed.tld      | 31 ----------------------
 1 file changed, 31 deletions(-)

diff --git a/freemarker-servlet/src/test/resources/META-INF/malformed.tld b/freemarker-servlet/src/test/resources/META-INF/malformed.tld
deleted file mode 100644
index be3b092a..00000000
--- a/freemarker-servlet/src/test/resources/META-INF/malformed.tld
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
-  version="2.1">
-  <tlib-version>2.0</tlib-version>
-  <short-name>For ClassPathTlds testing - 3</short-name>
-  <uri>http://freemarker.org/taglibs/test/MetaInfTldSources-1xx</uri>
-  <ta>
-    <name>simpletag</name>
-    <tag-class>org.apache.freemarker.servlet.jsp.taglibmembers.TestSimpleTag3</tag-class>
-    <body-content>empty</body-content>
-  </tag>
-</taglib>
\ No newline at end of file


[freemarker] 03/09: Forward ported from 2.3-gae: Added ?cUpperCase, and ?cLowerCase

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 1c8ea677dd32c2f8f90aecdb181c653dbd4be2ee
Author: ddekany <dd...@apache.org>
AuthorDate: Sat Dec 31 22:55:04 2022 +0100

    Forward ported from 2.3-gae: Added ?cUpperCase, and ?cLowerCase
---
 .../templatesuite/expected/string-builtins1.txt    |  1 +
 .../templatesuite/templates/string-builtins1.f3ac  |  7 ++++
 .../org/apache/freemarker/core/ASTExpBuiltIn.java  | 49 ++++++----------------
 3 files changed, 20 insertions(+), 37 deletions(-)

diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/string-builtins1.txt b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/string-builtins1.txt
index d79e7dc0..a43e56c7 100644
--- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/string-builtins1.txt
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/string-builtins1.txt
@@ -110,3 +110,4 @@ FOOBAR
 [<\/script>] = [<\/script>]
 [\u003C![CDATA[] = [\u003C![CDATA[]
 []]\u003E] = []]\u003E]
+
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/string-builtins1.f3ac b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/string-builtins1.f3ac
index be1b19e3..ab6187c7 100644
--- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/string-builtins1.f3ac
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/string-builtins1.f3ac
@@ -127,3 +127,10 @@ ${c?eval}
 [${"</script>"?jsonString}] = [<\/script>]
 [${"<![CDATA["?jsonString}] = [\u003C![CDATA[]
 [${"]]>"?jsonString}] = []]\u003E]
+
+<#-- ?c_...: -->
+<#setting locale="tr_TR">
+<@assertEquals actual="i"?upperCase expected="\x0130" />
+<@assertEquals actual="i"?cUpperCase expected="I" />
+<@assertEquals actual="I"?lowerCase expected="\x0131" />
+<@assertEquals actual="I"?cLowerCase expected="i" />
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
index 8500d6d9..e9d43731 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
@@ -19,47 +19,15 @@
 
 package org.apache.freemarker.core;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
 import org.apache.freemarker.core.BuiltInsForDates.iso_BI;
 import org.apache.freemarker.core.BuiltInsForDates.iso_utc_or_local_BI;
 import org.apache.freemarker.core.BuiltInsForMarkupOutputs.markup_stringBI;
 import org.apache.freemarker.core.BuiltInsForMultipleTypes.is_dateLikeBI;
-import org.apache.freemarker.core.BuiltInsForNodes.ancestorsBI;
-import org.apache.freemarker.core.BuiltInsForNodes.childrenBI;
-import org.apache.freemarker.core.BuiltInsForNodes.nextSiblingBI;
-import org.apache.freemarker.core.BuiltInsForNodes.node_nameBI;
-import org.apache.freemarker.core.BuiltInsForNodes.node_namespaceBI;
-import org.apache.freemarker.core.BuiltInsForNodes.node_typeBI;
-import org.apache.freemarker.core.BuiltInsForNodes.parentBI;
-import org.apache.freemarker.core.BuiltInsForNodes.previousSiblingBI;
-import org.apache.freemarker.core.BuiltInsForNodes.rootBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.absBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.byteBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.ceilingBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.doubleBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.floatBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.floorBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.intBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.is_infiniteBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.is_nanBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.longBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.number_to_dateBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.roundBI;
-import org.apache.freemarker.core.BuiltInsForNumbers.shortBI;
+import org.apache.freemarker.core.BuiltInsForNodes.*;
+import org.apache.freemarker.core.BuiltInsForNumbers.*;
 import org.apache.freemarker.core.BuiltInsForOutputFormatRelated.escBI;
 import org.apache.freemarker.core.BuiltInsForOutputFormatRelated.no_escBI;
-import org.apache.freemarker.core.BuiltInsForSequences.chunkBI;
-import org.apache.freemarker.core.BuiltInsForSequences.firstBI;
-import org.apache.freemarker.core.BuiltInsForSequences.lastBI;
-import org.apache.freemarker.core.BuiltInsForSequences.reverseBI;
-import org.apache.freemarker.core.BuiltInsForSequences.seq_containsBI;
-import org.apache.freemarker.core.BuiltInsForSequences.seq_index_ofBI;
-import org.apache.freemarker.core.BuiltInsForSequences.sortBI;
-import org.apache.freemarker.core.BuiltInsForSequences.sort_byBI;
+import org.apache.freemarker.core.BuiltInsForSequences.*;
 import org.apache.freemarker.core.BuiltInsForStringsMisc.evalBI;
 import org.apache.freemarker.core.BuiltInsForStringsMisc.evalJsonBI;
 import org.apache.freemarker.core.model.TemplateCallableModel;
@@ -68,6 +36,11 @@ import org.apache.freemarker.core.model.TemplateModelWithOriginName;
 import org.apache.freemarker.core.util._DateUtils;
 import org.apache.freemarker.core.util._StringUtils;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
 /**
  * AST expression node: {@code exp?name}
  */
@@ -76,8 +49,8 @@ abstract class ASTExpBuiltIn extends ASTExpression implements Cloneable {
     protected ASTExpression target;
     protected String key;
 
-    static final int NUMBER_OF_BIS = 272;
-    static final HashMap<String, ASTExpBuiltIn> BUILT_INS_BY_NAME = new HashMap(NUMBER_OF_BIS * 3 / 2 + 1, 1f);
+    static final int NUMBER_OF_BIS = 274;
+    static final HashMap<String, ASTExpBuiltIn> BUILT_INS_BY_NAME = new HashMap<>(NUMBER_OF_BIS * 3 / 2 + 1, 1f);
 
     static {
         // Note that you must update NUMBER_OF_BIS if you add new items here!
@@ -224,6 +197,7 @@ abstract class ASTExpBuiltIn extends ASTExpression implements Cloneable {
         putBI("long", new longBI());
         putBI("lowerAbc", new BuiltInsForNumbers.lower_abcBI());
         putBI("lowerCase", new BuiltInsForStringsBasic.lower_caseBI());
+        putBI("cLowerCase", new BuiltInsForStringsBasic.c_lower_caseBI());
         putBI("namespace", new BuiltInsForMultipleTypes.namespaceBI());
         putBI("new", new BuiltInsForStringsMisc.newBI());
         putBI("markupString", new markup_stringBI());
@@ -275,6 +249,7 @@ abstract class ASTExpBuiltIn extends ASTExpression implements Cloneable {
         putBI("uncapFirst", new BuiltInsForStringsBasic.uncap_firstBI());
         putBI("upperAbc", new BuiltInsForNumbers.upper_abcBI());
         putBI("upperCase", new BuiltInsForStringsBasic.upper_caseBI());
+        putBI("cUpperCase", new BuiltInsForStringsBasic.c_upper_caseBI());
         putBI("url", new BuiltInsForStringsEncoding.urlBI());
         putBI("urlPath", new BuiltInsForStringsEncoding.urlPathBI());
         putBI("values", new BuiltInsForHashes.valuesBI());


[freemarker] 02/09: Forward ported from 2.3-gae: Typo fixes, and some minor javadoc improvements

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 10e312945e931506a975b47f7b8cb984c1ea9a48
Author: ddekany <dd...@apache.org>
AuthorDate: Sat Dec 31 22:35:02 2022 +0100

    Forward ported from 2.3-gae: Typo fixes, and some minor javadoc improvements
---
 .../freemarker/converter/_ConverterUtils.java      |  2 +-
 .../freemarker/core/BuiltInsForStringsBasic.java   | 36 +++++++++------
 .../org/apache/freemarker/core/JSONParser.java     | 15 +------
 .../org/apache/freemarker/core/_DelayedAOrAn.java  |  2 +-
 .../core/_DelayedConversionToString.java           |  2 +-
 .../freemarker/core/_DelayedGetCanonicalForm.java  |  2 +-
 .../apache/freemarker/core/_DelayedGetMessage.java |  2 +-
 .../core/_DelayedGetMessageWithoutStackTop.java    |  2 +-
 .../org/apache/freemarker/core/_DelayedJQuote.java |  2 +-
 .../freemarker/core/_DelayedJQuotedListing.java    |  6 +--
 .../freemarker/core/_DelayedJoinWithComma.java     |  2 +-
 .../_DelayedTemplateLanguageTypeDescription.java   |  2 +-
 .../freemarker/core/_ErrorDescriptionBuilder.java  | 10 ++---
 .../java/org/apache/freemarker/core/_Java8.java    |  2 +-
 .../org/apache/freemarker/core/_Java8Impl.java     |  2 +-
 .../_ObjectBuilderSettingEvaluationException.java  |  2 +-
 .../core/_ObjectBuilderSettingEvaluator.java       | 52 ++++++----------------
 .../core/_SettingEvaluationEnvironment.java        |  6 +--
 ..._UnexpectedTypeErrorExplainerTemplateModel.java |  2 +-
 .../impl/BigDecimalArithmeticEngine.java           |  6 +--
 .../freemarker/core/debug/_DebuggerService.java    | 10 ++---
 .../core/model/TemplateMarkupOutputModel.java      |  4 +-
 .../outputformat/CommonMarkupOutputFormat.java     | 14 +++++-
 .../core/outputformat/MarkupOutputFormat.java      | 10 ++---
 .../templateresolver/TemplateLoadingSource.java    |  8 ++--
 .../freemarker/core/util/_ArrayAdapterList.java    |  2 +-
 .../freemarker/core/util/_ArrayIterator.java       |  2 +-
 .../apache/freemarker/core/util/_ClassUtils.java   |  8 ++--
 .../freemarker/core/util/_CollectionUtils.java     | 12 +----
 .../apache/freemarker/core/util/_DateUtils.java    |  8 +---
 .../apache/freemarker/core/util/_JavaVersions.java |  2 +-
 .../apache/freemarker/core/util/_NumberUtils.java  |  2 +-
 .../freemarker/core/util/_SortedArraySet.java      |  2 +-
 .../apache/freemarker/core/util/_StringUtils.java  | 10 ++---
 .../core/util/_UnmodifiableCompositeSet.java       |  2 +-
 .../freemarker/core/util/_UnmodifiableSet.java     |  2 +-
 .../core/valueformat/TemplateNumberFormat.java     |  6 +--
 freemarker-manual/src/main/docgen/en_US/book.xml   |  4 +-
 .../CopyrightCommentRemoverTemplateLoader.java     | 18 +++-----
 39 files changed, 124 insertions(+), 159 deletions(-)

diff --git a/freemarker-converter/src/main/java/org/apache/freemarker/converter/_ConverterUtils.java b/freemarker-converter/src/main/java/org/apache/freemarker/converter/_ConverterUtils.java
index 5b26b580..4c14be48 100644
--- a/freemarker-converter/src/main/java/org/apache/freemarker/converter/_ConverterUtils.java
+++ b/freemarker-converter/src/main/java/org/apache/freemarker/converter/_ConverterUtils.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.converter;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public final class _ConverterUtils {
 
     private _ConverterUtils() {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
index be2910d9..680cfe82 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
@@ -19,24 +19,20 @@
 
 package org.apache.freemarker.core;
 
-import static org.apache.freemarker.core.util.CallableUtils.*;
+import org.apache.freemarker.core.model.*;
+import org.apache.freemarker.core.model.impl.SimpleNumber;
+import org.apache.freemarker.core.model.impl.SimpleString;
+import org.apache.freemarker.core.pluggablebuiltin.TruncateBuiltinAlgorithm;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util._StringUtils;
 
 import java.util.ArrayList;
+import java.util.Locale;
 import java.util.StringTokenizer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.freemarker.core.model.ArgumentArrayLayout;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateFunctionModel;
-import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateStringModel;
-import org.apache.freemarker.core.model.impl.SimpleNumber;
-import org.apache.freemarker.core.model.impl.SimpleString;
-import org.apache.freemarker.core.pluggablebuiltin.TruncateBuiltinAlgorithm;
-import org.apache.freemarker.core.util.CallableUtils;
-import org.apache.freemarker.core.util._StringUtils;
+import static org.apache.freemarker.core.util.CallableUtils.*;
 
 class BuiltInsForStringsBasic {
 
@@ -488,7 +484,14 @@ class BuiltInsForStringsBasic {
         TemplateModel calculateResult(String s, Environment env) {
             return new SimpleString(s.toLowerCase(env.getLocale()));
         }
-    }    
+    }
+
+    static class c_lower_caseBI extends BuiltInForString {
+        @Override
+        TemplateModel calculateResult(String s, Environment env) {
+            return new SimpleString(s.toLowerCase(Locale.ROOT));
+        }
+    }
 
     static class padBI extends BuiltInForString {
         
@@ -922,6 +925,13 @@ class BuiltInsForStringsBasic {
         }
     }
 
+    static class c_upper_caseBI extends BuiltInForString {
+        @Override
+        TemplateModel calculateResult(String s, Environment env) {
+            return new SimpleString(s.toUpperCase(Locale.ROOT));
+        }
+    }
+
     static class word_listBI extends BuiltInForString {
         @Override
         TemplateModel calculateResult(String s, Environment env) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/JSONParser.java b/freemarker-core/src/main/java/org/apache/freemarker/core/JSONParser.java
index 5c5ae480..50ef8de8 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/JSONParser.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/JSONParser.java
@@ -19,25 +19,14 @@
 
 package org.apache.freemarker.core;
 
-import java.math.BigDecimal;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateNullModel;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.TemplateStringModel;
-import org.apache.freemarker.core.model.impl.SimpleHash;
+import org.apache.freemarker.core.model.*;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
 import org.apache.freemarker.core.model.impl.SimpleString;
 import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.util._NumberUtils;
 import org.apache.freemarker.core.util._StringUtils;
 
-import jdk.nashorn.internal.objects.NativeNumber;
+import java.math.BigDecimal;
 
 /**
  * JSON parser that returns a {@link TameplatModel}, similar to what FTL literals product (and so, what
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedAOrAn.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedAOrAn.java
index 1c5bc093..c2a62071 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedAOrAn.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedAOrAn.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedAOrAn extends _DelayedConversionToString {
 
     public _DelayedAOrAn(Object object) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedConversionToString.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedConversionToString.java
index 4fbe13fa..7859407e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedConversionToString.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedConversionToString.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public abstract class _DelayedConversionToString {
 
     private static final String NOT_SET = new String();
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetCanonicalForm.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetCanonicalForm.java
index 38a4cd80..077c6481 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetCanonicalForm.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetCanonicalForm.java
@@ -20,7 +20,7 @@
 package org.apache.freemarker.core;
 
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedGetCanonicalForm extends _DelayedConversionToString {
     
     public _DelayedGetCanonicalForm(ASTNode obj) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessage.java
index 7bef399e..676ccb9d 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessage.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedGetMessage extends _DelayedConversionToString {
 
     public _DelayedGetMessage(Throwable exception) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessageWithoutStackTop.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessageWithoutStackTop.java
index 7694c15f..a94d360f 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessageWithoutStackTop.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedGetMessageWithoutStackTop.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedGetMessageWithoutStackTop extends _DelayedConversionToString {
 
     public _DelayedGetMessageWithoutStackTop(TemplateException exception) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuote.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuote.java
index 0d045742..73786c8f 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuote.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuote.java
@@ -21,7 +21,7 @@ package org.apache.freemarker.core;
 
 import org.apache.freemarker.core.util._StringUtils;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedJQuote extends _DelayedConversionToString {
 
     public _DelayedJQuote(Object object) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuotedListing.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuotedListing.java
index d2512815..0852fa07 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuotedListing.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJQuotedListing.java
@@ -19,11 +19,11 @@
 
 package org.apache.freemarker.core;
 
-import java.util.Collection;
-
 import org.apache.freemarker.core.util._StringUtils;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+import java.util.Collection;
+
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedJQuotedListing extends _DelayedConversionToString {
 
     public _DelayedJQuotedListing(Collection<?> object) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJoinWithComma.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJoinWithComma.java
index 7ae1da33..2234609f 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJoinWithComma.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedJoinWithComma.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedJoinWithComma extends _DelayedConversionToString {
 
     public _DelayedJoinWithComma(String[] items) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedTemplateLanguageTypeDescription.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedTemplateLanguageTypeDescription.java
index 4c22bc27..a49493cd 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedTemplateLanguageTypeDescription.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_DelayedTemplateLanguageTypeDescription.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.util.TemplateLanguageUtils;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _DelayedTemplateLanguageTypeDescription extends _DelayedConversionToString {
     
     public _DelayedTemplateLanguageTypeDescription(TemplateModel tm) {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_ErrorDescriptionBuilder.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_ErrorDescriptionBuilder.java
index f00da1ab..792634d1 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_ErrorDescriptionBuilder.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_ErrorDescriptionBuilder.java
@@ -19,18 +19,18 @@
 
 package org.apache.freemarker.core;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-
 import org.apache.freemarker.core.model.impl._MethodUtils;
 import org.apache.freemarker.core.util._ClassUtils;
 import org.apache.freemarker.core.util._StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
 /**
- * Used internally only, might changes without notice!
+ * Used internally only, might change without notice!
  * Packs a structured from of the error description from which the error message can be rendered on-demand.
  * Note that this class isn't serializable, thus the containing exception should render the message before it's
  * serialized.
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8.java
index 037ef9a6..491a3ddc 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core;
 import java.lang.reflect.Method;
 
 /**
- * Used internally only, might changes without notice!
+ * Used internally only, might change without notice!
  * Used for accessing functionality that's only present in Java 6 or later.
  */
 public interface _Java8 {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8Impl.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8Impl.java
index 527a180a..c94fbf5c 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8Impl.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_Java8Impl.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core;
 import java.lang.reflect.Method;
 
 /**
- * Used internally only, might changes without notice!
+ * Used internally only, might change without notice!
  * Used for accessing functionality that's only present in Java 8 or later.
  */
 public final class _Java8Impl implements _Java8 {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluationException.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluationException.java
index 6c8e700c..8b3410c7 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluationException.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluationException.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core;
 import org.apache.freemarker.core.util._StringUtils;
 
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * Thrown by {@link _ObjectBuilderSettingEvaluator}.
  */
 public class _ObjectBuilderSettingEvaluationException extends Exception {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
index ec52865c..9bfd1c35 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
@@ -19,6 +19,17 @@
 
 package org.apache.freemarker.core;
 
+import org.apache.freemarker.core.model.ObjectWrappingException;
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.JavaMethodModel;
+import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper;
+import org.apache.freemarker.core.outputformat.impl.*;
+import org.apache.freemarker.core.pluggablebuiltin.impl.DefaultTruncateBuiltinAlgorithm;
+import org.apache.freemarker.core.templateresolver.*;
+import org.apache.freemarker.core.util.*;
+
 import java.beans.Introspector;
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Field;
@@ -27,45 +38,10 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.freemarker.core.model.ObjectWrappingException;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
-import org.apache.freemarker.core.model.impl.JavaMethodModel;
-import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper;
-import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
-import org.apache.freemarker.core.outputformat.impl.PlainTextOutputFormat;
-import org.apache.freemarker.core.outputformat.impl.RTFOutputFormat;
-import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
-import org.apache.freemarker.core.outputformat.impl.XHTMLOutputFormat;
-import org.apache.freemarker.core.outputformat.impl.XMLOutputFormat;
-import org.apache.freemarker.core.pluggablebuiltin.impl.DefaultTruncateBuiltinAlgorithm;
-import org.apache.freemarker.core.templateresolver.AndMatcher;
-import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.FileExtensionMatcher;
-import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
-import org.apache.freemarker.core.templateresolver.FirstMatchTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.MergingTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.NotMatcher;
-import org.apache.freemarker.core.templateresolver.OrMatcher;
-import org.apache.freemarker.core.templateresolver.PathGlobMatcher;
-import org.apache.freemarker.core.templateresolver.PathRegexMatcher;
-import org.apache.freemarker.core.util.BugException;
-import org.apache.freemarker.core.util.GenericParseException;
-import org.apache.freemarker.core.util.TemplateLanguageUtils;
-import org.apache.freemarker.core.util._ClassUtils;
-import org.apache.freemarker.core.util._StringUtils;
+import java.util.*;
 
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * 
  * Evaluates object builder expressions used in configuration {@link Properties}.
  * It should be replaced with FTL later (when it was improved to be practical for this), so the syntax should be
@@ -442,7 +418,7 @@ public class _ObjectBuilderSettingEvaluator {
                         }
                     } else {
                         if (resultCoerced) {
-                            // The FTL way (BigDecimal is loseless, and it will be coerced to the target type later):
+                            // The FTL way (BigDecimal is lossless, and it will be coerced to the target type later):
                             return new BigDecimal(numStr);
                         } else {
                             // The Java way (lossy but familiar):
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_SettingEvaluationEnvironment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_SettingEvaluationEnvironment.java
index 9501185e..d4f68470 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_SettingEvaluationEnvironment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_SettingEvaluationEnvironment.java
@@ -19,12 +19,12 @@
 
 package org.apache.freemarker.core;
 
-import java.util.Properties;
-
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 
+import java.util.Properties;
+
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * The runtime environment used during the evaluation of configuration {@link Properties}.
  */
 public class _SettingEvaluationEnvironment {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_UnexpectedTypeErrorExplainerTemplateModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_UnexpectedTypeErrorExplainerTemplateModel.java
index 56481b87..456bef97 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_UnexpectedTypeErrorExplainerTemplateModel.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_UnexpectedTypeErrorExplainerTemplateModel.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core;
 import org.apache.freemarker.core.model.TemplateModel;
 
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * 
  * <p>Implemented by {@link TemplateModel}-s that can explain why they don't implement a certain type. 
  * */
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/arithmetic/impl/BigDecimalArithmeticEngine.java b/freemarker-core/src/main/java/org/apache/freemarker/core/arithmetic/impl/BigDecimalArithmeticEngine.java
index 827b0e84..63512a07 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/arithmetic/impl/BigDecimalArithmeticEngine.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/arithmetic/impl/BigDecimalArithmeticEngine.java
@@ -18,11 +18,11 @@
  */
 package org.apache.freemarker.core.arithmetic.impl;
 
-import java.math.BigDecimal;
-
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
 import org.apache.freemarker.core.util._NumberUtils;
 
+import java.math.BigDecimal;
+
 /**
  * Arithmetic engine that converts all numbers to {@link BigDecimal} and then operates on them, and also keeps the
  * result as a {@link BigDecimal}. This is FreeMarker's default arithmetic engine.
@@ -48,7 +48,7 @@ public class BigDecimalArithmeticEngine extends ArithmeticEngine {
             return 0;
         } else {
             // The most common case is comparing values of the same type. As BigDecimal can represent all of these
-            // with loseless round-trip (i.e., converting to BigDecimal and then back the original type gives the
+            // with lossless round-trip (i.e., converting to BigDecimal and then back the original type gives the
             // original value), we can avoid conversion to BigDecimal without changing the result.
             if (first.getClass() == second.getClass()) {
                 // Bit of optimization for this is a very common case:
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/debug/_DebuggerService.java b/freemarker-core/src/main/java/org/apache/freemarker/core/debug/_DebuggerService.java
index 4d379178..9f5caf4d 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/debug/_DebuggerService.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/debug/_DebuggerService.java
@@ -19,16 +19,16 @@
 
 package org.apache.freemarker.core.debug;
 
-import java.rmi.RemoteException;
-import java.util.Collections;
-import java.util.List;
-
 import org.apache.freemarker.core.Environment;
 import org.apache.freemarker.core.Template;
 import org.apache.freemarker.core.util._SecurityUtils;
 
+import java.rmi.RemoteException;
+import java.util.Collections;
+import java.util.List;
+
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * This class provides debugging hooks for the core FreeMarker engine. It is
  * not usable for anyone outside the FreeMarker core classes.
  */
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
index aff86575..3f813981 100644
--- 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
@@ -27,8 +27,8 @@ import org.apache.freemarker.core.outputformat.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}.
+ * Each implementation of this type has a corresponding {@link OutputFormat} subclass, 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 TemplateStringModel}-s, and so
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/CommonMarkupOutputFormat.java b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/CommonMarkupOutputFormat.java
index 337d37bc..ce1ee85a 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/CommonMarkupOutputFormat.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/CommonMarkupOutputFormat.java
@@ -18,11 +18,11 @@
  */
 package org.apache.freemarker.core.outputformat;
 
+import org.apache.freemarker.core.TemplateException;
+
 import java.io.IOException;
 import java.io.Writer;
 
-import org.apache.freemarker.core.TemplateException;
-
 /**
  * Common superclass for implementing {@link MarkupOutputFormat}-s that use a {@link CommonTemplateMarkupOutputModel}
  * subclass.
@@ -115,6 +115,16 @@ public abstract class CommonMarkupOutputFormat<MO extends CommonTemplateMarkupOu
 
     /**
      * Creates a new {@link CommonTemplateMarkupOutputModel} that's bound to this {@link OutputFormat} instance.
+     * When this is called from {@link CommonMarkupOutputFormat}, exactly one of the parameters will be
+     * non-{@code null}.
+     *
+     * @param plainTextContent
+     *      {@code null} if the content is markup that possibly can be described as plain text without loss.
+     * @param markupContent
+     *      Typically will be {@code null} if {@code plainTextContent} is not {@code null}. While the plain text always
+     *      can be converted to markup via {@link #escapePlainText(String)}, it's up to the implementation if it wants
+     *      to do that now and store the markup, or later on demand (like each time when
+     *      {@link #getMarkupString(CommonTemplateMarkupOutputModel)} is called).
      */
     protected abstract MO newTemplateMarkupOutputModel(String plainTextContent, String markupContent)
             throws TemplateException;
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/MarkupOutputFormat.java b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/MarkupOutputFormat.java
index 77ba50c6..ed0b36fb 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/MarkupOutputFormat.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/MarkupOutputFormat.java
@@ -18,15 +18,15 @@
  */
 package org.apache.freemarker.core.outputformat;
 
-import java.io.IOException;
-import java.io.Writer;
-
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.TemplateHTMLOutputModel;
 
+import java.io.IOException;
+import java.io.Writer;
+
 /**
  * Superclass of {@link OutputFormat}-s that represent a "markup" format, which is any format where certain character
  * sequences have special meaning and thus may need escaping. (Escaping is important for FreeMarker, as typically it has
@@ -78,7 +78,7 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
 
     /**
      * Equivalent to calling {@link #fromPlainTextByEscaping(String)} and then
-     * {@link #output(TemplateMarkupOutputModel, Writer)}, but the implementation may uses a more efficient solution.
+     * {@link #output(TemplateMarkupOutputModel, Writer)}, but the implementation may use a more efficient solution.
      */
     public abstract void output(String textToEsc, Writer out) throws IOException, TemplateException;
     
@@ -106,7 +106,7 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
     
     /**
      * Should give the same result as {@link #fromPlainTextByEscaping(String)} and then
-     * {@link #getMarkupString(TemplateMarkupOutputModel)}, but the implementation may uses a more efficient solution.
+     * {@link #getMarkupString(TemplateMarkupOutputModel)}, but the implementation may use a more efficient solution.
      */
     public abstract String escapePlainText(String plainTextContent) throws TemplateException;
 
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingSource.java b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingSource.java
index fe39b54a..e1ad6391 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingSource.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingSource.java
@@ -18,16 +18,16 @@
  */
 package org.apache.freemarker.core.templateresolver;
 
-import java.io.Serializable;
-import java.util.HashMap;
-
 import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader;
 import org.apache.freemarker.core.templateresolver.impl.FileTemplateLoader;
 
+import java.io.Serializable;
+import java.util.HashMap;
+
 /**
  * The point of {@link TemplateLoadingSource} is that with their {@link Object#equals(Object)} method we can tell if two
  * cache entries were generated from the same physical resource or not. Comparing the template names isn't enough,
- * because a {@link TemplateLoader} may uses some kind of fallback mechanism, such as delegating to other
+ * because a {@link TemplateLoader} may use some kind of fallback mechanism, such as delegating to other
  * {@link TemplateLoader}-s until the template is found. Like if we have two {@link FileTemplateLoader}-s with different
  * physical root directories, both can contain {@code "foo/bar.f3ah"}, but obviously the two files aren't the same.
  * 
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayAdapterList.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayAdapterList.java
index c3e5d8f9..eab4adb5 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayAdapterList.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayAdapterList.java
@@ -24,7 +24,7 @@ import java.util.Arrays;
 import java.util.Iterator;
 
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * Immutable list that wraps an array that's known to be non-changing.
  */
 public class _ArrayAdapterList<E> extends AbstractList<E> {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayIterator.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayIterator.java
index 0ff9241a..68d2225c 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayIterator.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ArrayIterator.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core.util;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _ArrayIterator<T> implements Iterator<T> {
 
     private final T[] array;
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
index 00aaadfb..2647e61f 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
@@ -19,6 +19,8 @@
 
 package org.apache.freemarker.core.util;
 
+import org.apache.freemarker.core.model.impl.BeanModel;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Array;
@@ -27,8 +29,6 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.freemarker.core.model.impl.BeanModel;
-
 public class _ClassUtils {
     
     private static final String ORG_APACHE_FREEMARKER = "org.apache.freemarker.";
@@ -216,7 +216,7 @@ public class _ClassUtils {
             throws IOException {
         InputStream ins;
         try {
-            // This is how we did this earlier. May uses some JarURLConnection caches, which leads to the problems.
+            // This is how we did this earlier. May use some JarURLConnection caches, which leads to the problems.
             ins = baseClass.getResourceAsStream(resource);
         } catch (Exception e) {
             // Workaround for "IllegalStateException: zip file closed", and other related exceptions. This happens due
@@ -261,7 +261,7 @@ public class _ClassUtils {
         InputStream ins  = null;
         try {
             try {
-                // This is how we did this earlier. May uses some JarURLConnection caches, which leads to the problems.
+                // This is how we did this earlier. May use some JarURLConnection caches, which leads to the problems.
                 ins = baseClass.getResourceAsStream(resource);
             } catch (Exception e) {
                 throw new MaybeZipFileClosedException();
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtils.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtils.java
index 60b94a72..ba9069b4 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtils.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtils.java
@@ -19,18 +19,10 @@
 
 package org.apache.freemarker.core.util;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * {@link Collection} and {@link Map}-related utilities.
  */
 public class _CollectionUtils {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_DateUtils.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_DateUtils.java
index 60201b6b..e010d9fd 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_DateUtils.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_DateUtils.java
@@ -20,16 +20,12 @@
 package org.apache.freemarker.core.util;
 
 import java.text.ParseException;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
- * Don't use this; used internally by FreeMarker, might changes without notice.
+ * Don't use this; used internally by FreeMarker, might change without notice.
  * Date and time related utilities.
  */
 public class _DateUtils {
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
index 88efaca0..986e2437 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_JavaVersions.java
@@ -24,7 +24,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Used internally only, might changes without notice!
+ * Used internally only, might change without notice!
  */
 public final class _JavaVersions {
 
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_NumberUtils.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_NumberUtils.java
index 9c65eaf7..bfd324be 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_NumberUtils.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_NumberUtils.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core.util;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _NumberUtils {
 
     private static final BigDecimal BIG_DECIMAL_INT_MIN = BigDecimal.valueOf(Integer.MIN_VALUE);
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_SortedArraySet.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_SortedArraySet.java
index 788fed7d..414da33f 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_SortedArraySet.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_SortedArraySet.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _SortedArraySet<E> extends _UnmodifiableSet<E> {
 
     private final E[] array;
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_StringUtils.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_StringUtils.java
index 587b20fa..228488e7 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_StringUtils.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_StringUtils.java
@@ -19,6 +19,10 @@
 
 package org.apache.freemarker.core.util;
 
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.Template;
+import org.apache.freemarker.core.Version;
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
@@ -29,11 +33,7 @@ import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.regex.Pattern;
 
-import org.apache.freemarker.core.Environment;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.Version;
-
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _StringUtils {
 
     private static final char[] LT = new char[] { '&', 'l', 't', ';' };
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableCompositeSet.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableCompositeSet.java
index ab88f57f..23034d06 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableCompositeSet.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableCompositeSet.java
@@ -22,7 +22,7 @@ package org.apache.freemarker.core.util;
 import java.util.Iterator;
 import java.util.Set;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public class _UnmodifiableCompositeSet<E> extends _UnmodifiableSet<E> {
     
     private final Set<E> set1, set2;
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableSet.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableSet.java
index 7e08815d..464e8410 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableSet.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_UnmodifiableSet.java
@@ -21,7 +21,7 @@ package org.apache.freemarker.core.util;
 
 import java.util.AbstractSet;
 
-/** Don't use this; used internally by FreeMarker, might changes without notice. */
+/** Don't use this; used internally by FreeMarker, might change without notice. */
 public abstract class _UnmodifiableSet<E> extends AbstractSet<E> {
 
     @Override
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormat.java b/freemarker-core/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormat.java
index 25e7ad46..47904edb 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormat.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormat.java
@@ -18,8 +18,6 @@
  */
 package org.apache.freemarker.core.valueformat;
 
-import java.text.NumberFormat;
-
 import org.apache.freemarker.core.Environment;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
@@ -27,6 +25,8 @@ import org.apache.freemarker.core.model.TemplateDateModel;
 import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.model.TemplateNumberModel;
 
+import java.text.NumberFormat;
+
 /**
  * Represents a number format; used in templates for formatting and parsing with that format. This is similar to Java's
  * {@link NumberFormat}, but made to fit the requirements of FreeMarker. Also, it makes easier to define formats that
@@ -84,7 +84,7 @@ public abstract class TemplateNumberFormat extends TemplateValueFormat {
      * will be support, it will be similar to {@link TemplateDateFormat#parse(String, int)}.
      */
     public final Object parse(String s) throws TemplateValueFormatException {
-        throw new ParsingNotSupportedException("Number formats currenly don't support parsing");
+        throw new ParsingNotSupportedException("Number formats currently don't support parsing");
     }
     
     
diff --git a/freemarker-manual/src/main/docgen/en_US/book.xml b/freemarker-manual/src/main/docgen/en_US/book.xml
index 2f9d3b7d..c8492a93 100644
--- a/freemarker-manual/src/main/docgen/en_US/book.xml
+++ b/freemarker-manual/src/main/docgen/en_US/book.xml
@@ -10604,7 +10604,7 @@ cfg.setNumberFormat("@ua 0.####;; roundingMode=halfUp");</programlisting>
         linkend="gloss.unicode">UNICODE</link> text" (UTF-16). Nonetheless,
         there are situations when it must deal with <link
         linkend="gloss.charset">charsets</link>, because it has to exchange
-        data with the outer world that may uses various other charsets.</para>
+        data with the outer world that may use various other charsets.</para>
 
         <section>
           <title>The charset of the input</title>
@@ -28786,7 +28786,7 @@ End book</programlisting>
           <answer>
             <para>FreeMarker uses the locale-sensitive number formatting
             capability of the Java platform. The default number format for
-            your locale may uses grouping or other formatting. If you don't
+            your locale may use grouping or other formatting. If you don't
             want that, you have to override the number format suggested by the
             Java platform with the <literal>number_format</literal> <link
             linkend="pgui_config_settings">FreeMarker setting</link>. For
diff --git a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/CopyrightCommentRemoverTemplateLoader.java b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
index 3c03a873..7a564ffa 100644
--- a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
+++ b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
@@ -19,20 +19,12 @@
 
 package org.apache.freemarker.test;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.Serializable;
-import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.input.ReaderInputStream;
-import org.apache.freemarker.core.templateresolver.TemplateLoader;
-import org.apache.freemarker.core.templateresolver.TemplateLoaderSession;
-import org.apache.freemarker.core.templateresolver.TemplateLoadingResult;
-import org.apache.freemarker.core.templateresolver.TemplateLoadingResultStatus;
-import org.apache.freemarker.core.templateresolver.TemplateLoadingSource;
+import org.apache.freemarker.core.templateresolver.*;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
 
 /**
  * Removes the Apache copyright boiler plate from the beginning of the template, so that they don't mess up the expected
@@ -92,7 +84,7 @@ public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader {
             return null;
         }
         try {
-            // Encoding then decosing in ISO-8859-1 is binary loseless
+            // Encoding then decoding in ISO-8859-1 is binary lossless
             String content = IOUtils.toString(in, StandardCharsets.ISO_8859_1.name());
             return new ReaderInputStream(
                     new StringReader(TestUtils.removeFTLCopyrightComment(content)),


[freemarker] 04/09: Forward ported from 2.3-gae: FREEMARKER-198: To avoid deadlock when class initialization happens on multiple threads (like _TemplateAPI->DefaultObjectWrapper, and DefaultObjectWrapper->_TemplateAPI), factored out static fields from _TemplateAPI into their owns classes.

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit f27a127666c37e8400d8dd4cf079247e9e25605d
Author: ddekany <dd...@apache.org>
AuthorDate: Sat Dec 31 23:46:38 2022 +0100

    Forward ported from 2.3-gae: FREEMARKER-198: To avoid deadlock when class initialization happens on multiple threads (like _TemplateAPI->DefaultObjectWrapper, and DefaultObjectWrapper->_TemplateAPI), factored out static fields from _TemplateAPI into their owns classes.
---
 .../apache/freemarker/core/ConfigurationTest.java  | 85 ++++++----------------
 .../core/model/impl/DefaultObjectWrapperTest.java  | 60 +++------------
 .../org/apache/freemarker/core/NativeSequence.java | 10 +--
 .../java/org/apache/freemarker/core/_CoreAPI.java  |  6 +-
 .../org/apache/freemarker/core/_VersionInts.java   | 32 ++++++++
 5 files changed, 75 insertions(+), 118 deletions(-)

diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
index 8c1791de..f5486e5b 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
@@ -19,42 +19,11 @@
 
 package org.apache.freemarker.core;
 
-import static org.apache.freemarker.core.Configuration.*;
-import static org.apache.freemarker.core.Configuration.ExtendableBuilder.*;
-import static org.apache.freemarker.test.hamcerst.Matchers.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.TreeSet;
-
-import org.apache.freemarker.core.Configuration.*;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import org.apache.freemarker.core.model.TemplateHashModel;
 import org.apache.freemarker.core.model.TemplateStringModel;
-import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
-import org.apache.freemarker.core.model.impl.MemberAccessPolicy;
-import org.apache.freemarker.core.model.impl.MemberSelectorListMemberAccessPolicy;
-import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper;
-import org.apache.freemarker.core.model.impl.SimpleString;
-import org.apache.freemarker.core.model.impl.WhitelistMemberAccessPolicy;
+import org.apache.freemarker.core.model.impl.*;
 import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.outputformat.UnregisteredOutputFormatException;
@@ -62,31 +31,9 @@ import org.apache.freemarker.core.outputformat.impl.CombinedMarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.RTFOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.XMLOutputFormat;
-import org.apache.freemarker.core.templateresolver.CacheStorageWithGetSize;
-import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
-import org.apache.freemarker.core.templateresolver.TemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.TemplateConfigurationFactoryException;
-import org.apache.freemarker.core.templateresolver.TemplateLookupContext;
-import org.apache.freemarker.core.templateresolver.TemplateLookupResult;
-import org.apache.freemarker.core.templateresolver.TemplateLookupStrategy;
-import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader;
-import org.apache.freemarker.core.templateresolver.impl.ClassTemplateLoader;
-import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateLookupStrategy;
-import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormat;
-import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver;
-import org.apache.freemarker.core.templateresolver.impl.NullCacheStorage;
-import org.apache.freemarker.core.templateresolver.impl.SoftCacheStorage;
-import org.apache.freemarker.core.templateresolver.impl.StringTemplateLoader;
-import org.apache.freemarker.core.templateresolver.impl.StrongCacheStorage;
-import org.apache.freemarker.core.userpkg.BaseNTemplateNumberFormatFactory;
-import org.apache.freemarker.core.userpkg.CustomHTMLOutputFormat;
-import org.apache.freemarker.core.userpkg.DummyOutputFormat;
-import org.apache.freemarker.core.userpkg.EpochMillisDivTemplateDateFormatFactory;
-import org.apache.freemarker.core.userpkg.EpochMillisTemplateDateFormatFactory;
-import org.apache.freemarker.core.userpkg.HexTemplateNumberFormatFactory;
-import org.apache.freemarker.core.userpkg.NameClashingDummyOutputFormat;
-import org.apache.freemarker.core.userpkg.SeldomEscapedOutputFormat;
+import org.apache.freemarker.core.templateresolver.*;
+import org.apache.freemarker.core.templateresolver.impl.*;
+import org.apache.freemarker.core.userpkg.*;
 import org.apache.freemarker.core.util._CollectionUtils;
 import org.apache.freemarker.core.util._DateUtils;
 import org.apache.freemarker.core.util._NullWriter;
@@ -94,8 +41,22 @@ import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
 import org.junit.Test;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+import static org.apache.freemarker.core.Configuration.*;
+import static org.apache.freemarker.core.Configuration.ExtendableBuilder.*;
+import static org.apache.freemarker.test.hamcerst.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
 
 public class ConfigurationTest {
 
@@ -223,7 +184,7 @@ public class ConfigurationTest {
     @Test
     public void testVersion() {
         Version v = getVersion();
-        assertTrue(v.intValue() >= _CoreAPI.VERSION_INT_3_0_0);
+        assertTrue(v.intValue() >= _VersionInts.VERSION_INT_3_0_0);
         
         try {
             new Builder(new Version(999, 1, 2)).build();
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
index 010705c2..80d8096b 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java
@@ -19,57 +19,21 @@
 
 package org.apache.freemarker.core.model.impl;
 
-import static org.apache.freemarker.test.hamcerst.Matchers.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.Vector;
-
-import org.apache.freemarker.core.Configuration;
-import org.apache.freemarker.core.NonTemplateCallPlace;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.Version;
-import org.apache.freemarker.core._CoreAPI;
-import org.apache.freemarker.core.model.AdapterTemplateModel;
-import org.apache.freemarker.core.model.ObjectWrapper;
-import org.apache.freemarker.core.model.ObjectWrappingException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx;
-import org.apache.freemarker.core.model.TemplateIterableModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelIterator;
-import org.apache.freemarker.core.model.TemplateModelWithAPISupport;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.TemplateStringModel;
-import org.apache.freemarker.core.model.WrapperTemplateModel;
-import org.apache.freemarker.core.model.WrappingTemplateModel;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.apache.freemarker.core.*;
+import org.apache.freemarker.core.model.*;
 import org.apache.freemarker.core.util.CallableUtils;
 import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.*;
+
+import static org.apache.freemarker.test.hamcerst.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
 
 public class DefaultObjectWrapperTest {
 
@@ -83,7 +47,7 @@ public class DefaultObjectWrapperTest {
         expected.add(Configuration.VERSION_3_0_0);
 
         List<Version> actual = new ArrayList<>();
-        int i = _CoreAPI.VERSION_INT_3_0_0;
+        int i = _VersionInts.VERSION_INT_3_0_0;
         while (i <= Configuration.getVersion().intValue()) {
             int major = i / 1000000;
             int minor = i % 1000000 / 1000;
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java b/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java
index a56febfc..cf99ea0e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java
@@ -19,17 +19,17 @@
 
 package org.apache.freemarker.core;
 
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-
 import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelIterator;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+
 /**
- * A sequence where each items is already a {@link TemplateModel}, so no {@link ObjectWrapper} need to be specified.
+ * A sequence where each item is already a {@link TemplateModel}, so no {@link ObjectWrapper} need to be specified.
  *
  * <p>While this class allows adding items, doing so is not thread-safe, and thus only meant to be done during the
  * initialization of the sequence.
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java
index 14de157d..b408c9e1 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java
@@ -28,8 +28,8 @@ import org.apache.freemarker.core.util._NullArgumentException;
  * access things inside this package that users shouldn't. 
  */ 
 public final class _CoreAPI {
-
-    public static final int VERSION_INT_3_0_0 = Configuration.VERSION_3_0_0.intValue();
+    // ATTENTION! Don't refer to other classes in the static initializer of this class! Fields that need that must be
+    // moved into a separate class, to avoid class init deadlocks.
 
     // Can't be instantiated
     private _CoreAPI() { }
@@ -66,7 +66,7 @@ public final class _CoreAPI {
                     + incompatibleImprovements + ", but the installed FreeMarker version is only "
                     + Configuration.getVersion() + ". You may need to upgrade FreeMarker in your project.");
         }
-        if (iciV < VERSION_INT_3_0_0) {
+        if (iciV < _VersionInts.VERSION_INT_3_0_0) {
             throw new IllegalArgumentException("\"incompatibleImprovements\" must be at least 3.0.0, but was "
                     + incompatibleImprovements);
         }
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_VersionInts.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_VersionInts.java
new file mode 100644
index 00000000..711f4c3c
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_VersionInts.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+/**
+ * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
+ * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
+ * access things inside this package that users shouldn't.
+ */
+// Because we refer to other classes in the static initializer of this class, be careful with referring this class in
+// the static initializers of other classes, as that can lead to deadlock if the class initialization locks are acquired
+// by the JVM in different orders! This is also why this was extracted from _CoreAPI.
+public class _VersionInts {
+    public static final int VERSION_INT_3_0_0 = Configuration.VERSION_3_0_0.intValue();
+}