blob: 49d3f03eadd4f51e64e6d6dd5a424e45fcacd51e [file] [log] [blame]
<?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.
-->
<book conformance="docgen" version="5.0" xml:lang="en"
xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ns5="http://www.w3.org/1998/Math/MathML"
xmlns:ns4="http://www.w3.org/1999/xhtml"
xmlns:ns3="http://www.w3.org/2000/svg"
xmlns:ns="http://docbook.org/ns/docbook">
<info>
<title>Apache FreeMarker Manual</title>
<titleabbrev>Manual</titleabbrev>
<productname>Freemarker 2.3.31</productname>
</info>
<preface role="index.html" xml:id="preface">
<title>What is Apache FreeMarker?</title>
<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>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>
<mediaobject>
<imageobject>
<imagedata fileref="figures/overview.png"/>
</imageobject>
</mediaobject>
<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>
<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>
<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_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 <link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setSetting-java.lang.String-java.lang.String-">Java
API documentation of
<literal>Configuration.setSetting(...)</literal></link>.</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(
"A format parameter is required to specify the numerical system base.");
}
throw new InvalidFormatParametersException(
"The format paramter must be an integer, but was (shown quoted): "
+ StringUtil.jQuote(params));
}
if (base &lt; 2) {
throw new InvalidFormatParametersException("A base must be at least 2.");
}
return new BaseNTemplateNumberFormat(base, fallbackFormat);
}
private static class BaseNTemplateNumberFormat extends TemplateNumberFormat {
private final int base;
private final TemplateNumberFormat fallbackFormat;
private BaseNTemplateNumberFormat(int base, TemplateNumberFormat fallbackFormat) {
this.base = base;
this.fallbackFormat = fallbackFormat;
}
@Override
public String formatToPlainText(TemplateNumberModel numberModel)
throws TemplateModelException, TemplateValueFormatException {
Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
try {
return Integer.toString(NumberUtil.toIntExact(n), base);
} catch (ArithmeticException e) {
if (fallbackFormat == null) {
throw new UnformattableValueException(
n + " doesn't fit into an int, and there was no fallback format "
+ "specified.");
} else {
return fallbackFormat.formatToPlainText(numberModel);
}
}
}
@Override
public boolean isLocaleBound() {
return false;
}
@Override
public String getDescription() {
return "base " + base;
}
}
}</programlisting>
<para>We register the above format with name
<quote>base</quote>:</para>
<programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
Configuration cfg = ...;
...
Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats = ...;
...
customNumberFormats.put("base", BaseNTemplateNumberFormatFactory.INSTANCE);
...
cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
<para>Now we can use this format in templates:</para>
<programlisting role="template">${x?string.@base_8}</programlisting>
<para>Above there the parameter string was <literal>"8"</literal>,
as FreeMarker allows separating that from the format name with
<literal>_</literal> instead of whitespace, so that you don't have
to write the longer
<literal><replaceable>n</replaceable>?string["@base 8"]</literal>
form.</para>
<para>Of course, we could also set this as the default number format
like:</para>
<programlisting role="unspecified">cfg.setNumberFormat("@base 8");</programlisting>
<para>Here's an example of using the a fallback number format (which
is <literal>"0.0###"</literal>):</para>
<programlisting role="unspecified">cfg.setNumberFormat("@base 8|0.0###");</programlisting>
<para>Note that this functionality, with the <literal>|</literal>
syntax and all, is purely implemented in the example code
earlier.</para>
</section>
<section xml:id="pgui_config_custom_formats_ex_cust_algo_date">
<title>Custom date/time format example</title>
<para>This simple date format formats the date/time value to the
milliseconds since the epoch:</para>
<programlisting role="unspecified">package com.example;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateModelException;
public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFactory {
public static final EpochMillisTemplateDateFormatFactory INSTANCE
= new EpochMillisTemplateDateFormatFactory();
private EpochMillisTemplateDateFormatFactory() {
// Defined to decrease visibility
}
@Override
public TemplateDateFormat get(String params, int dateType,
Locale locale, TimeZone timeZone, boolean zonelessInput,
Environment env)
throws InvalidFormatParametersException {
TemplateFormatUtil.checkHasNoParameters(params);
return EpochMillisTemplateDateFormat.INSTANCE;
}
private static class EpochMillisTemplateDateFormat extends TemplateDateFormat {
private static final EpochMillisTemplateDateFormat INSTANCE
= new EpochMillisTemplateDateFormat();
private EpochMillisTemplateDateFormat() { }
@Override
public String formatToPlainText(TemplateDateModel dateModel)
throws UnformattableValueException, TemplateModelException {
return String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime());
}
@Override
public boolean isLocaleBound() {
return false;
}
@Override
public boolean isTimeZoneBound() {
return false;
}
@Override
public Date parse(String s, int dateType) throws UnparsableValueException {
try {
return new Date(Long.parseLong(s));
} catch (NumberFormatException e) {
throw new UnparsableValueException("Malformed long");
}
}
@Override
public String getDescription() {
return "millis since the epoch";
}
}
}</programlisting>
<para>We register the above format with name
<quote>epoch</quote>:</para>
<programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
Configuration cfg = ...;
...
Map&lt;String, TemplateDateFormatFactory&gt; customDateFormats = ...;
...
customDateFormats.put("epoch", EpochMillisTemplateDateFormatFactory.INSTANCE);
...
cfg.setCustomDateFormats(customDateFormats);</programlisting>
<para>Now we can use this format in templates:</para>
<programlisting role="template">${t?string.@epoch}</programlisting>
<para>Of course, we could also set this as the default date-time
format like:</para>
<programlisting role="unspecified">cfg.setDateTimeFormat("@epoch");</programlisting>
<para>For a more complex that for example uses format parameters,
refer to the <link
linkend="pgui_config_custom_formats_ex_cust_algo_advanced">advanced
number format example</link>. Doing that with date formats is very
similar.</para>
</section>
<section xml:id="pgui_config_custom_formats_ex_alias">
<title>Alias format example</title>
<para>In this example we specify some number formats and date
formats that are aliases to another format:</para>
<programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
Configuration cfg = ...;
Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats
= new HashMap&lt;String, TemplateNumberFormatFactory&gt;();
customNumberFormats.put("price", new AliasTemplateNumberFormatFactory(",000.00"));
customNumberFormats.put("weight",
new AliasTemplateNumberFormatFactory("0.##;; roundingMode=halfUp"));
cfg.setCustomNumberFormats(customNumberFormats);
Map&lt;String, TemplateDateFormatFactory&gt; customDateFormats
= new HashMap&lt;String, TemplateDateFormatFactory&gt;();
customDateFormats.put("fileDate", new AliasTemplateDateFormatFactory("dd/MMM/yy hh:mm a"));
customDateFormats.put("logEventTime", new AliasTemplateDateFormatFactory("iso ms u"));
cfg.setCustomDateFormats(customDateFormats);</programlisting>
<para>So now you can do this in a template:</para>
<programlisting role="template">${product.price?string.@price}
${product.weight?string.@weight}
${lastModified?string.@fileDate}
${lastError.timestamp?string.@logEventTime}</programlisting>
<para>Note that the constructor parameter of
<literal>AliasTemplateNumberFormatFactory</literal> can naturally
refer to a custom format too:</para>
<programlisting role="unspecified">Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats
= new HashMap&lt;String, TemplateNumberFormatFactory&gt;();
customNumberFormats.put("base", BaseNTemplateNumberFormatFactory.INSTANCE);
customNumberFormats.put("oct", new AliasTemplateNumberFormatFactory("@base 8"));
cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
<para>So now
<literal><replaceable>n</replaceable>?string.@oct</literal> will
format the number to octal form.</para>
</section>
<section xml:id="pgui_config_custom_formats_ex_model_aware">
<title>Model-aware format example</title>
<para>In this example we specify a number format that automatically
show the unit after the number if that was put into the data-model
as <literal>UnitAwareTemplateNumberModel</literal>. First let's see
<literal>UnitAwareTemplateNumberModel</literal>:</para>
<programlisting role="unspecified">package com.example;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
public class UnitAwareTemplateNumberModel implements TemplateNumberModel {
private final Number value;
private final String unit;
public UnitAwareTemplateNumberModel(Number value, String unit) {
this.value = value;
this.unit = unit;
}
@Override
public Number getAsNumber() throws TemplateModelException {
return value;
}
public String getUnit() {
return unit;
}
}</programlisting>
<para>When you fill the data-model, you could do something like
this:</para>
<programlisting role="unspecified">Map&lt;String, Object&gt; dataModel = new HashMap&lt;&gt;();
dataModel.put("weight", new UnitAwareTemplateNumberModel(1.5, "kg"));
// Rather than just: dataModel.put("weight", 1.5);</programlisting>
<para>Then if we have this in the template:</para>
<programlisting role="template">${weight}</programlisting>
<para>we want to see this:</para>
<programlisting role="output">1.5 kg</programlisting>
<para>To achieve that, we define this custom number format:</para>
<programlisting role="unspecified">package com.example;
import java.util.Locale;
import freemarker.core.Environment;
import freemarker.core.TemplateNumberFormat;
import freemarker.core.TemplateNumberFormatFactory;
import freemarker.core.TemplateValueFormatException;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
/**
* A number format that takes any other number format as parameter (specified as a string, as
* usual in FreeMarker), then if the model is a {@link UnitAwareTemplateNumberModel}, it shows
* the unit after the number formatted with the other format, otherwise it just shows the formatted
* number without unit.
*/
public class UnitAwareTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
public static final UnitAwareTemplateNumberFormatFactory INSTANCE
= new UnitAwareTemplateNumberFormatFactory();
private UnitAwareTemplateNumberFormatFactory() {
// Defined to decrease visibility
}
@Override
public TemplateNumberFormat get(String params, Locale locale, Environment env)
throws TemplateValueFormatException {
return new UnitAwareNumberFormat(env.getTemplateNumberFormat(params, locale));
}
private static class UnitAwareNumberFormat extends TemplateNumberFormat {
private final TemplateNumberFormat innerFormat;
private UnitAwareNumberFormat(TemplateNumberFormat innerFormat) {
this.innerFormat = innerFormat;
}
@Override
public String formatToPlainText(TemplateNumberModel numberModel)
throws TemplateModelException, TemplateValueFormatException {
String innerResult = innerFormat.formatToPlainText(numberModel);
return numberModel instanceof UnitAwareTemplateNumberModel
? innerResult + " " + ((UnitAwareTemplateNumberModel) numberModel).getUnit()
: innerResult;
}
@Override
public boolean isLocaleBound() {
return innerFormat.isLocaleBound();
}
@Override
public String getDescription() {
return "unit-aware " + innerFormat.getDescription();
}
}
}</programlisting>
<para>Finally, we set the above custom format as the default number
format:</para>
<programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
Configuration cfg = ...;
Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats = new HashMap&lt;&gt;();
customNumberFormats.put("ua", UnitAwareTemplateNumberFormatFactory.INSTANCE);
cfg.setCustomNumberFormats(customNumberFormats);
// Note: "0.####;; roundingMode=halfUp" is a standard format specified in FreeMarker.
cfg.setNumberFormat("@ua 0.####;; roundingMode=halfUp");</programlisting>
</section>
</section>
<section xml:id="pgui_config_incompatible_improvements">
<title>The "incompatible improvements" setting</title>
<indexterm>
<primary>incompatible improvements</primary>
</indexterm>
<indexterm>
<primary>incompatible_improvements</primary>
</indexterm>
<indexterm>
<primary>incompatibleImprovements</primary>
</indexterm>
<indexterm>
<primary>backward compatibility</primary>
</indexterm>
<section>
<title>What does it do</title>
<para>This setting specifies the FreeMarker version number where the
not 100% backward compatible bug fixes and improvements
<emphasis>that you want to enable</emphasis> were already
implemented. Usually, it's a bad idea to left it on its default,
which is 2.3.0 (maximum backward compatibility).</para>
<para>In new projects you should set this to the fixed FreeMarker
version (like <literal>Configuration.VERSION_2_3_28</literal>) that
you are actually using when starting the project. In older projects
it's also usually better to keep this high , however you should
check the changes activated (find them in <link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#Configuration-freemarker.template.Version-">the
API JavaDoc of the <literal>Configuration(Version)</literal>
constructor</link>), especially if not only the 3rd version number
(the micro version) of <quote>incompatible improvements</quote>
setting is increased. Generally, as far as you only increase the
last (3rd) version number of this setting, the changes are low risk,
and whether you can afford that risk depends on the concrete
application. Never use a dynamic value like
<literal>Configuration.getVersion()</literal> though, as that way
upgrading FreeMarker can break your application!</para>
<para>Bug fixes and improvements that are fully backward compatible,
also those that are important security fixes, are enabled regardless
of the <quote>incompatible improvements</quote> setting.</para>
<para>An important consequence of setting this setting is that now
your application will check if the stated minimum FreeMarker version
requirement is met. Like if you set this setting to 2.3.22, but
accidentally the application is deployed with FreeMarker 2.3.21,
then FreeMarker will fail, telling that a higher version is
required. After all, the fixes/improvements you have requested
aren't available on a lower version.</para>
</section>
<section xml:id="pgui_config_incompatible_improvements_how_to_set">
<title>How to set it</title>
<para>The incompatible improvements setting exists on the
<literal>Configuration</literal> level. It can be set on multiple
ways:</para>
<itemizedlist>
<listitem>
<para>Create the
<literal>freemarker.template.Configuration</literal> object
like:</para>
<programlisting role="unspecified">... = new Configuration(Configuration.VERSION_2_3_28)</programlisting>
</listitem>
<listitem>
<para>Or, alter the <literal>Configuration</literal> singleton
where you initialize its other settings like:</para>
<programlisting role="unspecified">cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_28)</programlisting>
</listitem>
<listitem>
<para>Or, if you are configuring FreeMarker with properties
(<literal>*.properties</literal> file or
<literal>java.util.Properties</literal> object), add:</para>
<programlisting role="unspecified">incompatible_improvements=2.3.28</programlisting>
</listitem>
<listitem>
<para>Or, if you are configuring FreeMarker through
<literal>FreemarkerServlet</literal>, add this
<literal>init-param</literal> to it in the
<literal>web.xml</literal>:</para>
<programlisting role="unspecified">&lt;init-param&gt;
&lt;param-name&gt;incompatible_improvements&lt;/param-name&gt;
&lt;param-value&gt;2.3.28&lt;/param-value&gt;
&lt;/init-param&gt;</programlisting>
</listitem>
</itemizedlist>
<para>But, <emphasis>if you set the
<literal>object_wrapper</literal> setting</emphasis> (same as
<literal>Configuration.setObjectWrapper(ObjectWrapper)</literal>) of
your configuration, then it's important to know that
<literal>BeansWrapper</literal> and its subclasses (most
importantly, <literal>DefaultObjectWrapper</literal>) has its own
independent <literal>incompatibleImprovements</literal> property,
and some fixes/improvements are activated by that, not by
<literal>Configuration</literal>'s similar setting. You don't have
to be aware of this complication if you aren't setting the
<literal>object_wrapper</literal> configuration setting anywhere,
because the default <literal>object_wrapper</literal> has the same
<quote>incompatible improvements</quote> as of the
<literal>Configuration</literal>. But if you are setting the
<literal>object_wrapper</literal>, then you must not forget to set
the <literal>incompatibleImprovements</literal> property of the
<literal>ObjectWrapper</literal> itself, in additionally to that of
the <literal>Configuration</literal>. (Note that it's fine to have
different <quote>incompatible improvements</quote> for the
<literal>Configuration</literal> and for the
<literal>ObjectWrapper</literal>, only it should be a conscious
decision.) <link
linkend="topic.setDefaultObjectWrapperIcIIndividually">See here how
to set it</link> in the case of
<literal>DefaultObjectWrapper</literal> (for
<literal>BeansWrapper</literal> it's the same, only with different
class name of course).</para>
<warning>
<para>Do not ever use
<literal>Configuration.getVersion()</literal> to set the
<quote>incompatible improvements</quote> setting. Always use a
fixed value, like <literal>Configuration.VERSION_2_3_28</literal>.
Otherwise your application can break as you upgrade FreeMarker.
The whole point of <quote>incompatible improvements</quote> is to
protect you from that, while you still always get the
fixes/improvements that are backward compatible.</para>
</warning>
</section>
</section>
</chapter>
<chapter xml:id="pgui_misc">
<title>Miscellaneous</title>
<para>This is just an introductory guide. See the <olink
targetdoc="api">FreeMarker Java API documentation</olink> for the
details.</para>
<section xml:id="pgui_misc_var">
<title>Variables, scopes</title>
<indexterm>
<primary>variables</primary>
</indexterm>
<indexterm>
<primary>variable scopes</primary>
</indexterm>
<indexterm>
<primary>scopes</primary>
</indexterm>
<para>This chapter explains what happens when a template tries to
access a variable, and how the variables are stored.</para>
<para>When you call <literal>Template.process</literal> it will
internally create an <literal>Environment</literal> object that will
be in use until <literal>process</literal> returns. This object stores
the runtime state of template processing. Among other things, it
stores the variables created by the template with directives like
<literal>assign</literal>, <literal>macro</literal>,
<literal>local</literal> or <literal>global</literal>. It never tries
to modify the data-model object that you pass to the
<literal>process</literal> call, nor does it create or replace shared
variables stored in the configuration.</para>
<para>When you try to read a variable, FreeMarker will seek the
variable in this order, and stops when it finds a variable with the
right name:</para>
<orderedlist>
<listitem>
<para>In the Environment:</para>
<orderedlist>
<listitem>
<para>If you are in a loop, in the set of loop variables. Loop
variables are the variables created by directives like
<literal>list</literal>.</para>
</listitem>
<listitem>
<para>If you are inside a macro, in the local variable set of
the macro. Local variables can be created with the
<literal>local</literal> directive. Also, the parameters of
macros are local variables.</para>
</listitem>
<listitem>
<para>In the current <link
linkend="dgui_misc_namespace">namespace</link>. You can put
variables into a namespace with the <literal>assign</literal>
directive.</para>
</listitem>
<listitem>
<para>In the set of variables created with
<literal>global</literal> directive. FTL handles these
variables as if they were normal members of the data-model.
That is, they are visible in all namespaces, and you can
access them as if they would be in the data-model.</para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>In the data-model object you have passed to the
<literal>process</literal> method</para>
</listitem>
<listitem>
<para>In the set of shared variables stored in the
<literal>Configuration</literal></para>
</listitem>
</orderedlist>
<para>In practice, from the viewpoint of template authors these 6
layers are only 4 layers, since from that viewpoint the last 3 layers
(variables created with <literal>global</literal>, the actual
data-model object, shared variables) together constitute the set of
global variables.</para>
<para>Note that it is possible to get variables from a specific layer
in FTL with <link linkend="ref_specvar">special
variables</link>.</para>
</section>
<section xml:id="pgui_misc_charset">
<title>Charset issues</title>
<indexterm>
<primary>charset</primary>
</indexterm>
<indexterm>
<primary>encoding</primary>
</indexterm>
<para>FreeMarker, as most Java applications, works with "<link
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>
<section>
<title>The charset of the input</title>
<para>When FreeMarker has to load a template file (or an unparsed
text file), then it must know the charset of the file, since files
are just raw byte sequences. You can use the
<literal>encoding</literal> <link
linkend="pgui_config_settings">setting</link> to specify the
charset. This setting takes effect only when FreeMarker loads a
template (parsed or unparsed) with the
<literal>getTemplate</literal> method of
<literal>Configuration</literal>. Note that the <link
linkend="ref.directive.include"><literal>include</literal>
directive</link> uses this method internally, so the value of the
<literal>encoding</literal> setting is significant for an already
loaded template if the template contains <literal>include</literal>
directive call.</para>
<para>The getter and setter method of the
<literal>encoding</literal> setting is special in the first
(configuration) layer. The getter method guesses the return value
based on a <literal>Locale</literal> passed as parameter; it looks
up the encoding in a table that maps locales to encodings (called
encoding map), and if the locale was not found there, it returns the
default encoding. You can fill the encoding map with the
<literal>setEncoding(Locale locale, String encoding)</literal>
method of the configuration; the encoding map is initially empty.
The default encoding is initially the value of the
<literal>file.encoding</literal> system property, but you always
should set a default default with the
<literal>setDefaultEncoding</literal> method, rather than relying on
that. For new projects, a popular default encoding is
<literal>utf-8</literal>.</para>
<para>You can give the charset directly by overriding the
<literal>encoding</literal> setting in the template layer or runtime
environment layer (When you specify an encoding as the parameter of
<literal>getTemplate</literal> method, you override the
<literal>encoding</literal> setting in the template layer.). If you
don't override it, the effective value will be what the
<literal>configuration.getEncoding(Locale)</literal> method returns
for the effective value of the <literal>locale</literal>
setting.</para>
<para>Also, instead of relying on this charset guessing mechanism,
you can specify the charset of the template in the template file
itself, with the <link linkend="ref.directive.ftl"><link
linkend="ref.directive.ftl"><literal>ftl</literal></link>
directive</link>, like <literal>&lt;#ftl
encoding="utf-8"&gt;</literal>.</para>
<para>Note that the charset of the template is independent from the
charset of the output that the tempalte generates (unless the
enclosing software deliberately sets the output charset to the same
as the template charset).</para>
</section>
<section>
<title>The charset of the output</title>
<note>
<para>The <literal>output_encoding</literal> setting/variable and
the <link linkend="ref_builtin_url"><literal>url</literal>
built-in</link> is available since FreeMarker 2.3.1. It doesn't
exist in 2.3.</para>
</note>
<para><indexterm>
<primary>output encoding</primary>
</indexterm><indexterm>
<primary>output charset</primary>
</indexterm>In principle FreeMarker does not deal with the charset
of the output, since it writes the output to a
<literal>java.io.Writer</literal>. Since the
<literal>Writer</literal> is made by the software that encapsulates
FreeMarker (such as a Web application framework), the output charset
is controlled by the encapsulating software. Still, FreeMarker has a
setting called <literal>output_encoding</literal> (starting from
FreeMarker version 2.3.1). The enclosing software should set this
setting (to the charset that the <literal>Writer</literal> uses), to
inform FreeMarker what charset is used for the output (otherwise
FreeMarker can't find it out). Some features, such as the <link
linkend="ref_builtin_url"><literal>url</literal> built-in</link>,
and the <link
linkend="ref_specvar"><literal>output_encoding</literal> special
variable</link> utilize this information. Thus, if the enclosing
software doesn't set this setting then FreeMarker features that need
to know the output charset can't be used.</para>
<para>If you write software that will use FreeMarker, you may wonder
what output charset should you choose. Of course it depends on the
consumer of the FreeMarker output, but if the consumer is flexible
regarding this question, then the common practice is either using
the charset of the template file for the output, or using UTF-8.
Using UTF-8 is usually a better practice, because arbitrary text may
comes from the data-model, which then possibly contains characters
that couldn't be encoded with the charset of the template.</para>
<para>FreeMarker settings can be set for each individual template
processing if you use
<literal>Template.createProcessingEnvironment(<replaceable>...</replaceable>)</literal>
plus
<literal>Environment.process(<replaceable>...</replaceable>)</literal>
instead of
<literal>Template.process(<replaceable>...</replaceable>)</literal>.
Thus, you can set the <literal>output_encoding</literal> setting for
each template execution independently:</para>
<programlisting role="unspecified">Writer w = new OutputStreamWriter(out, outputCharset);
Environment env = template.createProcessingEnvironment(dataModel, w);
env.setOutputEncoding(outputCharset);
env.process();</programlisting>
</section>
</section>
<section xml:id="pgui_misc_multithreading">
<title>Multithreading</title>
<indexterm>
<primary>multithreading</primary>
</indexterm>
<indexterm>
<primary>thread-safety</primary>
</indexterm>
<para>In a multithreaded environment <literal>Configuration</literal>
instances, <literal>Template</literal> instances and data-models
should be handled as immutable (read-only) objects. That is, you
create and initialize them (for example with
<literal>set<replaceable>...</replaceable></literal> methods), and
then you don't modify them later (e.g. you don't call
<literal>set<replaceable>...</replaceable></literal>). This allows us
to avoid expensive synchronized blocks in a multithreaded environment.
Beware with <literal>Template</literal> instances; when you get a
<literal>Template</literal> instance with
<literal>Configuration.getTemplate</literal>, you may get an instance
from the template cache that is already used by other threads, so do
not call its <literal>set<replaceable>...</replaceable></literal>
methods (calling <literal>process</literal> is of course fine).</para>
<para>The above restrictions do not apply if you access all objects
from the <emphasis>same</emphasis> single thread only.</para>
<para>It is impossible to modify the data-model object or a <link
linkend="pgui_config_sharedvariables">shared variable</link> with FTL,
unless you put methods (or other objects) into the data-model that do
that. We discourage you from writing methods that modify the
data-model object or the shared variables. Try to use variables that
are stored in the environment object instead (this object is created
for a single <literal>Template.process</literal> call to store the
runtime state of processing), so you don't modify data that are
possibly used by multiple threads. For more information read: <xref
linkend="pgui_misc_var"/></para>
</section>
<section xml:id="pgui_misc_beanwrapper">
<title>Bean wrapper</title>
<indexterm>
<primary>wrapping</primary>
<secondary>reflection</secondary>
</indexterm>
<indexterm>
<primary>wrapping</primary>
<secondary>beans</secondary>
</indexterm>
<indexterm>
<primary>beans</primary>
<secondary>wrapping</secondary>
</indexterm>
<indexterm>
<primary>BeansWrapper</primary>
</indexterm>
<note>
<para>Using <literal>BeansWrapper</literal> directly is not
recommended anymore. Use its subclass,
<literal>DefaultObjectWrapper</literal> instead, though by ensuring
that its <literal>incompatibleImprovements</literal> property is at
least 2.3.22. <literal>DefaultObjectWrapper</literal> gives cleaner
data-model (less confusing multi-type FTL values) and is usually
faster. <link linkend="pgui_datamodel_defaultObjectWrapper">See more
about DefaultObjectWrapper here...</link></para>
</note>
<para>The <literal>freemarker.ext.beans.BeansWrapper</literal> is an
<link linkend="pgui_datamodel_objectWrapper">object wrapper</link>
that was originally added to FreeMarker so arbitrary POJO-s (Plain Old
Java Objects) can be wrapped into <literal>TemplateModel</literal>
interfaces. Since then it has became the normal way of doing things,
and in fact the <literal>DefaultObjectWrapper</literal> itself is a
<literal>BeansWrapper</literal> extension. So everything described
here goes for the <literal>DefaultObjectWrapper</literal> too, except
that the <literal>DefaultObjectWrapper</literal> will wrap
<literal>String</literal>, <literal>Number</literal>,
<literal>Date</literal>, <literal>array</literal>,
<literal>Collection</literal> (like <literal>List</literal>),
<literal>Map</literal>, <literal>Boolean</literal> and
<literal>Iterator</literal> objects with the
<literal>freemarker.template.Simple<replaceable>Xxx</replaceable></literal>
classes, and W3C DOM nodes with
<literal>freemarker.ext.dom.NodeModel</literal> (<link
linkend="xgui">more about wrapped W3C DOM...</link>), so for those the
above described rules doesn't apply.</para>
<para>You will want to use <literal>BeansWrapper</literal> instead of
<literal>DefaultObjectWrapper</literal> when any of these
stands:</para>
<itemizedlist>
<listitem>
<para>The <literal>Collection</literal>-s and
<literal>Map</literal>-s of the model should be allowed to be
modified during template execution.
(<literal>DefaultObjectWrapper</literal> prevents that, since it
creates a copy of the collections when they are wrapped, and the
copies will be read-only.)</para>
</listitem>
<listitem>
<para>If the identity of the <literal>array</literal>,
<literal>Collection</literal> and <literal>Map</literal> objects
must be kept when they are passed to a wrapped object's method in
the template. That is, if those methods must get exactly the same
object that was earlier wrapped.</para>
</listitem>
<listitem>
<para>If the Java API of the earlier listed classes
(<literal>String</literal>, <literal>Map</literal>,
<literal>List</literal> ...etc) should be visible for the
templates. Even with <literal>BeansWrapper</literal>, they are not
visible by default, but it can be achieved by setting the exposure
level (see later). Note that this is usually a bad practice; try
to use <link linkend="ref_builtins">the built-ins</link> (like
<literal>foo?size</literal>, <literal>foo?upper_case</literal>,
<literal>foo?replace('_', '-')</literal> ...etc) instead of the
Java API.</para>
</listitem>
</itemizedlist>
<para>Below is a summary of the <literal>TemplateModel</literal>-s
that the <literal>BeansWrapper</literal> creates. Let's assume that
the object is called <literal>obj</literal> before wrapping, and
<literal>model</literal> after wrapping for the sake of the following
discussion.</para>
<section xml:id="beanswrapper_hash">
<title>TemplateHashModel functionality</title>
<para>Every object will be wrapped into a
<literal>TemplateHashModel</literal> that will expose JavaBeans
properties and methods of the object. This way, you can use
<literal>model.foo</literal> in the template to invoke
<literal>obj.getFoo()</literal> or <literal>obj.isFoo()</literal>
methods. (Note that public fields are not visible directly; you must
write a getter method for them.) Public methods are also retrievable
through the hash model as template method models, therefore you can
use the <literal>model.doBar()</literal> to invoke
<literal>object.doBar()</literal>. More on this on discussion of
method model functionality.</para>
<para>If the requested key can not be mapped to a bean property or
method, the framework will attempt to locate the so-called "generic
get method", that is a method with signature public
<literal><replaceable>any-return-type</replaceable>
get(String)</literal> or public
<literal><replaceable>any-return-type</replaceable>
get(Object)</literal> and invoke that method with the requested key.
Note that this allows convenient access to mappings in a
<literal>java.util.Map</literal> and similar classes - as long as
the keys of the map are <literal>String</literal>s and some property
or method name does not shadow the mapping. (There is a solution to
avoid shadowing, read on.) Also note that the models for
<literal>java.util.ResourceBundle</literal> objects use the
<literal>getObject(String)</literal> as the generic get
method.</para>
<para>If you call <literal>setExposeFields(true)</literal> on a
<literal>BeansWrapper</literal> instance, it will also expose
public, non-static fields of classes as hash keys and values. I.e.
if <literal>foo</literal> is a public, non-static field of the class
<literal>Bar</literal>, and <literal>bar</literal> is a template
variable wrapping an instance of <literal>Bar</literal>, then
<literal>bar.foo</literal> expression will evaluate as the value of
the field <literal>foo</literal> of the <literal>bar</literal>
object. The public fields in all superclasses of the class are also
exposed.</para>
</section>
<section>
<title>A word on security</title>
<para>By default, you will not be able to access several methods
that are considered not safe for templating. For instance, you can't
use synchronization methods (<literal>wait</literal>,
<literal>notify</literal>, <literal>notifyAll</literal>), thread and
thread group management methods (<literal>stop</literal>,
<literal>suspend</literal>, <literal>resume</literal>,
<literal>setDaemon</literal>, <literal>setPriority</literal>),
reflection (<literal>Field</literal>
<literal>set<replaceable>Xxx</replaceable></literal> methods,
<literal>Method.invoke</literal>,
<literal>Constructor.newInstance</literal>,
<literal>Class.newInstance</literal>,
<literal>Class.getClassLoader</literal> etc.) and various dangerous
methods in <literal>System</literal> and <literal>Runtime</literal>
classes (<literal>exec</literal>, <literal>exit</literal>,
<literal>halt</literal>, <literal>load</literal>, etc.). The
<literal>BeansWrapper</literal> has several security levels (called
"levels of method exposure"), and the default called
<literal>EXPOSE_SAFE</literal> is probably suited for most
applications. There is a no-safeguard level called
<literal>EXPOSE_ALL</literal> that allows you to call even the above
unsafe methods, and a strict level
<literal>EXPOSE_PROPERTIES_ONLY</literal> that will expose only bean
property getters. Finally, there is a level named
<literal>EXPOSE_NOTHING</literal> that will expose no properties and
no methods. The only data you will be able to access through hash
model interface in this case are items in maps and resource bundles,
as well as objects returned from a call to generic
<literal>get(Object)</literal> or <literal>get(String)</literal>
methods - provided the affected objects have such method.</para>
</section>
<section>
<title>TemplateScalarModel functionality</title>
<para>Models for <literal>java.lang.String</literal> objects will
implement <literal>TemplateScalarModel</literal> whose
<literal>getAsString()</literal> method simply delegates to
<literal>toString()</literal>. Note that wrapping
<literal>String</literal> objects into Bean wrappers provides much
more functionality than just them being scalars: because of the hash
interface described above, the models that wrap
<literal>String</literal>s also provide access to all
<literal>String</literal> methods (<literal>indexOf</literal>,
<literal>substring</literal>, etc.), though most of them has native
FreeMarker equivalent which are better to use
(<literal>s?index_of(n)</literal>,
<literal>s[start..&lt;end]</literal>, etc).</para>
</section>
<section>
<title>TemplateNumberModel functionality</title>
<para>Model wrappers for objects that are instances of
<literal>java.lang.Number</literal> implement
<literal>TemplateNumberModel</literal> whose
<literal>getAsNumber()</literal> method returns the wrapped number
object. Note that wrapping <literal>Number</literal> objects into
Bean wrappers provides much more functionality than just them being
number models: because of the hash interface described above, the
models that wrap <literal>Number</literal>s also provide access to
all their methods.</para>
</section>
<section>
<title>TemplateCollectionModel functionality</title>
<para>Model wrappers for native Java arrays and all classes that
implement <literal>java.util.Collection</literal> will implement
<literal>TemplateCollectionModel</literal> and thus gain the
additional capability of being usable through
<literal>list</literal> directive.</para>
</section>
<section>
<title>TemplateSequenceModel functionality</title>
<para>Model wrappers for native Java arrays and all classes that
implement <literal>java.util.List</literal> will implement
<literal>TemplateSequenceModel</literal> and thus their elements
will be accessible by index using the <literal>model[i]</literal>
syntax. You can also query the length of the array or the size of
the list using the <literal>model?size</literal> built-in.</para>
<para>Also, every method that takes a single parameter that is
assignable through reflective method invocation from a
<literal>java.lang.Integer</literal> (these are
<literal>int</literal>, <literal>long</literal>,
<literal>float</literal>, <literal>double</literal>,
<literal>java.lang.Object</literal>,
<literal>java.lang.Number</literal>, and
<literal>java.lang.Integer</literal>) also implements this
interface. What this means is that you have a convenient way for
accessing the so-called indexed bean properties:
<literal>model.foo[i]</literal> will translate into
<literal>obj.getFoo(i)</literal>.</para>
</section>
<section xml:id="beanswrapper_method">
<title>TemplateMethodModel functionality</title>
<para>All methods of an object are represented as
<literal>TemplateMethodModelEx</literal> objects accessible using a
hash key with method name on their object's model. When you call a
method using
<literal>model.<replaceable>method</replaceable>(<replaceable>arg1</replaceable>,
<replaceable>arg2</replaceable>,
<replaceable>...</replaceable>)</literal> the arguments are passed
to the method as template models. The method will first try to
unwrap them - see below for details about unwrapping. These
unwrapped arguments are then used for the actual method call. In
case the method is overloaded, the most specific method will be
selected using the same rules that are used by the Java compiler to
select a method from several overloaded methods. In case that no
method signature matches the passed parameters, or that no method
can be chosen without ambiguity, a
<literal>TemplateModelException</literal> is thrown.</para>
<para>Methods of return type <literal>void</literal> return
<literal>TemplateModel.NOTHING</literal>, so they can be safely
called with the <literal>${obj.method(args)}</literal>
syntax.</para>
<para>Models for instances of <literal>java.util.Map</literal> also
implement <literal>TemplateMethodModelEx</literal> as a means for
invoking their <literal>get()</literal> method. As it was discussed
previously, you can use the hash functionality to access the "get"
method as well, but it has several drawbacks: it's slower because
first property and method names are checked for the key; keys that
conflict with property and method names will be shadowed by them;
finally you can use <literal>String</literal> keys only with that
approach. In contrast, invoking <literal>model(key)</literal>
translates to <literal>model.get(key)</literal> directly: it's
faster because there's no property and method name lookup; it is
subject to no shadowing; and finally it works for non-String keys
since the argument is unwrapped just as with ordinary method calls.
In effect, <literal>model(key)</literal> on a <literal>Map</literal>
is equal to <literal>model.get(key)</literal>, only shorter to
write.</para>
<para>Models for <literal>java.util.ResourceBundle</literal> also
implement <literal>TemplateMethodModelEx</literal> as a convenient
way of resource access and message formatting. A single-argument
call to a bundle will retrieve the resource with the name that
corresponds to the <literal>toString()</literal> value of the
unwrapped argument. A multiple-argument call to a bundle will also
retrieve the resource with the name that corresponds to the
<literal>toString()</literal> value of the unwrapped argument, but
it will use it as a format pattern and pass it to
<literal>java.text.MessageFormat</literal> using the unwrapped
values of second and later arguments as formatting parameters.
<literal>MessageFormat</literal> objects will be initialized with
the locale of the bundle that originated them.</para>
</section>
<section>
<title>Unwrapping rules</title>
<para>When invoking a Java method from a template, its arguments
need to be converted from template models back to Java objects.
Assuming that the target type (the declared type of the method's
formal parameter) is denoted as <literal>T</literal>, the following
rules are tried in the following order:</para>
<itemizedlist>
<listitem>
<para>If the model is the null model for this wrapper, Java
<literal>null</literal> is returned.</para>
</listitem>
<listitem>
<para>If the model implements
<literal>AdapterTemplateModel</literal>, the result of
<literal>model.getAdaptedObject(T)</literal> is returned if it
is instance of <literal>T</literal> or it is a number and can be
converted to <literal>T</literal> using numeric coercion as
described three bullets lower. <phrase role="forProgrammers">All
models created by the BeansWrapper are themselves
AdapterTemplateModel implementations, so unwrapping a model that
was created by BeansWrapper for an underlying Java object always
yields the original Java object.</phrase></para>
</listitem>
<listitem>
<para>If the model implements the deprecated
<literal>WrapperTemplateModel</literal>, the result of
<literal>model.getWrappedObject()</literal> is returned if it is
instance of <literal>T</literal> or it is a number and can be
converted to <literal>T</literal> using numeric coercion as
described two bullets lower.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is
<literal>java.lang.String</literal>, then if model implements
<literal>TemplateScalarModel</literal> its string value is
returned. <phrase role="forProgrammers">Note that if the model
doesn't implement TemplateScalarModel we don't attempt to
automatically convert the model to string using
String.valueOf(model). You'll have to use the ?string built-in
explicitly to pass non-scalars as strings.</phrase></para>
</listitem>
<listitem>
<para>If <literal>T</literal> is a primitive numeric type or
<literal>java.lang.Number</literal> is assignable from
<literal>T</literal>, and model implements
<literal>TemplateNumberModel</literal>, then its numeric value
is returned if it is instance of <literal>T</literal> or its
boxing type (if <literal>T</literal> is primitive type).
Otherwise, if <literal>T</literal> is a built-in Java numeric
type (primitive type or a standard subclass of
<literal>java.lang.Number</literal>, including
<literal>BigInteger</literal> and <literal>BigDecimal</literal>)
a new object of class <literal>T</literal> or its boxing type is
created with the number model's appropriately coerced
value.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is <literal>boolean</literal> or
<literal>java.lang.Boolean</literal>, and model implements
<literal>TemplateBooleanModel</literal>, then its boolean value
is returned.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is
<literal>java.util.Map</literal> and the model implements
<literal>TemplateHashModel</literal>, then a special Map
representation of the hash model is returned.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is
<literal>java.util.List</literal> and the model implements
<literal>TemplateSequenceModel</literal>, then a special List
representation of the sequence model is returned.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is
<literal>java.util.Set</literal> and the model implements
<literal>TemplateCollectionModel</literal>, then a special Set
representation of the collection model is returned.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is
<literal>java.util.Collection</literal> or
<literal>java.lang.Iterable</literal> and the model implements
either <literal>TemplateCollectionModel</literal> or
<literal>TemplateSequenceModel</literal>, then a special Set or
List representation of the collection or sequence model
(respectively) is returned.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is a Java array type and the model
implements <literal>TemplateSequenceModel</literal>, then a new
array of the specified type is created and its elements
unwrapped into the array recursively using the array's component
type as <literal>T</literal>.</para>
</listitem>
<listitem>
<para>If <literal>T</literal> is <literal>char</literal> or
<literal>java.lang.Character</literal>, and model implements
<literal>TemplateScalarModel</literal>, and its string
representation contains exactly one character, then a
<literal>java.lang.Character</literal> with that value is
retured.</para>
</listitem>
<listitem>
<para>If <literal>java.util.Date</literal> is assignable from
<literal>T</literal>, and model implements
<literal>TemplateDateModel</literal>, and its date value is
instance of <literal>T</literal>, then its date value is
returned.</para>
</listitem>
<listitem>
<para>If model is a number model, and its numeric value is
instance of <literal>T</literal>, the numeric value is returned.
<phrase role="forProgrammers">You can have a custom subclass of
java.lang.Number that implements a custom interface, and T might
be that interface. (*)</phrase></para>
</listitem>
<listitem>
<para>If model is a date model, and its date value is instance
of <literal>T</literal>, the date value is returned. <phrase
role="forProgrammers">Similar consideration as for
(*)</phrase></para>
</listitem>
<listitem>
<para>If model is a scalar model, and <literal>T</literal> is
assignable from <literal>java.lang.String</literal>, the string
value is returned. <phrase role="forProgrammers">This covers
cases when T is java.lang.Object, java.lang.Comparable, and
java.io.Serializable (**)</phrase></para>
</listitem>
<listitem>
<para>If model is a boolean model, and <literal>T</literal> is
assignable from <literal>java.lang.Boolean</literal>, the
boolean value is returned. <phrase role="forProgrammers">Same as
(**)</phrase></para>
</listitem>
<listitem>
<para>If model is a hash model, and <literal>T</literal> is
assignable from
<literal>freemarker.ext.beans.HashAdapter</literal>, a hash
adapter is returned. <phrase role="forProgrammers">Same as
(**)</phrase></para>
</listitem>
<listitem>
<para>If model is a sequence model, and <literal>T</literal> is
assignable from
<literal>freemarker.ext.beans.SequenceAdapter</literal>, a
sequence adapter is returned. <phrase role="forProgrammers">Same
as (**)</phrase></para>
</listitem>
<listitem>
<para>If model is a collection model, and <literal>T</literal>
is assignable from
<literal>freemarker.ext.beans.SetAdapter</literal>, a set
adapter for the collection is returned. <phrase
role="forProgrammers">Same as (**)</phrase></para>
</listitem>
<listitem>
<para>If the model is instance of <literal>T</literal>, the
model itself is returned. <phrase role="forProgrammers">This
covers the case where the method explicitly declared a
FreeMarker-specific model interface, as well as allows returning
directive, method and transform models when java.lang.Object is
requested.</phrase></para>
</listitem>
<listitem>
<para>An exception signifying no conversion is possible is
thrown.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Accessing static methods</title>
<indexterm>
<primary>static method</primary>
<secondary>accessing from templates</secondary>
</indexterm>
<para>The <literal>TemplateHashModel</literal> returned from
<literal>BeansWrapper.getStaticModels()</literal> can be used to
create hash models for accessing static methods and fields of an
arbitrary class.</para>
<programlisting role="unspecified">BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel staticModels = wrapper.getStaticModels();
TemplateHashModel fileStatics =
(TemplateHashModel) staticModels.get("java.io.File");</programlisting>
<para>And you will get a template hash model that exposes all static
methods and static fields (both final and non-final) of the
<literal>java.lang.System</literal> class as hash keys. Suppose that
you put the previous model in your root model:</para>
<programlisting role="unspecified">root.put("File", fileStatics);</programlisting>
<para>From now on, you can use <literal>${File.SEPARATOR}</literal>
to insert the file separator character into your template, or you
can even list all roots of your file system by:</para>
<programlisting role="template">&lt;#list File.listRoots() as fileSystemRoot&gt;...&lt;/#list&gt;</programlisting>
<para>Of course, you must be aware of the potential security issues
this model brings.</para>
<para>You can even give the template authors complete freedom over
which classes' static methods they use by placing the static models
hash into your template root model with</para>
<programlisting role="unspecified">root.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());</programlisting>
<para>This object exposes just about any class' static methods if
it's used as a hash with class name as the key. You can then use
expression like
<literal>${statics["java.lang.System"].currentTimeMillis()}</literal>
in your template. Note, however that this has even more security
implications, as someone could even invoke
<literal>System.exit()</literal> using this model if the method
exposure level is weakened to <literal>EXPOSE_ALL</literal>.</para>
<para>Note that in above examples, we always use the default
<literal>BeansWrapper</literal> instance. This is a convenient
static wrapper instance that you can use in most cases. You are also
free to create your own <literal>BeansWrapper</literal> instances
and use them instead especially when you want to modify some of its
characteristics (like model caching, security level, or the null
model representation).</para>
</section>
<section xml:id="jdk_15_enums">
<title>Accessing enums</title>
<indexterm>
<primary>enum</primary>
</indexterm>
<para>The <literal>TemplateHashModel</literal> returned from
<literal>BeansWrapper.getEnumModels()</literal> can be used to
create hash models for accessing values of enums. (An attempt to
invoke this method on an earlier JRE will result in an
<literal>UnsupportedOperationException</literal>.)</para>
<programlisting role="unspecified">BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel enumModels = wrapper.getEnumModels();
TemplateHashModel roundingModeEnums =
(TemplateHashModel) enumModels.get("java.math.RoundingMode");</programlisting>
<para>And you will get a template hash model that exposes all enum
values of the <literal>java.math.RoundingMode</literal> class as
hash keys. Suppose that you put the previous model in your root
model:</para>
<programlisting role="unspecified">root.put("RoundingMode", roundingModeEnums);</programlisting>
<para>From now on, you can use <literal>RoundingMode.UP</literal> as
an expression to reference the <literal>UP</literal> enum value in
your template.</para>
<para>You can even give the template authors complete freedom over
which enum classes they use by placing the enum models hash into
your template root model with</para>
<programlisting role="unspecified">root.put("enums", BeansWrapper.getDefaultInstance().getEnumModels());</programlisting>
<para>This object exposes any enum class if it's used as a hash with
class name as the key. You can then use expression like
<literal>${enums["java.math.RoundingMode"].UP}</literal> in your
template.</para>
<para>The exposed enum values can be used as scalars (they'll
delegate to their <literal>toString()</literal> method), and can be
used in equality and inequality comparisons as well.</para>
<para>Note that in above examples, we always use the default
<literal>BeansWrapper</literal> instance. This is a convenient
static wrapper instance that you can use in most cases. You are also
free to create your own <literal>BeansWrapper</literal> instances
and use them instead especially when you want to modify some of its
characteristics (like model caching, security level, or the null
model representation).</para>
</section>
</section>
<section xml:id="pgui_misc_logging">
<title>Logging</title>
<indexterm>
<primary>logging</primary>
</indexterm>
<indexterm>
<primary>SLF4J</primary>
</indexterm>
<indexterm>
<primary>Log4j2</primary>
</indexterm>
<section>
<title>Logging library selection</title>
<para>Is short, the recommended setup in contemporary application
(as of 2015) is using SLF4J API for logging everywhere. To get
FreeMarker 2.3.x. to use SLF4J, simply add the
<literal>org.slf4j:log4j-over-slf4j</literal> dependency to your
project, and ensure that <literal>log4j:log4j</literal> isn't
present. (Starting from FreeMarker 2.4.x you don't need
<literal>log4j-over-slf4j</literal> anymore, though it does no harm
either.)</para>
<para>Read on if you are curious about the details, or if you can't
use SLF4J...</para>
<para>FreeMarker integrates with the following logging libraries:
<link xlink:href="http://www.slf4j.org/">SLF4J</link>, <link
xlink:href="http://commons.apache.org/logging/">Apache Commons
Logging</link>, <link
xlink:href="http://jakarta.apache.org/log4j">Log4J</link> 1.x, <link
xlink:href="http://jakarta.apache.org/avalon/logkit">Avalon
LogKit</link>, and <link
xlink:href="http://java.sun.com/j2se/1.4/docs/api/java/util/logging/package-summary.html"><literal>java.util.logging</literal></link>.
By default, FreeMarker will look for the these logging libraries in
the following order, and will automatically use the first one it
finds (in 2.3.x): <remark>[2.4 - un-remark this] SLF4J, Apache
Commons Logging, </remark>Log4J (will use SLF4J instead if it's a
properly installed <literal>log4j-over-slf4j</literal>, since
2.3.22), Apache Avalon LogKit, <literal>java.util.logging</literal>.
As you can see, Log4j has the highest priority. The presence of
Log4j is simply detected from the presence of the
<literal>org.apache.log4j.Logger</literal> class, which means that
Log4j redirections like <literal>log4j-over-slf4j</literal> or
<literal>log4j-1.2-api</literal> will also get the highest
priority.</para>
<para>Prior to FreeMarker 2.4, SLF4J and Apache Commons Logging
aren't searched automatically due to backward compatibility
constraints. But if you have
<literal>org.slf4j:log4j-over-slf4j</literal> properly installed
(means, you have no real Log4j in your class path, and SLF4J has a
backing implementation like <literal>logback-classic</literal>),
then FreeMarker will use the SLF4J API directly instead of the Log4j
API (since FreeMarker 2.3.22).</para>
<para>Note that a similar trick can be applied for logging into
Log4j2: If <literal>org.apache.logging.log4j:log4j-1.2-api</literal>
is present, FreeMarker 2.3.x will pick that as it looks like Log4j,
but all the messages will actually go to Log4j2.</para>
<para>If the auto detection doesn't give you the result that you
want, you can set the
<literal>org.freemarker.loggerLibrary</literal> system property to
select a logger library explicitly (since 2.3.22), like:</para>
<programlisting role="unspecified">java <replaceable>...</replaceable> -Dorg.freemarker.loggerLibrary=SLF4J</programlisting>
<para>The supported system property values are:
<literal>SLF4J</literal>, <literal>CommonsLogging</literal>,
<literal>JUL</literal> (for <literal>java.util.logging</literal>),
<literal>Avalon</literal>, <literal>auto</literal> (the default
behavior), <literal>none</literal> (disables logging).</para>
<para>Note that for reliable operation, the system property should
be set when the JVM starts (like above), not later from Java
code.</para>
<para>Using SLF4J is recommended, as it works best with FreeMarker,
and also because it will be the highest priority auto detected
logger starting from FreeMarker 2.4.</para>
</section>
<section>
<title>Logging categories</title>
<para>All log messages produced by FreeMarker are logged with a
logger category that starts with <literal>freemarker.</literal>. The
currently used logger categories are:</para>
<informaltable border="1">
<thead>
<tr>
<th>Log category name</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>freemarker.beans</literal></td>
<td>Logs messages of the Beans wrapper module.</td>
</tr>
<tr>
<td><literal>freemarker.cache</literal></td>
<td>Logs messages related to template loading and
caching.</td>
</tr>
<tr>
<td><literal>freemarker.runtime</literal></td>
<td>Logs messages related to template execution that doesn't
fit any of the more specific categories. Most importantly, it
logs template exceptions thrown during template processing
(however that should be disabled in modern application; see
later).</td>
</tr>
<tr>
<td><literal>freemarker.runtime.attempt</literal></td>
<td>Logs template exceptions thrown during template processing
and caught by
<literal>attempt</literal>/<literal>recover</literal>
directives, with DEBUG severity. Note that such exceptions
will be still also logged with their normal logger (like
<literal>freemarker.runtime</literal>).</td>
</tr>
<tr>
<td><literal>freemarker.servlet</literal></td>
<td>Logs messages of the <literal>FreemarkerServlet</literal>
class.</td>
</tr>
<tr>
<td><literal>freemarker.jsp</literal></td>
<td>Logs messages of the FreeMarker JSP support.</td>
</tr>
<tr>
<td><literal>freemarker.configuration</literal></td>
<td>Logs messages related to configuring FreeMarker, and not
fitting any other categories.</td>
</tr>
</tbody>
</informaltable>
<para>One quirk relating this is that FreeMarker will log exceptions
during template execution under the
<literal>freemarker.runtime</literal> category even if the exception
continues propagating and so eventually will be thrown by
<literal>Template.process</literal> or
<literal>Environment.process</literal> anyway. (Those are the API
calls with which the template was invoked from the application or
the application framework.) Well behaving applications log the
exceptions thrown at them, or rarely, handle them and deliberately
don't want to log them. But as FreeMarker has already logged that
exception, you will end up one more log entry than expected. To fix
that (since 2.3.22), set the
<literal>log_template_exceptions</literal>
(<literal>Configurable.setLogTemplateExceptions(boolean)</literal>)
setting to <literal>false</literal>.</para>
</section>
</section>
<section xml:id="pgui_misc_servlet">
<title>Using FreeMarker with servlets</title>
<anchor xml:id="topic.servlet"/>
<indexterm>
<primary>Servlet</primary>
</indexterm>
<indexterm>
<primary>HTTP</primary>
</indexterm>
<indexterm>
<primary>JSP</primary>
</indexterm>
<indexterm>
<primary>Model 2</primary>
</indexterm>
<indexterm>
<primary>Struts</primary>
</indexterm>
<indexterm>
<primary>Web application framework</primary>
</indexterm>
<para>In a fundamental sense, using FreeMarker in the web application
space is no different from anywhere else; FreeMarker writes its output
to a <literal>Writer</literal> that you pass to the
<literal>Template.process</literal> method, and it does not care if
that <literal>Writer</literal> prints to the console or to a file or
to the output stream of <literal>HttpServletResponse</literal>.
FreeMarker knows nothing about servlets and Web; it just merges Java
object with template files and generates text output from them. From
here, it is up to you how to build a Web application around
this.</para>
<para>But, probably you want to use FreeMarker with some already
existing Web application framework. Many frameworks rely on the
<quote>Model 2</quote> architecture, where JSP pages handle
presentation. If you use such a framework (for example, <link
xlink:href="http://jakarta.apache.org/struts">Apache Struts</link>),
then read on. For other frameworks please refer to the documentation
of the framework.</para>
<section xml:id="pgui_misc_servlet_model2">
<title>Using FreeMarker for <quote>Model 2</quote></title>
<para>Many frameworks follow the strategy that the HTTP request is
dispatched to user-defined <quote>action</quote> classes that put
data into <literal>ServletContext</literal>,
<literal>HttpSession</literal> and
<literal>HttpServletRequest</literal> objects as attributes, and
then the request is forwarded by the framework to a JSP page (the
view) that will generate the HTML page using the data sent with the
attributes. This is often referred as Model 2.</para>
<mediaobject>
<imageobject>
<imagedata fileref="figures/model2sketch.png"/>
</imageobject>
</mediaobject>
<para>With these frameworks you can simply use FTL files instead of
JSP files. But, since your servlet container (Web application
server), unlike with JSP files, does not know out-of-the-box what to
do with FTL files, a little extra configuring is needed for your Web
application:</para>
<orderedlist>
<listitem>
<para>Copy <literal>freemarker.jar</literal> (from the
<literal>lib</literal> directory of the FreeMarker distribution)
into the <literal>WEB-INF/lib</literal> directory of your Web
application.</para>
</listitem>
<listitem>
<para>Insert the following section to the
<literal>WEB-INF/web.xml</literal> file of your Web application
(and adjust it if required):</para>
</listitem>
</orderedlist>
<programlisting role="unspecified">&lt;servlet&gt;
&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
&lt;servlet-class&gt;<emphasis>freemarker.ext.servlet.FreemarkerServlet</emphasis>&lt;/servlet-class&gt;
&lt;!--
Init-param documentation:
<link xlink:href="https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html</link>
--&gt;
&lt;!-- FreemarkerServlet settings: --&gt;
&lt;init-param&gt;
&lt;param-name&gt;TemplatePath&lt;/param-name&gt;
&lt;param-value&gt;/&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;NoCache&lt;/param-name&gt;
&lt;param-value&gt;true&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;ResponseCharacterEncoding&lt;/param-name&gt;
&lt;!-- Use the output_encoding setting of FreeMarker: --&gt;
&lt;param-value&gt;fromTemplate&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;ExceptionOnMissingTemplate&lt;/param-name&gt;
&lt;!-- true =&gt; HTTP 500 on missing template, instead of HTTP 404. --&gt;
&lt;param-value&gt;true&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;!-- FreeMarker engine settings: --&gt;
&lt;init-param&gt;
&lt;param-name&gt;incompatible_improvements&lt;/param-name&gt;
&lt;param-value&gt;2.3.27&lt;/param-value&gt;
&lt;!--
Recommended to set to a high value.
See: https://freemarker.apache.org/docs/pgui_config_incompatible_improvements.html
--&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;template_exception_handler&lt;/param-name&gt;
&lt;!-- Use "html_debug" during development! --&gt;
&lt;param-value&gt;rethrow&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;template_update_delay&lt;/param-name&gt;
&lt;!-- Use 0 during development! Consider what value you need otherwise. --&gt;
&lt;param-value&gt;30 s&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;default_encoding&lt;/param-name&gt;
&lt;!-- The encoding of the template files: --&gt;
&lt;param-value&gt;UTF-8&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;output_encoding&lt;/param-name&gt;
&lt;!-- The encoding of the template output; Note that you must set
"ResponseCharacterEncodring" to "fromTemplate" for this to work! --&gt;
&lt;param-value&gt;UTF-8&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;locale&lt;/param-name&gt;
&lt;!-- Influences number and date/time formatting, etc. --&gt;
&lt;param-value&gt;en_US&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;number_format&lt;/param-name&gt;
&lt;param-value&gt;0.##########&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
&lt;url-pattern&gt;<emphasis>*.ftl</emphasis>&lt;/url-pattern&gt;
&lt;!-- HTML and XML auto-escaped if incompatible_improvements &gt;= 2.3.24: --&gt;
&lt;url-pattern&gt;<emphasis>*.ftlh</emphasis>&lt;/url-pattern&gt;
&lt;url-pattern&gt;<emphasis>*.ftl</emphasis>x&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
<replaceable>...</replaceable>
&lt;!--
Prevent the visiting of MVC Views from outside the servlet container.
RequestDispatcher.forward/include should, and will still work.
Removing this may open security holes!
--&gt;
&lt;security-constraint&gt;
&lt;web-resource-collection&gt;
&lt;web-resource-name&gt;FreeMarker MVC Views&lt;/web-resource-name&gt;
&lt;url-pattern&gt;*.ftl&lt;/url-pattern&gt;
&lt;url-pattern&gt;*.ftlh&lt;/url-pattern&gt;
&lt;url-pattern&gt;*.ftlx&lt;/url-pattern&gt;
&lt;/web-resource-collection&gt;
&lt;auth-constraint&gt;
&lt;!-- Nobody is allowed to visit these directly. --&gt;
&lt;/auth-constraint&gt;
&lt;/security-constraint&gt;</programlisting>
<para>After this, you can use FTL files (<literal>*.ftl</literal>)
in the same manner as JSP (<literal>*.jsp</literal>) files. (Of
course you can choose another extension besides
<literal>ftl</literal>; it is just the convention)</para>
<note>
<para>How does it work? Let's examine how JSP-s work. Many servlet
container handles JSP-s with a servlet that is mapped to the
<literal>*.jsp</literal> request URL pattern. That servlet will
receive all requests where the request URL ends with
<literal>.jsp</literal>, find the JSP file based on the request
URL, and internally compiles it to a <literal>Servlet</literal>,
and then call the generated servlet to generate the page. The
<literal>FreemarkerServlet</literal> mapped here to the
<literal>*.ftl</literal> URL pattern does the same, except that
FTL files are not compiled to <literal>Servlet</literal>-s, but to
<literal>Template</literal> objects, and then the
<literal>process</literal> method of <literal>Template</literal>
will be called to generate the page.</para>
</note>
<para><anchor xml:id="topic.servlet.scopeAttr"/>For example, instead
of this JSP file (note that it heavily uses Struts tag-libs to save
designers from embedded Java monsters):</para>
<programlisting role="template">&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %&gt;
&lt;html&gt;
&lt;head&gt;&lt;title&gt;Acmee Products International&lt;/title&gt;
&lt;body&gt;
&lt;h1&gt;Hello &lt;bean:write name="user"/&gt;!&lt;/h1&gt;
&lt;p&gt;These are our latest offers:
&lt;ul&gt;
&lt;logic:iterate name="latestProducts" id="prod"&gt;
&lt;li&gt;&lt;bean:write name="prod" property="name"/&gt;
for &lt;bean:write name="prod" property="price"/&gt; Credits.
&lt;/logic:iterate&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>you can use this FTL file (use <literal>ftl</literal> file
extension instead of <literal>jsp</literal>):</para>
<programlisting role="template">&lt;html&gt;
&lt;head&gt;&lt;title&gt;Acmee Products International&lt;/title&gt;
&lt;body&gt;
&lt;h1&gt;Hello ${user}!&lt;/h1&gt;
&lt;p&gt;These are our latest offers:
&lt;ul&gt;
&lt;#list latestProducts as prod&gt;
&lt;li&gt;${prod.name} for ${prod.price} Credits.
&lt;/#list&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<warning>
<para>In FreeMarker <literal>&lt;html:form
action="/query"&gt;<replaceable>...</replaceable>&lt;/html:form&gt;</literal>
is just static text, so it is printed to the output as is, like
any other XML or HTML markup. JSP tags are just FreeMarker
directives, nothing special, so you <emphasis>use FreeMarker
syntax</emphasis> for calling them, not JSP syntax:
<literal>&lt;@html.form
action="/query"&gt;<replaceable>...</replaceable>&lt;/@html.form&gt;</literal>.
Note that in the FreeMarker syntax you <emphasis>don't use
<literal>${<replaceable>...</replaceable>}</literal> in
parameters</emphasis> as in JSP, and you <emphasis>don't quote the
parameter values</emphasis>. So this is
<emphasis>WRONG</emphasis>:</para>
<programlisting role="template">&lt;#-- WRONG: --&gt;
&lt;@my.jspTag color="${aVariable}" name="aStringLiteral"
width="100" height=${a+b} /&gt;</programlisting>
<para>and this is good:</para>
<programlisting role="template">&lt;#-- Good: --&gt;
&lt;@my.jspTag color=aVariable name="aStringLiteral"
width=100 height=a+b /&gt;</programlisting>
</warning>
<para>In both templates, when you refer to <literal>user</literal>
and <literal>latestProduct</literal>, it will first try to find a
variable with that name that was created in the template (like
<literal>prod</literal>; if you master JSP: a page scope attribute).
If that fails, it will try to look up an attribute with that name in
the <literal>HttpServletRequest</literal>, and if it is not there
then in the <literal>HttpSession</literal>, and if it still doesn't
find it then in the <literal>ServletContext</literal>. In the case
of FTL this works because <literal>FreemarkerServlet</literal>
builds the data-model from the attributes of the mentioned 3
objects. That is, in this case the root hash is not a
<literal>java.util.Map</literal> (as it was in some example codes in
this manual), but
<literal>ServletContext</literal>+<literal>HttpSession</literal>+<literal>HttpServletRequest</literal>;
FreeMarker is pretty flexible about what the data-model is. So if
you want to put variable <literal>"name"</literal> into the
data-model, then you call
<literal>servletRequest.setAttribute("name", "Fred")</literal>; this
is the logic of Model 2, and FreeMarker adapts itself to it.</para>
<para><literal>FreemarkerServlet</literal> also puts 3 hashes into
the data-model, by which you can access the attributes of the 3
objects directly. The hash variables are:
<literal>Request</literal>, <literal>Session</literal>,
<literal>Application</literal> (corresponds to
<literal>ServletContext</literal>). It also exposes another hash
named <literal>RequestParameters</literal> that provides access to
the parameters of the HTTP request.</para>
<para><literal>FreemarkerServlet</literal> has various init-params.
It can be set up to load templates from an arbitrary directory, from
the classpath, or relative to the Web application directory. You can
set the charset used for templates, the default locale used by
templates, what object wrapper do you want to use, etc.</para>
<para><literal>FreemarkerServlet</literal> is easily tailored to
special needs through subclassing. Say, if you need to have
additional variables available in your data-model for all templates,
subclass the servlet and override the
<literal>preTemplateProcess()</literal> method to shove any
additional data you need into the model before the template gets
processed. Or subclass the servlet, and set these globally available
variables as <link linkend="pgui_config_sharedvariables">shared
variables</link> in the <literal>Configuration</literal>.</para>
<para>For more information please read the Java API documentation of
the class.</para>
</section>
<section xml:id="pgui_misc_servlet_include">
<title>Including content from other web application
resources</title>
<indexterm>
<primary>include</primary>
<secondary>servlet</secondary>
</indexterm>
<indexterm>
<primary>include</primary>
<secondary>JSP</secondary>
</indexterm>
<indexterm>
<primary>servlet</primary>
<secondary>include</secondary>
</indexterm>
<indexterm>
<primary>JSP</primary>
<secondary>include</secondary>
</indexterm>
<para>You can use the <literal>&lt;@include_page
path="..."/&gt;</literal> custom directive provided by the
<literal>FreemarkerServlet</literal> (since 2.3.15) to include the
contents of another web application resource into the output; this
is often useful to integrate output of JSP pages (living alongside
the FreeMarker templates in the same web server) into the FreeMarker
template output. Using:</para>
<programlisting role="template">&lt;@include_page path="path/to/some.jsp"/&gt;</programlisting>
<para>is identical to using this tag in JSP:</para>
<programlisting role="template">&lt;jsp:include page="path/to/some.jsp"&gt;</programlisting>
<note>
<para><literal>&lt;@include_page ...&gt;</literal> is not to be
confused with <literal>&lt;#include ...&gt;</literal>, as the last
is for including FreeMarker templates without involving the
Servlet container. An <literal>&lt;#include ...&gt;</literal>-ed
template shares the template processing state with the including
template, such as the data-model and the template-language
variables, while <literal>&lt;@include_page ...&gt;</literal>
starts an independent HTTP request processing.</para>
</note>
<note>
<para>Some Web Application Frameworks provide their own solution
for this, in which case you possibly should use that instead. Also
some Web Application Frameworks don't use
<literal>FreemarkerServlet</literal>, so
<literal>include_page</literal> is not available.</para>
</note>
<para>The path can be relative or absolute. Relative paths are
interpreted relative to the URL of the current HTTP request (one
that triggered the template processing), while absolute paths are
absolute in the current servlet context (current web application).
You can not include pages from outside the current web application.
Note that you can include any page, not just a JSP page; we just
used page with path ending in <literal>.jsp</literal> as an
illustration.</para>
<para>In addition to the <literal>path</literal> parameter, you can
also specify an optional parameter named
<literal>inherit_params</literal> with a boolean value (defaults to
true when not specified) that specifies whether the included page
will see the HTTP request parameters of the current request or
not.</para>
<para>Finally, you can specify an optional parameter named
<literal>params</literal> that specifies new request parameters that
the included page will see. In case inherited parameters are passed
too, the values of specified parameters will get prepended to the
values of inherited parameters of the same name. The value of
<literal>params</literal> must be a hash, with each value in it
being either a string, or a sequence of strings (if you need
multivalued parameters). Here's a full example:</para>
<programlisting role="template">&lt;@include_page path="path/to/some.jsp" inherit_params=true params={"foo": "99", "bar": ["a", "b"]}/&gt;</programlisting>
<para>This will include the page
<literal>path/to/some.jsp</literal>, pass it all request parameters
of the current request, except for "foo" and "bar", which will be
set to "99" and multi-value of "a", "b", respectively. In case the
original request already had values for these parameters, the new
values will be prepended to the existing values. I.e. if "foo" had
values "111" and "123", then it will now have values "99", "111",
"123".</para>
<para><phrase role="forProgrammers">It is in fact possible to pass
non-string values for parameter values within
<literal>params</literal>. Such a value will be converted to a
suitable Java object first (i.e. a Number, a Boolean, a Date, etc.),
and then its Java <literal>toString()</literal> method will be used
to obtain the string value. It is better to not rely on this
mechanism, though, and instead explicitly ensure that parameter
values that aren't strings are converted to strings on the template
level where you have control over formatting using the
<literal>?string</literal> and <literal>?c</literal> built-ins.
</phrase></para>
</section>
<section>
<title>Using JSP custom tags in FTL</title>
<indexterm>
<primary>JSP</primary>
<secondary>taglib</secondary>
</indexterm>
<indexterm>
<primary>custom tags</primary>
</indexterm>
<indexterm>
<primary>taglib</primary>
</indexterm>
<para><literal>FreemarkerServlet</literal> puts the
<literal>JspTaglibs</literal> hash into the data-model, which you
can use to access JSP taglibs. The JSP custom tags will be
accessible as plain user-defined directives, and the custom EL
functions (since FreeMarker 2.3.22) as methods. For example, for
this JSP file:</para>
<programlisting role="template">&lt;%@ page contentType="text/html;charset=ISO-8859-2" language="java"%&gt;
&lt;%@ taglib prefix="e" uri="/WEB-INF/example.tld" %&gt;
&lt;%@ taglib prefix="oe" uri="/WEB-INF/other-example.tld" %&gt;
&lt;%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %&gt;
&lt;%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %&gt;
&lt;%-- Custom JSP tags and functions: --%&gt;
&lt;e:someTag numParam="123" boolParam="true" strParam="Example" anotherParam="${someVar}"&gt;
...
&lt;/e:someTag&gt;
&lt;oe:otherTag /&gt;
${e:someELFunction(1, 2)}
&lt;%-- JSTL: --%&gt;
&lt;c:if test="${foo}"&gt;
Do this
&lt;/c:if&gt;
&lt;c:choose&gt;
&lt;c:when test="${x == 1}"&gt;
Do this
&lt;/c:when&gt;
&lt;c:otherwise&gt;
Do that
&lt;/c:otherwise&gt;
&lt;/c:choose&gt;
&lt;c:forEach var="person" items="${persons}"&gt;
${person.name}
&lt;/c:forEach&gt;
${fn:trim(bar)}</programlisting>
<para>the about equivalent FTL is:</para>
<programlisting role="template">&lt;#assign e=JspTaglibs["/WEB-INF/example.tld"]&gt;
&lt;#assign oe=JspTaglibs["/WEB-INF/other-example.tld"]&gt;
&lt;#-- Custom JSP tags and functions: --#&gt;
&lt;@e.someTag numParam=123 boolParam=true strParam="Example" anotherParam=someVar&gt;
...
&lt;/@e.someTag&gt;
&lt;@oe.otherTag /&gt;
${e.someELFunction(1, 2)}
&lt;#-- JSTL - Instead, use native FTL constructs: --&gt;
&lt;#if foo&gt;
Do this
&lt;/#if&gt;
&lt;#if x == 1&gt;
Do this
&lt;#else&gt;
Do that
&lt;/#if&gt;
&lt;#list persons as person&gt;
${person.name}
&lt;/#list&gt;
${bar?trim}</programlisting>
<note>
<para>Parameter values don't use quotation and
<literal>"${<replaceable>...</replaceable>}"</literal> like in
JSP. See more explanation later.</para>
</note>
<note>
<para><literal>JspTaglibs</literal> is not a core FreeMarker
feature; it only exists when the template is called through the
<literal>FreemarkerServlet</literal>. That's because JSP
tags/functions assume a servlet environment (FreeMarker doesn't),
plus some Servlet concepts have to be emulated in the special
FreeMarker data-model that <literal>FreemarkerServlet</literal>
builds. Many modern frameworks use FreeMarker on a pure way, not
through <literal>FreemarkerServlet</literal>.</para>
</note>
<para>Since JSP custom tags are written to operate in JSP
environment, they assume that variables (often referred as
<quote>beans</quote> in JSP world) are stored in 4 scopes: page
scope, request scope, session scope and application scope. FTL has
no such notation (the 4 scopes), but
<literal>FreemarkerServlet</literal> provides emulated JSP
environment for the custom JSP tags, which maintains correspondence
between the <quote>beans</quote> of JSP scopes and FTL variables.
For the custom JSP tags, the request, session and application scopes
are exactly the same as with real JSP: the attributes of the
<literal>javax.servlet.ServletContext</literal>,
<literal>HttpSession</literal> and <literal>ServletRequest</literal>
objects. From the FTL side you see these 3 scopes together as the
data-model, as it was explained earlier. The page scope corresponds
to the FTL global variables (see the <link
linkend="ref.directive.global"><literal>global</literal>
directive</link>). That is, if you create a variable with the
<literal>global</literal> directive, it will be visible for the
custom tags as page scope variable through the emulated JSP
environment. Also, if a JSP-tag creates a new page scope variable,
the result will be the same as if you create a variable with the
<literal>global</literal> directive. Note that the variables in the
data-model are not visible as page-scope attributes for the JSP
tags, despite that they are globally visible, since the data-model
corresponds to the request, session and application scopes, not the
page-scope.</para>
<para>On JSP pages you quote all attribute values, it does not mater
if the type of the parameter is string or boolean or number. But
since custom tags are accessible in FTL templates as user-defined
FTL directives, you have to use the FTL syntax rules inside the
custom tags, not the JSP rules. So when you specify the value of an
<quote>attribute</quote>, then on the right side of the
<literal>=</literal> there is an <link
linkend="dgui_template_exp">FTL expression</link>. Thus,
<emphasis>you must not quote boolean and numerical parameter
values</emphasis> (e.g. <literal>&lt;@tiles.insert
page="/layout.ftl" flush=true/&gt;</literal>), or they are
interpreted as string values, and this will cause a type mismatch
error when FreeMarker tries to pass the value to the custom tag that
expects non-string value. Also note that, naturally, you can use any
FTL expression as attribute value, such as variables, calculated
values, etc. (e.g. <literal>&lt;@tiles.insert page=layoutName
flush=foo &amp;&amp; bar/&gt;</literal>).</para>
<para>FreeMarker does not rely on the JSP support of the servlet
container in which it is run when it uses JSP taglibs since it
implements its own lightweight JSP runtime environment. There is
only one small detail to pay attention to: to enable the FreeMarker
JSP runtime environment to dispatch events to JSP taglibs that
register event listeners in their TLD files, you should add this to
the <literal>WEB-INF/web.xml</literal> of your Web
application:</para>
<programlisting role="unspecified">&lt;listener&gt;
&lt;listener-class&gt;freemarker.ext.jsp.EventForwarding&lt;/listener-class&gt;
&lt;/listener&gt;</programlisting>
<para>Note that you can use JSP taglibs with FreeMarker even if the
servlet container has no native JSP support, just make sure that the
<literal>javax.servlet.jsp.*</literal> packages for JSP 2.0 (or
later) are available to your Web application.</para>
<para>As of this writing, JSP features up to JSP 2.1 are
implemented, except the "tag files" feature of JSP 2 (i.e., custom
JSP tags <emphasis>implemented</emphasis> in JSP language). The tag
files had to be compiled to Java classes to be usable under
FreeMarker.</para>
<para><literal>JspTaglibs[<replaceable>uri</replaceable>]</literal>
will have to find the TLD for the URI specified, just like JSP's
<literal>@taglib</literal> directive has to. For this, it implements
the TLD discovery mechanism described in the JSP specification. See
more there, but in a nutshell, it searches TLD-s in
<literal>WEB-INF/web.xml</literal> <literal>taglib</literal>
elements, at <literal>WEB-INF/**/*.tld</literal>, and in
<literal>WEB-INF/lib/*.{jar,zip}/META-INF/**/*.tld</literal>.
Additionally, it can discover TLD-s that are visible for the class
loader even if they are outside the WAR structure, when you set that
up with the <literal>MetaInfTldSources</literal> and/or
<literal>ClasspathTlds</literal>
<literal>FreemarkerServlet</literal> init-params (since 2.3.22). See
the Java API documentation of <literal>FreemarkerServlet</literal>
for the description of these. It's also possible to set these from
Java system properties, which can be handy when you want to change
these in the Eclipse run configuration without modifying the
<literal>web.xml</literal>; again, see the
<literal>FreemarkerServlet</literal> API docs.
<literal>FreemarkerServlet</literal> also recognizes the
<literal>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</literal>
servlet context attribute, and adds the entries from it to
<literal>MetaInfTldSources</literal>.</para>
</section>
<section>
<title>Embed FTL into JSP pages</title>
<indexterm>
<primary>JSP</primary>
<secondary>taglib</secondary>
</indexterm>
<para>There is a taglib that allows you to put FTL fragments into
JSP pages. The embedded FTL fragment can access the attributes
(Beans) of the 4 JSP scopes. You can find a working example and the
taglib in the FreeMarker distribution.</para>
</section>
</section>
<section xml:id="pgui_misc_secureenv">
<title>Configuring security policy for FreeMarker</title>
<indexterm>
<primary>security</primary>
</indexterm>
<para>When FreeMarker is used in a Java virtual machine with a
security manager installed, you have to grant it few permissions to
ensure it operates properly. Most notably, you need these entries to
your security policy file for
<literal>freemarker.jar</literal>:</para>
<programlisting role="unspecified">grant codeBase "file:/path/to/freemarker.jar"
{
permission java.util.PropertyPermission "file.encoding", "read";
permission java.util.PropertyPermission "freemarker.*", "read";
}</programlisting>
<para>Additionally, if you are loading templates from a directory, you
need to give FreeMarker permissions to read files from that directory
using the following permission:</para>
<programlisting role="unspecified">grant codeBase "file:/path/to/freemarker.jar"
{
...
permission java.io.FilePermission "/path/to/templates/-", "read";
}</programlisting>
<para>Finally, if you're just using the default template loading
mechanism which loads templates from the current directory, then
specify these permissions additionally: (note that the expression
<literal>${user.dir}</literal> will be evaluated at run time by the
policy interpreter, pretty much as if it were a FreeMarker
template)</para>
<programlisting role="unspecified">
grant codeBase "file:/path/to/freemarker.jar"
{
...
permission java.util.PropertyPermission "user.dir", "read";
permission java.io.FilePermission "${user.dir}/-", "read";
}</programlisting>
<para>Naturally, if you're running under Windows, use double backslash
instead of a single slash for separating directory components in
paths.</para>
</section>
<section xml:id="pgui_misc_xml_legacy">
<title>Legacy XML wrapper implementation</title>
<note>
<para><emphasis>The legacy XML wrapper is deprecated.</emphasis>
FreeMarker 2.3 has introduced support for a new XML processing
model. To support this, a new XML wrapper package was introduced,
<literal>freemarker.ext.dom</literal>. For new usage, we encourage
you to use that. It is documented in the part <xref
linkend="xgui"/>.</para>
</note>
<para>The class <literal>freemarker.ext.xml.NodeListModel</literal>
provides a template model for wrapping XML documents represented as
node trees. Every node list can contain zero or more XML nodes
(documents, elements, texts, processing instructions, comments, entity
references, CDATA sections, etc.). The node list implements the
following template model interfaces with the following
semantics:</para>
<section>
<title>TemplateScalarModel</title>
<para>When used as a scalar, the node list will render the XML
fragment that represents its contained nodes. This makes it handy
for use in XML-to-XML transforming templates.</para>
</section>
<section>
<title>TemplateCollectionModel</title>
<para>When used as a collection with <literal>list</literal>
directive, it will simply enumerate its nodes. Every node will be
returned as a new node list consisting of a single node.</para>
</section>
<section>
<title>TemplateSequenceModel</title>
<para>When used as a sequence, it will return the i-th node as a new
node list consisting of the single requested node. I.e. to return
the 3rd <literal>&lt;chapter&gt;</literal> element of the
<literal>&lt;book&gt;</literal> element, you'd use the following
(note indexes are zero-based):</para>
<programlisting role="template">&lt;#assign thirdChapter = xmldoc.book.chapter[2]&gt;</programlisting>
</section>
<section>
<title>TemplateHashModel</title>
<para>When used as a hash, it is basically used to traverse
children. That is, if you have a node list named
<literal>book</literal> that wraps an element node with several
chapters, then the <literal>book.chapter</literal> will yield a node
list with all chapter elements of that book element. The at sign is
used to refer to attributes: <literal>book.@title</literal> yields a
node list with a single attribute node, that is the title attribute
of the book element.</para>
<para>It is important to realize the consequence that, for example,
if <literal>book</literal> has no <literal>chapter</literal>-s then
<literal>book.chapter</literal> is an empty sequence, so
<literal>xmldoc.book.chapter??</literal> will
<emphasis>not</emphasis> be <literal>false</literal>, it will be
always <literal>true</literal>! Similarly,
<literal>xmldoc.book.somethingTotallyNonsense??</literal> will not
be <literal>false</literal> either. To check if there was no
children found, use <literal>xmldoc.book.chapter?size ==
0</literal>.</para>
<para>The hash defines several "magic keys" as well. All these keys
start with an underscore. The most notable is the
<literal>_text</literal> key which retrieves the text of the node:
<literal>${book.@title._text}</literal> will render the value of the
attribute into the template. Similarly, <literal>_name</literal>
will retrieve the name of the element or attribute.
<literal>*</literal> or <literal>_allChildren</literal> returns all
direct children elements of all elements in the node list, while
<literal>@*</literal> or <literal>_allAttributes</literal> returns
all attributes of the elements in the node list. There are many more
such keys; here's a detailed summary of all the hash keys:</para>
<informaltable border="1">
<thead>
<tr>
<th>Key name</th>
<th>Evaluates to</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>*</literal> or <literal>_children</literal></td>
<td>all direct element children of current nodes
(non-recursive). Applicable to element and document
nodes.</td>
</tr>
<tr>
<td><literal>@*</literal> or
<literal>_attributes</literal></td>
<td>all attributes of current nodes. Applicable to elements
only.</td>
</tr>
<tr>
<td><literal>@<replaceable>attributeName</replaceable></literal></td>
<td>named attributes of current nodes. Applicable to elements,
doctypes and processing instructions. On doctypes it supports
attributes <literal>publicId</literal>,
<literal>systemId</literal> and
<literal>elementName</literal>. On processing instructions, it
supports attributes <literal>target</literal> and
<literal>data</literal>, as well as any other attribute name
specified in data as <literal>name="value"</literal> pair. The
attribute nodes for doctype and processing instruction are
synthetic, and as such have no parent. Note, however that
<literal>@*</literal> does NOT operate on doctypes or
processing instructions.</td>
</tr>
<tr>
<td><literal>_ancestor</literal></td>
<td>all ancestors up to root element (recursive) of current
nodes. Applicable to same node types as
<literal>_parent</literal>.</td>
</tr>
<tr>
<td><literal>_ancestorOrSelf</literal></td>
<td>all ancestors of current nodes plus current nodes.
Applicable to same node types as
<literal>_parent</literal>.</td>
</tr>
<tr>
<td><literal>_cname</literal></td>
<td>the canonical names of current nodes (namespace URI +
local name), one string per node (non-recursive). Applicable
to elements and attributes</td>
</tr>
<tr>
<td><literal>_content</literal></td>
<td>the complete content of current nodes, including children
elements, text, entity references, and processing instructions
(non-recursive). Applicable to elements and documents.</td>
</tr>
<tr>
<td><literal>_descendant</literal></td>
<td>all recursive descendant element children of current
nodes. Applicable to document and element nodes.</td>
</tr>
<tr>
<td><literal>_descendantOrSelf</literal></td>
<td>all recursive descendant element children of current nodes
plus current nodes. Applicable to document and element
nodes.</td>
</tr>
<tr>
<td><literal>_document</literal></td>
<td>all documents the current nodes belong to. Applicable to
all nodes except text.</td>
</tr>
<tr>
<td><literal>_doctype</literal></td>
<td>doctypes of the current nodes. Applicable to document
nodes only.</td>
</tr>
<tr>
<td><literal>_filterType</literal></td>
<td>is a filter-by-type template method model. When called, it
will yield a node list that contains only those current nodes
whose type matches one of types passed as argument. You should
pass arbitrary number of strings to this method containing the
names of types to keep. Valid type names are: "attribute",
"cdata", "comment", "document", "documentType", "element",
"entity", "entityReference", "processingInstruction",
"text".</td>
</tr>
<tr>
<td><literal>_name</literal></td>
<td>the names of current nodes, one string per node
(non-recursive). Applicable to elements and attributes
(returns their local names), entities, processing instructions
(returns its target), doctypes (returns its public ID)</td>
</tr>
<tr>
<td><literal>_nsprefix</literal></td>
<td>the namespace prefixes of current nodes, one string per
node (non-recursive). Applicable to elements and
attributes</td>
</tr>
<tr>
<td><literal>_nsuri</literal></td>
<td>the namespace URIs of current nodes, one string per node
(non-recursive). Applicable to elements and attributes</td>
</tr>
<tr>
<td><literal>_parent</literal></td>
<td>parent elements of current nodes. Applicable to element,
attribute, comment, entity, processing instruction.</td>
</tr>
<tr>
<td><literal>_qname</literal></td>
<td>the qualified names of current nodes in
<literal>[namespacePrefix:]localName</literal> form, one
string per node (non-recursive). Applicable to elements and
attributes</td>
</tr>
<tr>
<td><literal>_registerNamespace(prefix, uri)</literal></td>
<td>register a XML namespace with the specified prefix and URI
for the current node list and all node lists that are derived
from the current node list. After registering, you can use the
<literal>nodelist["prefix:localname"]</literal> or
<literal>nodelist["@prefix:localname"]</literal> syntaxes to
reach elements and attributes whose names are
namespace-scoped. Note that the namespace prefix need not
match the actual prefix used by the XML document itself since
namespaces are compared solely by their URI.</td>
</tr>
<tr>
<td><literal>_text</literal></td>
<td>the text of current nodes, one string per node
(non-recursive). Applicable to elements, attributes, comments,
processing instructions (returns its data) and CDATA sections.
The reserved XML characters ('&lt;' and '&amp;') are not
escaped.</td>
</tr>
<tr>
<td><literal>_type</literal></td>
<td>Returns a node list containing one string per node
describing the type of the node. Possible node type names are:
"attribute", "cdata", "comment", "document", "documentType",
"element", "entity", "entityReference",
"processingInstruction", "text". If the type of the node is
unknown, returns "unknown".</td>
</tr>
<tr>
<td><literal>_unique</literal></td>
<td>a copy of the current nodes that keeps only the first
occurrence of every node, eliminating duplicates. Duplicates
can occur in the node list by applying uptree-traversals
<literal>_parent</literal>, <literal>_ancestor</literal>,
<literal>_ancestorOrSelf</literal>, and
<literal>_document</literal>. I.e.
<literal>foo._children._parent</literal> will return a node
list that has duplicates of nodes in foo - each node will have
the number of occurrences equal to the number of its children.
In these cases, use
<literal>foo._children._parent._unique</literal> to eliminate
duplicates. Applicable to all node types.</td>
</tr>
<tr>
<td>any other key</td>
<td>element children of current nodes with name matching the
key. This allows for convenience child traversal in
<literal>book.chapter.title</literal> style syntax. Note that
<literal>nodeset.childname</literal> is technically equivalent
to <literal>nodeset("childname")</literal>, but is both
shorter to write and evaluates faster. Applicable to document
and element nodes.</td>
</tr>
</tbody>
</informaltable>
</section>
<section>
<title>TemplateMethodModel</title>
<para>When used as a method model, it returns a node list that is
the result of evaluating an XPath expression on the current contents
of the node list. For this feature to work, you must have the
<literal>Jaxen</literal> library in your classpath. For
example:</para>
<programlisting role="template">&lt;#assign firstChapter=xmldoc("//chapter[first()]")&gt;</programlisting>
</section>
<section>
<title>Namespace handling</title>
<para>For purposes of traversal of children elements that have
namespace-scoped names, you can register namespace prefixes with the
node list. You can do it either in Java, calling the</para>
<programlisting role="unspecified">public void registerNamespace(String prefix, String uri);</programlisting>
<para>method, or inside a template using the</para>
<programlisting role="template">${<replaceable>nodelist</replaceable>._registerNamespace(<replaceable>prefix</replaceable>, <replaceable>uri</replaceable>)}</programlisting>
<para>syntax. From there on, you can refer to children elements in
the namespace denoted by the particular URI through the
syntax</para>
<programlisting role="metaTemplate"><literal><replaceable>nodelist</replaceable>["<replaceable>prefix</replaceable>:<replaceable>localName</replaceable>"]</literal></programlisting>
<para>and</para>
<programlisting role="metaTemplate"><literal><replaceable>nodelist</replaceable>["@<replaceable>prefix</replaceable>:<replaceable>localName</replaceable>"]</literal></programlisting>
<para>as well as use these namespace prefixes in XPath expressions.
Namespaces registered with a node list are propagated to all node
lists that are derived from the original node list. Note also that
namespaces are matched by their URI only, so you can safely use a
prefix for a namespace inside your template that differs from the
prefix in the actual XML document - a prefix is just a local alias
for the URI both in the template and in the XML document.</para>
</section>
</section>
<section xml:id="pgui_misc_ant">
<title>Using FreeMarker with Ant</title>
<indexterm>
<primary>ant task</primary>
</indexterm>
<para>There are two <quote>FreeMarker Ant tasks</quote> that we know
about:</para>
<itemizedlist>
<listitem>
<para><literal>FreemarkerXmlTask</literal>: It comes with the
FreeMarker distribution, packed into the
<literal>freemarker.jar</literal>. This is a lightweight,
easy-to-use Ant task for transforming XML documents with
FreeMarker templates. Its approach is that the source files (input
files) are XML files, which are rendered to corresponding output
files, by a single template. That is, for each XML file, the
template will be executed (with the XML document in the
data-model), and the template output will be written into a file
of similar name than the name of the XML file. Thus, the template
file plays a similar role as an XSLT style sheet, but it is FTL,
not XSLT.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>command-line</primary>
</indexterm> FMPP: It's a more heavyweight, less XML centric,
third party Ant task (and standalone command-line tool). Its
primary approach is that the source files (input files) are
template files that generate the corresponding output files
themselves, but it also supports the approach of
<literal>FreemarkerXmlTask</literal> for the source files that are
XML-s. Also, it has extra features over the
<literal>FreemarkerXmlTask</literal>. What's its drawback then? As
it is more complex and more generalized, it's harder to learn and
use it.</para>
</listitem>
</itemizedlist>
<para>This section introduces the
<literal>FreemarkerXmlTask</literal>. For more information about FMPP
visit its homepage: <link
xlink:href="http://fmpp.sourceforge.net/">http://fmpp.sourceforge.net/</link>.</para>
<para>In order to use the <literal>FreemarkerXmlTask</literal>, you
must first define the
<literal>freemarker.ext.ant.FreemarkerXmlTask</literal> inside your
Ant buildfile, then call the task. Suppose you want to transform
several XML documents to HTML using the hypothetical "xml2html.ftl"
template, with XML documents located in the directory "xml" and HTML
documents generated into directory "html". You would write something
like:</para>
<programlisting role="unspecified">&lt;taskdef name="freemarker" classname="freemarker.ext.ant.FreemarkerXmlTask"&gt;
&lt;classpath&gt;
&lt;pathelement location="freemarker.jar" /&gt;
&lt;/classpath&gt;
&lt;/taskdef&gt;
&lt;mkdir dir="html" /&gt;
&lt;freemarker basedir="xml" destdir="html" includes="**/*.xml" template="xml2html.ftl" /&gt;</programlisting>
<para>The task would invoke the template for every XML document. Every
document would be parsed into a DOM tree, then wrapped as a FreeMarker
node variable. When template processing begins, the special variable,
<literal>.node</literal>, is set to the root node of the XML
document.</para>
<para>Note that if you are using the legacy (FreeMarker 2.2.x and
earlier) XML adapter implementation, that still works, and the root of
the XML tree is placed in the data-model as the variable
<literal>document</literal>. That contains an instance of the legacy
<literal>freemarker.ext.xml.NodeListModel</literal> class.</para>
<para>Note that all properties defined by the build file would be made
available as a hash model named "properties". Several other models are
made available; for detailed description of what variables are made
available to templates as well as what other attributes can the task
accept, see the JavaDoc for
<literal>freemarker.ext.ant.FreemarkerXmlTask</literal>.</para>
</section>
<section xml:id="pgui_misc_jythonwrapper">
<title>Jython wrapper</title>
<indexterm>
<primary>wrapping</primary>
<secondary>jython</secondary>
</indexterm>
<indexterm>
<primary>jython</primary>
<secondary>wrapping</secondary>
</indexterm>
<para>The <literal>freemarker.ext.jython</literal> package consists of
models that enable any Jython object to be used as a
<literal>TemplateModel</literal>. In the very basic case, you only
need to call the</para>
<programlisting role="unspecified">public TemplateModel wrap(Object obj);</programlisting>
<para>method of the
<literal>freemarker.ext.jython.JythonWrapper</literal> class. This
method will wrap the passed object into an appropriate
<literal>TemplateModel</literal>. Below is a summary of the properties
of returned model wrappers. Let's assume that the model that resulted
from the <literal>JythonWrapper</literal> call on object
<literal>obj</literal> is named <literal>model</literal> in the
template model root for the sake of the following discussion.</para>
<section>
<title>TemplateHashModel functionality</title>
<para><literal>PyDictionary</literal> and
<literal>PyStringMap</literal> will be wrapped into a hash model.
Key lookups are mapped to the <literal>__finditem__</literal>
method; if an item is not found, a model for <literal>None</literal>
is returned.</para>
</section>
<section>
<title>TemplateScalarModel functionality</title>
<para>Every python object will implement
<literal>TemplateScalarModel</literal> whose
<literal>getAsString()</literal> method simply delegates to
<literal>toString()</literal>.</para>
</section>
<section>
<title>TemplateBooleanModel functionality</title>
<para>Every python object will implement
<literal>TemplateBooleanModel</literal> whose
<literal>getAsBoolean()</literal> method simply delegates to
<literal>__nonzero__()</literal> in accordance with Python semantics
of true/false.</para>
</section>
<section>
<title>TemplateNumberModel functionality</title>
<para>Model wrappers for <literal>PyInteger</literal>,
<literal>PyLong</literal>, and <literal>PyFloat</literal> objects
implement <literal>TemplateNumberModel</literal> whose
<literal>getAsNumber()</literal> method returns
<literal>__tojava__(java.lang.Number.class)</literal>.</para>
</section>
<section>
<title>TemplateSequenceModel functionality</title>
<para>Model wrappers for all classes that extend
<literal>PySequence</literal> will implement
<literal>TemplateSequenceModel</literal> and thus their elements
will be accessible by index using the <literal>model[i]</literal>
syntax, which will delegate to <literal>__finditem__(i)</literal>.
You can also query the length of the array or the size of the list
using the <literal>model?size</literal> built-in, which will
delegate to <literal>__len__()</literal>.</para>
</section>
</section>
</chapter>
</part>
<part xml:id="ref">
<title>Template Language Reference</title>
<chapter xml:id="ref_builtins">
<title>Built-in Reference</title>
<indexterm>
<primary>built-in</primary>
</indexterm>
<section xml:id="ref_builtins_alphaidx">
<title>Alphabetical index</title>
<note>
<para>As of FreeMarker 2.3.23, you can use camel case instead of
snake case for directive names, like <literal>startsWith</literal>
instead of <literal>starts_with</literal>. But know that then within
the same template, FreeMarker will enforce the usage of camel case
for all identifiers that are part of the template language (user
defined names are not affected).</para>
</note>
<indexterm>
<primary>built-in</primary>
</indexterm>
<itemizedlist spacing="compact">
<listitem>
<para><link linkend="ref_builtin_abs">abs</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_absolute_template_name">absolute_template_name</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_ancestors">ancestors</link></para>
</listitem>
<listitem>
<para><link linkend="ref_buitin_api_and_has_api">api</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_boolean">boolean</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numType">byte</link></para>
</listitem>
<listitem>
<para>c <link linkend="ref_builtin_c">for strings</link>, <link
linkend="ref_builtin_c_boolean">for booleans</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_cap_first">cap_first</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_capitalize">capitalize</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_rounding">ceiling</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_children">children</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_chop_linebreak">chop_linebreak</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_chunk">chunk</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_contains">contains</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_counter">counter</link></para>
</listitem>
<listitem>
<para>date <link linkend="ref_builtin_date_datetype">for
dates</link>, <link linkend="ref_builtin_string_date">for
strings</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_date_if_unknown">date_if_unknown</link></para>
</listitem>
<listitem>
<para>datetime <link linkend="ref_builtin_date_datetype">for
dates</link>, <link linkend="ref_builtin_string_date">for
strings</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_date_if_unknown">datetime_if_unknown</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numType">double</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_drop_while">drop_while</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_esc">esc</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_ends_with">ends_with</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_ensure_ends_with">ensure_ends_with</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_ensure_starts_with">ensure_starts_with</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_eval">eval</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_eval_json">eval_json</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_filter">filter</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_first">first</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_rounding">floor</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_groups">groups</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numType">float</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_buitin_api_and_has_api">has_api</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_has_content">has_content</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_has_next">has_next</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_html">html</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_index">index</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_index_of">index_of</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numType">int</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_interpret">interpret</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_item_cycle">item_cycle</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_item_parity">item_parity</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_item_parity_cap">item_parity_cap</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_is_even_item">is_even_item</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_first">is_first</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_is_infinite">is_infinite</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_is_last">is_last</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_is_nan">is_nan</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_is_odd_item">is_odd_item</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_isType">is_<replaceable>type</replaceable></link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_date_iso">iso,
iso_...</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_j_string">j_string</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_join">join</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_js_string">js_string</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_keep_after">keep_after</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_keep_after_last">keep_after_last</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_keep_before">keep_before</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_keep_before_last">keep_before_last</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_keys">keys</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_last">last</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_last_index_of">last_index_of</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_left_pad">left_pad</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_length">length</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numType">long</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_lower_abc">lower_abc</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_lower_case">lower_case</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_map">map</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_markup_string">markup_string</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_matches">matches</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_min_max">max</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_min_max">min</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_namespace">namespace</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_new">new</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_next_sibling">next_sibling</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_no_esc">no_esc</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_node_namespace">node_namespace</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_node_name">node_name</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_node_type">node_type</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_number">number</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numToDate">number_to_date,
number_to_datetime, number_to_time</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_parent">parent</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_previous_sibling">previous_sibling</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_replace">replace</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_remove_beginning">remove_beginning</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_remove_ending">remove_ending</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_reverse">reverse</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_right_pad">right_pad</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_rounding">round</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_root">root</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_rtf">rtf</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_numType">short</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_size">size</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_sort">sort</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_seq_contains">seq_contains</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_seq_index_of">seq_index_of</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_seq_last_index_of">seq_last_index_of</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_sequence">sequence</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_sort_by">sort_by</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_split">split</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_starts_with">starts_with</link></para>
</listitem>
<listitem>
<para>string: <link linkend="ref_builtin_string_for_string">for
strings</link>, <link linkend="ref_builtin_string_for_number">for
numbers</link>, <link linkend="ref_builtin_string_for_boolean">for
booleans</link>, <link linkend="ref_builtin_string_for_date">for
date/time/date-time</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_substring">substring</link>
(deprecated)</para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_switch">switch</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_take_while">take_while</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_then">then</link></para>
</listitem>
<listitem>
<para>time <link linkend="ref_builtin_date_datetype">for
date/time/date-time</link>, <link
linkend="ref_builtin_string_date">for strings</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_date_if_unknown">time_if_unknown</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_trim">trim</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_truncate">truncate,
truncate_<replaceable>...</replaceable></link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_uncap_first">uncap_first</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_upper_abc">upper_abc</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_upper_case">upper_case</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_url">url</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_values">values</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_with_args">with_args</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_with_args_last">with_args_last</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_word_list">word_list</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_xhtml">xhtml</link></para>
</listitem>
<listitem>
<para><link linkend="ref_builtin_xml">xml</link></para>
</listitem>
</itemizedlist>
<para>See the built-ins filtered by left-hand-value type <link
linkend="ref_builtins">here</link>.</para>
<para>If you don't find a built-in here that you have seen in a
working template, probably you will find it here: <xref
linkend="ref_deprecated"/></para>
</section>
<section xml:id="ref_builtins_string">
<title>Built-ins for strings</title>
<indexterm>
<primary>string</primary>
<secondary>built-ins</secondary>
</indexterm>
<para>These built-ins act on a string left-value. However, if the
left-value is number or date/time/date-time or boolean (since 2.3.20),
it will automatically converted to string according the current
number-, date/time/date-time- and boolean-format settings (which are
the same formatters that are applied when inserting such values with
<literal>${<replaceable>...</replaceable>}</literal>).</para>
<section xml:id="ref_builtin_boolean">
<title>boolean</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>boolean built-in</primary>
</indexterm>
<indexterm>
<primary>string to boolean</primary>
</indexterm>
<indexterm>
<primary>converting string to boolean</primary>
</indexterm>
<indexterm>
<primary>parse string as boolean</primary>
</indexterm>
<para>The string converted to boolean value. The string must be
<literal>true</literal> or <literal>false</literal> (case
sensitive!), or must be in the format specified by the
<literal>boolean_format</literal> setting.</para>
<para>If the string is not in the appropriate format, an error will
abort template processing when you try to access this
built-in.</para>
</section>
<section xml:id="ref_builtin_cap_first">
<title>cap_first</title>
<indexterm>
<primary>cap_first built-in</primary>
</indexterm>
<para>The string with the very first word of the string capitalized.
For the precise meaning of <quote>word</quote> see the <link
linkend="ref_builtin_word_list">word_list built-in</link>.
Example:</para>
<programlisting role="template">${" green mouse"?cap_first}
${"GreEN mouse"?cap_first}
${"- green mouse"?cap_first}</programlisting>
<para>The output:</para>
<programlisting role="output"> Green mouse
GreEN mouse
- green mouse</programlisting>
<para>In the case of <literal>"- green mouse"</literal>, the first
word is the <literal>-</literal>.</para>
</section>
<section xml:id="ref_builtin_capitalize">
<title>capitalize</title>
<indexterm>
<primary>capitalize built-in</primary>
</indexterm>
<para>The string with all words capitalized. For the precise meaning
of <quote>word</quote> see the <link
linkend="ref_builtin_word_list">word_list built-in</link>.
Example:</para>
<programlisting role="template">${" green mouse"?capitalize}
${"GreEN mouse"?capitalize}</programlisting>
<para>The output:</para>
<programlisting role="output"> Green Mouse
Green Mouse</programlisting>
</section>
<section xml:id="ref_builtin_chop_linebreak">
<title>chop_linebreak</title>
<indexterm>
<primary>chop_linebreak built-in</primary>
</indexterm>
<para>Returns the string without the <link
linkend="gloss.lineBreak">line-break</link> at its very end if there
was a line-break, otherwise the unchanged string. If the string ends
with multiple line-breaks, only the last line-break is
removed.</para>
</section>
<section xml:id="ref_builtin_contains">
<title>contains</title>
<indexterm>
<primary>contains built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.1. It
doesn't exist in 2.3.</para>
</note>
<para>Returns if the substring specified as the parameter to this
built-in occurrs in the string. For example:</para>
<programlisting role="template">&lt;#if "piceous"?contains("ice")&gt;It contains "ice"&lt;/#if&gt;</programlisting>
<para>This will output:</para>
<programlisting role="output">It contains "ice"</programlisting>
</section>
<section xml:id="ref_builtin_string_date">
<title>date, time, datetime</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>date built-in</primary>
</indexterm>
<indexterm>
<primary>time built-in</primary>
</indexterm>
<indexterm>
<primary>datetime built-in</primary>
</indexterm>
<indexterm>
<primary>string to date</primary>
</indexterm>
<indexterm>
<primary>string to time</primary>
</indexterm>
<indexterm>
<primary>converting string to date</primary>
</indexterm>
<indexterm>
<primary>converting string to time</primary>
</indexterm>
<indexterm>
<primary>parsing string as date</primary>
</indexterm>
<indexterm>
<primary>parsing string as time</primary>
</indexterm>
<indexterm>
<primary>XML Schema date parsing</primary>
</indexterm>
<indexterm>
<primary>XML Schema time parsing</primary>
</indexterm>
<indexterm>
<primary>ISO 8601 parsing</primary>
</indexterm>
<para>The string value converted to a date, time, or date-time
value. It will expect the format specified by the <link
linkend="topic.dateTimeFormatSettings"><literal>date_format</literal>,
<literal>time_format</literal> and
<literal>datetime_format</literal> settings</link>. If the string is
not in the appropriate format, an error will abort template
processing when you try to access this built-in.</para>
<programlisting role="template">&lt;#-- The date_format, time_format and datetime_format settings must match this format! --&gt;
&lt;#assign someDate = "Oct 25, 1995"?date&gt;
&lt;#assign someTime = "3:05:30 PM"?time&gt;
&lt;#assign someDatetime = "Oct 25, 1995 03:05:00 PM"?datetime&gt;
&lt;#-- Changing the setting value changes the expected format: --&gt;
&lt;#setting datetime_format="iso"&gt;
&lt;#assign someDatetime = "1995-10-25T15:05"?datetime&gt;
</programlisting>
<para>You can also specify the format explicitly like
<literal>?datetime.<replaceable>format</replaceable></literal> (and
hence also as
<literal>?datetime["<replaceable>format</replaceable>"]</literal>)
or
<literal>?datetime("<replaceable>format</replaceable>")</literal>;
these three forms do the same. The format can be specified similarly
with <literal>?date</literal> and <literal>?time</literal> too. For
the syntax and meaning of format values see the possible values of
the <link
linkend="topic.dateTimeFormatSettings"><literal>date_format</literal>,
<literal>time_format</literal> and
<literal>datetime_format</literal> settings</link>. Example:</para>
<programlisting role="template">&lt;#-- Parsing XML Schema xs:date, xs:time and xs:dateTime values: --&gt;
&lt;#assign someDate = "1995-10-25"?date.xs&gt;
&lt;#assign someTime = "15:05:30"?time.xs&gt;
&lt;#assign someDatetime = "1995-10-25T15:05:00"?datetime.xs&gt;
&lt;#-- Parsing ISO 8601 (both extended and basic formats): --&gt;
&lt;#assign someDatetime = "1995-10-25T15:05"?datetime.iso&gt;
&lt;#assign someDatetime = "19951025T1505"?datetime.iso&gt;
&lt;#-- Parsing with SimpleDateFormat patterns: --&gt;
&lt;#assign someDate = "10/25/1995"?date("MM/dd/yyyy")&gt;
&lt;#assign someTime = "15:05:30"?time("HH:mm:ss")&gt;
&lt;#assign someDatetime = "1995-10-25 03:05 PM"?datetime("yyyy-MM-dd hh:mm a")&gt;
&lt;#-- Parsing with custom date formats: --&gt;
&lt;#assign someDatetime = "October/25/1995 03:05 PM"?datetime.@worklog&gt;</programlisting>
<para>To prevent misunderstandings, the left-hand value need not be
a string literal. For example, when you read data from XML DOM (from
where all values come as unparsed strings), you may do things like
<literal>order.confirmDate?date.xs</literal> to convert the string
value to a real date.</para>
<para>Of course, the format also can be a variable, like in
<literal>"<replaceable>...</replaceable>"?datetime(myFormat)</literal>.</para>
<para>Note that since 2.3.24, these built-ins can also be called
with 0 arguments, like <literal>?date()</literal>. It's almost the
same as just writing <literal>?date</literal>. The difference is
highly technical and rarely matters: <literal>?date()</literal> and
such returns exactly the same Java object that the date parser
(<literal>freemarker.core.TemplateDateFormat</literal>
implementation) returns, while <literal>?date</literal> without the
<literal>()</literal> returns a tricky wrapper value that's a date
and a method and hash on the same time.</para>
</section>
<section xml:id="ref_builtin_ends_with">
<title>ends_with</title>
<indexterm>
<primary>ends_with built-in</primary>
</indexterm>
<para>Returns whether this string ends with the substring specified
in the parameter. For example
<literal>"ahead"?ends_with("head")</literal> returns boolean
<literal>true</literal>. Also,
<literal>"head"?ends_with("head")</literal> will return
<literal>true</literal>.</para>
</section>
<section xml:id="ref_builtin_ensure_ends_with">
<title>ensure_ends_with</title>
<indexterm>
<primary>ensure_ends_with built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>If the string doesn't end with the substring specified as the
1st parameter, it adds it after the string, otherwise it returns the
original string. For example, both
<literal>"foo"?ensure_ends_with("/")</literal> and
<literal>"foo/"?ensure_ends_with("/")</literal> returns
<literal>"foo/"</literal>.</para>
</section>
<section xml:id="ref_builtin_ensure_starts_with">
<title>ensure_starts_with</title>
<indexterm>
<primary>ensure_ends_with built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>If the string doesn't start with the substring specified as
the 1st parameter, it adds it before the string, otherwise it
returns the original string. For example, both
<literal>"foo"?ensure_starts_with("/")</literal> and
<literal>"/foo"?ensure_starts_with("/")</literal> returns
<literal>"/foo"</literal>.</para>
<para>If you specify two parameters, then the 1st parameter is
interpreted as a Java regular expression, and if it doesn't match
the beginning of the string, then the string specified as the 2nd
parameter is added before the string. For example
<literal>someURL?ensure_starts_with("[a-zA-Z]+://",
"http://")</literal> will check if the string starts with something
that matches <literal>"[a-zA-Z]+://"</literal> (note that no
<literal>^</literal> is needed), and if it doesn't, it prepends
<literal>"http://"</literal>.</para>
<para>This method also accepts a 3rd <link
linkend="ref_builtin_string_flags">flags parameter</link>. As
calling with 2 parameters implies <literal>"r"</literal> there
(i.e., regular expression mode), you rarely need this. One notable
case is when you don't want the 1st parameter to be interpreted as a
regular expression, only as plain text, but you want the comparison
to be case-insensitive, in which case you would use
<literal>"i"</literal> as the 3rd parameter.</para>
</section>
<section xml:id="ref_builtin_esc">
<title>esc</title>
<para><indexterm>
<primary>esc built-in</primary>
</indexterm></para>
<note>
<para>This built-in is available since FreeMarker 2.3.24.</para>
</note>
<para>Escapes the value with the current <link
linkend="dgui_misc_autoescaping_outputformat">output format</link>,
and prevents the <link
linkend="dgui_misc_autoescaping">auto-escaping</link> of the
returned value (to avoid double escaping). Because of auto-escaping,
you usually only need this where auto-escaping was disabled:</para>
<programlisting role="template">&lt;#ftl output_format="HTML" <emphasis>auto_esc=false</emphasis>&gt;
&lt;#assign s = "R&amp;D"&gt;
${s}
${s?esc}</programlisting>
<programlisting role="output">R&amp;D
R&amp;amp;D</programlisting>
<para>In templates, where auto-escaping is on, using it is
redundant:</para>
<programlisting role="template">&lt;#ftl output_format="HTML"&gt;
&lt;#assign s = "R&amp;D"&gt;
${s}
${s?esc} &lt;#-- ?esc is redundant here --&gt;</programlisting>
<programlisting role="output">R&amp;amp;D
R&amp;amp;D</programlisting>
<para>This built-in works by converting the string value to a <link
linkend="dgui_misc_autoescaping_movalues">markup output
value</link>, by escaping the string with the current output format,
and using the result as the markup. The resulting markup output
value belongs to the current output format at the point of the
invocation.</para>
<para>This built-in can also be applied on markup output values,
which it will bypass without change, as far as the input markup
output value belongs to the current output format. If it doesn't,
then the markup has to be converted to the current output format,
which currently (as of 2.3.24) will be only successful if that value
was created by escaping plain text (usually, with
<literal>?esc</literal>).</para>
<para>This built-in can't be used where the current output format is
a <link linkend="dgui_misc_autoescaping_nonmarkupof">non-markup
output format</link>. An attempt to do so will cause a <link
linkend="gloss.parseTimeError">parse-time error</link>.</para>
<para>This built-in is not related to the deprecated <link
linkend="ref_directive_escape"><literal>escape</literal> and
<literal>noescape</literal> directives</link>. In fact, the parser
will prevent using them on the same place, to prevent
confusion.</para>
</section>
<section xml:id="ref_builtin_groups">
<title>groups</title>
<indexterm>
<primary>groups built-in</primary>
</indexterm>
<para>This is used only with the result of the
<literal>matches</literal> built-in. See <link
linkend="ref_builtin_matches">there...</link></para>
</section>
<section xml:id="ref_builtin_html">
<title>html (deprecated)</title>
<indexterm>
<primary>escaping</primary>
<secondary>output</secondary>
</indexterm>
<indexterm>
<primary>html built-in</primary>
</indexterm>
<note>
<para>This built-in is <emphasis>deprecated</emphasis> by the
<link linkend="dgui_misc_autoescaping">auto-escaping
mechanism</link> introduced in 2.3.24. To prevent double escaping
and confusion in general, using this built-in on places where
auto-escaping is active is a <link
linkend="gloss.parseTimeError">parse-time error</link>. To help
migration, this built-in silently bypasses HTML <link
linkend="dgui_misc_autoescaping_movalues">markup output
values</link> without changing them.</para>
</note>
<para>The string as HTML markup. That is, the string with
all:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>&lt;</literal> replaced with
<literal>&amp;lt;</literal></para>
</listitem>
<listitem>
<para><literal>&gt;</literal> replaced with
<literal>&amp;gt;</literal></para>
</listitem>
<listitem>
<para><literal>&amp;</literal> replaced with
<literal>&amp;amp;</literal></para>
</listitem>
<listitem>
<para><literal>"</literal> replaced with
<literal>&amp;quot;</literal></para>
</listitem>
<listitem>
<para><literal>'</literal> is replaced with
<literal>&amp;#39;</literal> <emphasis>if</emphasis> the
programmers has <link
linkend="pgui_config_incompatible_improvements_how_to_set">set
the <literal>incompatible_improvements</literal> setting</link>
to 2.3.24 or higher (also if it's set to 2.3.20 or higher and
you are outside a string literal). Otherwise
<literal>'</literal> won't be replaced, so you must use
quotation mark (<literal>"</literal>, not <literal>'</literal>)
to quote attribute values where you want to insert a value
safely.</para>
</listitem>
</itemizedlist>
<programlisting role="template">&lt;input type=text name=user value=<emphasis>"</emphasis>${user?html}<emphasis>"</emphasis>&gt;</programlisting>
<warning>
<para>When inserting the value of an attribute, always quote it,
or else it can be exploited by attackers! This is WRONG:
<literal>&lt;input name="user" value=${user?xhtml}&gt;</literal>.
This is good: <literal>&lt;input name="user"
value="${user?xhtml}"&gt;</literal>.</para>
</warning>
<para>Note that in HTML pages usually you want to use this built-in
for all interpolations. You can spare a lot of typing and lessen the
chances of accidental mistakes by using the <link
linkend="ref_directive_escape"><literal>escape</literal>
directive</link>.</para>
</section>
<section xml:id="ref_builtin_index_of">
<title>index_of</title>
<indexterm>
<primary>index_of built-in</primary>
</indexterm>
<para>Returns the index within this string of the first occurrence
of the specified substring. For example,
<literal>"abcabc"?index_of("bc")</literal> will return 1 (don't
forget that the index of the first character is 0). Also, you can
specify the index to start the search from:
<literal>"abcabc"?index_of("bc", 2)</literal> will return 4. There
is no restriction on the numerical value of the second parameter: if
it is negative, it has the same effect as if it were zero, and if it
is greater than the length of this string, it has the same effect as
if it were equal to the length of this string. Decimal values will
be truncated to integers.</para>
<para>If the 1st parameter does not occur as a substring in this
string (starting from the given index, if you use the second
parameter), then it returns -1.</para>
</section>
<section xml:id="ref_builtin_j_string">
<title>j_string</title>
<indexterm>
<primary>j_string built-in</primary>
</indexterm>
<para>Escapes the string with the escaping rules of Java language
string literals, so it's safe to insert the value into a string
literal. Note that it will <emphasis>not</emphasis> add quotation
marks around the inserted value; you meant to use this
<emphasis>inside</emphasis> the string literal.</para>
<para>All characters under <link linkend="gloss.UCS">UCS</link> code
point 0x20 will be escaped. When they have no dedicated escape
sequence in the Java language (like <literal>\n</literal>,
<literal>\t</literal>, etc.), they will be replaced with a UNICODE
escape
(<literal>\u<replaceable>XXXX</replaceable></literal>).</para>
<para>Example:</para>
<programlisting role="template">&lt;#assign beanName = 'The "foo" bean.'&gt;
String BEAN_NAME = "${beanName?j_string}";</programlisting>
<para>will output:</para>
<programlisting role="output">String BEAN_NAME = "The \"foo\" bean.";</programlisting>
</section>
<section xml:id="ref_builtin_js_string">
<title>js_string</title>
<indexterm>
<primary>js_string built-in</primary>
</indexterm>
<para>Escapes the string with the escaping rules of JavaScript
language string literals, so it's safe to insert the value into a
string literal. Note that it will <emphasis>not</emphasis> add
quotation marks around the inserted value; you meant to use this
<emphasis>inside</emphasis> the string literal.</para>
<warning>
<para>When inserting into a JavaScript string literal that's
inside a HTML attribute, you also must escape the value with HTML
escaping. Thus, of you don't have <link
linkend="pgui_config_outputformatsautoesc">automatic HTML
escaping</link>, this is WRONG: <literal>&lt;p
onclick="alert('${message?js_string}')"&gt;</literal>, and this is
good: <literal>&lt;p
onclick="alert('${message?js_string?html}')"&gt;</literal>.</para>
</warning>
<para>Example:</para>
<programlisting role="template">&lt;#assign user = "Big Joe's \"right hand\""&gt;
&lt;script&gt;
alert("Welcome ${user?js_string}!");
&lt;/script&gt;</programlisting>
<para>will output:</para>
<programlisting role="output">&lt;script&gt;
alert("Welcome Big Joe\'s \"right hand\"!");
&lt;/script&gt;</programlisting>
<para>The exact escaping rules are:</para>
<itemizedlist>
<listitem>
<para><literal>"</literal> is escaped as
<literal>\"</literal></para>
</listitem>
<listitem>
<para><literal>'</literal> is escaped as
<literal>\'</literal></para>
</listitem>
<listitem>
<para><literal>\</literal> is escaped as
<literal>\\</literal></para>
</listitem>
<listitem>
<para><literal>/</literal> is escaped as <literal>\/</literal>
if the <literal>/</literal> is directly after
<literal>&lt;</literal> in the escaped string, or if it's at the
beginning of the escaped string</para>
</listitem>
<listitem>
<para><literal>&gt;</literal> is escaped as
<literal>\&gt;</literal> if the <literal>&gt;</literal> is
directly after <literal>]]</literal> or <literal>--</literal> in
the escaped string, or if it's at the beginning of the escaped
string, or if there's only a <literal>]</literal> or
<literal>-</literal> before it at the beginning of the escaped
string</para>
</listitem>
<listitem>
<para><literal>&lt;</literal> is escaped as
<literal>\u003C</literal> if it's followed by
<literal>?</literal> or <literal>!</literal> in the escaped
string, or if it's at the end of the escaped string</para>
</listitem>
<listitem>
<para>Control characters in <link linkend="gloss.UCS">UCS</link>
code point ranges U+0000...U+001f and U+007f...U+009f are
escaped as <literal>\r</literal>, <literal>\n</literal>, etc.,
or as <literal>\x<replaceable>XX</replaceable></literal> where
there's no special escape for them in JavaScript.</para>
</listitem>
<listitem>
<para>Control characters with <link
linkend="gloss.UCS">UCS</link> code point U+2028 (Line
separator) and U+2029 (Paragraph separator) are escaped as
<literal>\u<replaceable>XXXX</replaceable></literal>, as they
are source code line-breaks in ECMAScript.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_builtin_json_string">
<title>json_string</title>
<indexterm>
<primary>json_string built-in</primary>
</indexterm>
<para>Escapes the string with the escaping rules of JSON language
string literals, so it's safe to insert the value into a string
literal. Note that it will <emphasis>not</emphasis> add quotation
marks around the inserted value; you meant to use this
<emphasis>inside</emphasis> the string literal.</para>
<para>This will not escape <literal>'</literal> characters, since
JSON strings must be quoted with <literal>"</literal>.</para>
<para>The escaping rules are almost identical to those <link
linkend="ref_builtin_j_string">documented for
<literal>js_string</literal></link>. The differences are that
<literal>'</literal> is not escaped at all, that &gt; is escaped as
\u003E (not as \&gt;), and that
<literal>\u<replaceable>XXXX</replaceable></literal> escapes are
used instead of <literal>\x<replaceable>XX</replaceable></literal>
escapes.</para>
</section>
<section xml:id="ref_builtin_keep_after">
<title>keep_after</title>
<indexterm>
<primary>keep_after built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>Removes the part of the string that is not after the first
occurrence of the given substring. For example:</para>
<programlisting role="template">${"abcdefgh"?keep_after("de")}</programlisting>
<para>will print</para>
<programlisting role="output">fgh</programlisting>
<para>If the parameter string is not found, it will return an empty
string. If the parameter string is a 0-length string, it will return
the original string unchanged.</para>
<para>This method accepts an optional <link
linkend="ref_builtin_string_flags">flags parameter</link>, as its
2nd parameter:</para>
<programlisting role="template">${"foo : bar"?keep_after(r"\s*:\s*", "r")}</programlisting>
<para>will print</para>
<programlisting role="output">bar</programlisting>
</section>
<section xml:id="ref_builtin_keep_after_last">
<title>keep_after_last</title>
<indexterm>
<primary>keep_after_last built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.22.</para>
</note>
<para>Same as <link
linkend="ref_builtin_keep_after"><literal>keep_after</literal></link>,
but keeps the part after the last occurrence of the parameter,
rather than after the first. Example:</para>
<programlisting role="template">${"foo.bar.txt"?keep_after_last(".")}</programlisting>
<para>will print</para>
<programlisting role="output">txt</programlisting>
<para>while with <literal>keep_after</literal> you would get
<literal>bar.txt</literal>.</para>
</section>
<section xml:id="ref_builtin_keep_before">
<title>keep_before</title>
<indexterm>
<primary>keep_before built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>Removes the part of the string that starts with the given
substring. For example:</para>
<programlisting role="template">${"abcdef"?keep_before("de")}</programlisting>
<para>will print</para>
<programlisting role="output">abc</programlisting>
<para>If the parameter string is not found, it will return the
original string unchanged. If the parameter string is a 0-length
string, it will return an empty string.</para>
<para>This method accepts an optional <link
linkend="ref_builtin_string_flags">flags parameter</link>, as its
2nd parameter:</para>
<programlisting role="template">${"foo : bar"?keep_before(r"\s*:\s*", "r")}</programlisting>
<para>will print</para>
<programlisting role="output">foo</programlisting>
</section>
<section xml:id="ref_builtin_keep_before_last">
<title>keep_before_last</title>
<indexterm>
<primary>keep_before_last built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.22.</para>
</note>
<para>Same as <link
linkend="ref_builtin_keep_before"><literal>keep_before</literal></link>,
but keeps the part before the last occurrence of the parameter,
rather than after the first. Example:</para>
<programlisting role="template">${"foo.bar.txt"?keep_before_last(".")}</programlisting>
<para>will print</para>
<programlisting role="output">foo.bar</programlisting>
<para>while with <literal>keep_before</literal> you would get
<literal>foo</literal>.</para>
</section>
<section xml:id="ref_builtin_last_index_of">
<title>last_index_of</title>
<indexterm>
<primary>last_index_of built-in</primary>
</indexterm>
<para>Returns the index within this string of the last (rightmost)
occurrence of the specified substring. It returns the index of the
first (leftmost) character of the substring. For example:
<literal>"abcabc"?last_index_of("ab")</literal> will return 3. Also,
you can specify the index to start the search from. For example,
<literal>"abcabc"?last_index_of("ab", 2)</literal> will return 0.
Note that the second parameter indicates the maximum index of the
start of the substring. There is no restriction on the numerical
value of the second parameter: if it is negative, it has the same
effect as if it were zero, and if it is greater than the length of
this string, it has the same effect as if it were equal to the
length of this string. Decimal values will be truncated to
inegers.</para>
<para>If the 1st parameter does not occur as a substring in this
string (before the given index, if you use the second parameter),
then it returns -1.</para>
</section>
<section xml:id="ref_builtin_left_pad">
<title>left_pad</title>
<indexterm>
<primary>left_pad built-in</primary>
</indexterm>
<indexterm>
<primary>padding</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.1.</para>
</note>
<para>If it's used with 1 parameter, then it inserts spaces on the
beginning of the string until it reaches the length that is
specified as the parameter. If the string is already as long or
longer than the specified length, then it does nothing. For example,
this:</para>
<programlisting role="template">[${""?left_pad(5)}]
[${"a"?left_pad(5)}]
[${"ab"?left_pad(5)}]
[${"abc"?left_pad(5)}]
[${"abcd"?left_pad(5)}]
[${"abcde"?left_pad(5)}]
[${"abcdef"?left_pad(5)}]
[${"abcdefg"?left_pad(5)}]
[${"abcdefgh"?left_pad(5)}]</programlisting>
<para>will output this:</para>
<programlisting role="output">[ ]
[ a]
[ ab]
[ abc]
[ abcd]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]</programlisting>
<para>If it's used with 2 parameters, then the 1st parameter means
the same as if you were using the built-in with only 1 parameter,
and the second parameter specifies what to insert instead of space
characters. For example:</para>
<programlisting role="template">[${""?left_pad(5, "-")}]
[${"a"?left_pad(5, "-")}]
[${"ab"?left_pad(5, "-")}]
[${"abc"?left_pad(5, "-")}]
[${"abcd"?left_pad(5, "-")}]
[${"abcde"?left_pad(5, "-")}]</programlisting>
<para>will output this:</para>
<programlisting role="output">[-----]
[----a]
[---ab]
[--abc]
[-abcd]
[abcde]</programlisting>
<para>The 2nd parameter can be a string whose length is greater than
1. Then the string will be inserted periodically, for
example:</para>
<programlisting role="template">[${""?left_pad(8, ".oO")}]
[${"a"?left_pad(8, ".oO")}]
[${"ab"?left_pad(8, ".oO")}]
[${"abc"?left_pad(8, ".oO")}]
[${"abcd"?left_pad(8, ".oO")}]</programlisting>
<para>will output this:</para>
<programlisting role="output">[.oO.oO.o]
[.oO.oO.a]
[.oO.oOab]
[.oO.oabc]
[.oO.abcd]</programlisting>
<para>The 2nd parameter must be a string value, and it must be at
least 1 character long.</para>
</section>
<section xml:id="ref_builtin_length">
<title>length</title>
<indexterm>
<primary>length built-in</primary>
</indexterm>
<para>The number of characters in the string.</para>
</section>
<section xml:id="ref_builtin_lower_case">
<title>lower_case</title>
<indexterm>
<primary>lower_case built-in</primary>
</indexterm>
<para>The lower case version of the string. For example
<literal>"GrEeN MoUsE"?lower_case</literal> will be <literal>"green
mouse"</literal>.</para>
</section>
<section xml:id="ref_builtin_matches">
<title>matches</title>
<indexterm>
<primary>matches built-in</primary>
</indexterm>
<para>This is a <quote>power user</quote> built-in. Ignore it if you
don't know <link linkend="gloss.regularExpression">regular
expressions</link>.</para>
<para>This built-in determines if the string exactly matches the
pattern. Also, it returns the list of matching sub-strings. The
return value is a multi-type value:</para>
<itemizedlist>
<listitem>
<para>Boolean: <literal>true</literal>, if it the entire string
matches the pattern, otherwise <literal>false</literal>. For
example, <literal>"fooo"?matches('fo*')</literal> is
<literal>true</literal>, but
<literal>"fooo bar"?matches('fo*')</literal> is
<literal>false</literal>.</para>
</listitem>
<listitem>
<para>Sequence: the list of matched substrings of the string.
Possibly a 0 length sequence.</para>
</listitem>
</itemizedlist>
<para>For example:</para>
<programlisting role="template">&lt;#if "fxo"?matches("f.?o")&gt;Matches.&lt;#else&gt;Does not match.&lt;/#if&gt;
&lt;#assign res = "foo bar fyo"?matches("f.?o")&gt;
&lt;#if res&gt;Matches.&lt;#else&gt;Does not match.&lt;/#if&gt;
Matching sub-strings:
&lt;#list res as m&gt;
- ${m}
&lt;/#list&gt;</programlisting>
<para>will print:</para>
<programlisting role="output">Matches.
Does not match.
Matching sub-strings:
- foo
- fyo</programlisting>
<para>If the regular expression contains groups (parentheses), then
you can access them with the <literal>groups</literal>
built-in:</para>
<programlisting role="template">&lt;#-- Entire input match --&gt;
&lt;#assign res = "John Doe"?matches(r"(\w+) (\w+)")&gt;
&lt;#if res&gt; &lt;#-- Must not try to access groups if there was no match! --&gt;
First name: ${res?groups[1]}
Second name: ${res?groups[2]}
&lt;/#if&gt;
&lt;#-- Subtring matches --&gt;
&lt;#assign res = "aa/rx; ab/r;"?matches("(.+?)/*(.+?);")&gt;
&lt;#list res as m&gt;
- "${m}" is "${m?groups[1]}" per "${m?groups[2]}"
&lt;/#list&gt;</programlisting>
<para>This will print:</para>
<programlisting role="output"> First name: John
Second name: Doe
- "aa/rx;" is "a" per "a/rx"
- " ab/r;" is " " per "ab/r"</programlisting>
<para>Notes regarding the behavior of the <literal>groups</literal>
built-in:</para>
<itemizedlist>
<listitem>
<para>It works both with substring matches and with the result
of entire string matching (as it was shown in the above
example)</para>
</listitem>
<listitem>
<para>The first item in the sequence that
<literal>groups</literal> returns is the whole substring matched
by the regular expression. Hence, the index of the first
explicit regular expression group (with other words, of the
first <literal>(<replaceable>...</replaceable>)</literal> in the
regular expression) is 1, and not 0. Also, because of this, the
size of the sequence is one more than the number of explicit
regular expression groups.</para>
</listitem>
<listitem>
<para>The size of the sequence returned by
<literal>groups</literal> only depends on the number of explicit
groups in the regular expression, and so it will be the same
(non-0) even if there was no match found for the regular
expression. Attempting to access an item of the sequence (as in
<literal>res?groups[1]</literal>) when there was match will
cause an error. Thus, before accessing the groups, you should
always check if there was any match (as in <literal>&lt;#if
res&gt;<replaceable>access the groups
here</replaceable>&lt;/#if&gt;</literal>).</para>
</listitem>
<listitem>
<para>When there's a match for the regular expression, but not
for a certain explicit group inside the regular expression, then
for that group the sequence will contain a 0 length string. So
accessing a group that matches nothing is safe, as far as the
containing regular expression has matched something.</para>
</listitem>
</itemizedlist>
<para><literal>matches</literal> accepts an optional 2nd parameter,
the <link linkend="ref_builtin_string_flags">flags</link>. Note that
it doesn't support flag <literal>f</literal>, and ignores the
<literal>r</literal> flag.</para>
</section>
<section xml:id="ref_builtin_no_esc">
<title>no_esc</title>
<para><indexterm>
<primary>no_esc built-in</primary>
</indexterm></para>
<note>
<para>This built-in is available since FreeMarker 2.3.24.</para>
</note>
<para>Prevents the <link
linkend="dgui_misc_autoescaping">auto-escaping</link> of a value.
For example:</para>
<programlisting role="template">&lt;#ftl output_format="HTML"&gt;
&lt;#assign s = "&lt;b&gt;Test&lt;/b&gt;"&gt;
${s}
${s?no_esc}</programlisting>
<programlisting role="output">&amp;lt;b&amp;gt;Test&amp;lt;/b&amp;gt;
&lt;b&gt;Test&lt;/b&gt;</programlisting>
<para>This works by converting the string value to a <link
linkend="dgui_misc_autoescaping_movalues">markup output
value</link>, which uses the string as the markup as is, and belongs
to the current <link
linkend="dgui_misc_autoescaping_outputformat">output format</link>
at the point of the invocation.</para>
<para>This built-in can also be applied on markup output values,
which it will bypass without change, as far as the input markup
output value belongs to current output format. If it doesn't, then
the markup has to be converted to the current output format, which
currently (as of 2.3.24) will be only successful if that value was
created by escaping plain text (usually, with
<literal>?esc</literal>).</para>
<para>This built-in can't be used where the current output format is
a <link linkend="dgui_misc_autoescaping_nonmarkupof">non-markup
output format</link>. An attempt to do so will cause a <link
linkend="gloss.parseTimeError">parse-time error</link>.</para>
<para>This built-in is not related to the deprecated <link
linkend="ref_directive_escape"><literal>escape</literal> and
<literal>noescape</literal> directives</link>. In fact, the parser
will prevent using them on the same place, to prevent
confusion.</para>
</section>
<section xml:id="ref_builtin_number">
<title>number</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>number built-in</primary>
</indexterm>
<indexterm>
<primary>string to number</primary>
</indexterm>
<indexterm>
<primary>converting string to number</primary>
</indexterm>
<indexterm>
<primary>parse string as number</primary>
</indexterm>
<para>The string converted to numerical value. The number must be in
<quote>computer language</quote> format. That is, it must be in the
locale independent form, where the decimal separator is dot, and
there's no grouping.</para>
<para>This built-in recognizes numbers in the format that the
FreeMarker template language uses. In additionally, it recognizes
scientific notation (e.g. <literal>"1.23E6"</literal>,
<literal>"1.5e-8"</literal>). Since FreeMarker 2.3.21, it also
recognizes all XML Schema number formats, like
<literal>NaN</literal>, <literal>INF</literal>,
<literal>-INF</literal>, plus the Java-native formats
<literal>Infinity</literal> and <literal>-Infinity</literal>.</para>
<para>If the string is not in the appropriate format, an error will
abort template processing when you try to access this
built-in.</para>
<para><phrase role="forProgrammers">In fact, the string is parsed by
the <literal>toNumber</literal> method of the current
<literal>arithmetic_engine</literal>, which is configuration
setting. However, that method should behave similarly as described
above.</phrase></para>
</section>
<section xml:id="ref_builtin_replace">
<title>replace</title>
<indexterm>
<primary>replace built-in</primary>
</indexterm>
<para>It is used to replace all occurrences of a string in the
original string with another string. It does not deal with word
boundaries. For example:</para>
<programlisting role="template">${"this is a car acarus"?replace("car", "bulldozer")}</programlisting>
<para>will print:</para>
<programlisting role="output">this is a bulldozer abulldozerus</programlisting>
<para>The replacing occurs in left-to-right order. This means that
this:</para>
<programlisting role="template">${"aaaaa"?replace("aaa", "X")}</programlisting>
<para>will print:</para>
<programlisting role="output">Xaa</programlisting>
<para>If the 1st parameter is an empty string, then all occurrences
of the empty string will be replaced, like
<literal>"foo"?replace("","|")</literal> will evaluate to
<literal>"|f|o|o|"</literal>.</para>
<para><literal>replace</literal> accepts an optional <link
linkend="ref_builtin_string_flags">flags parameter</link>, as its
3rd parameter.</para>
</section>
<section xml:id="ref_builtin_right_pad">
<title>right_pad</title>
<indexterm>
<primary>right_pad built-in</primary>
</indexterm>
<indexterm>
<primary>padding</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.1. It
doesn't exist in 2.3.</para>
</note>
<para>This is the same as <link
linkend="ref_builtin_left_pad"><literal>left_pad</literal></link>,
but it inserts the characters at the end of the string instead of
the beginning of the string.</para>
<para>Example:</para>
<programlisting role="template">[${""?right_pad(5)}]
[${"a"?right_pad(5)}]
[${"ab"?right_pad(5)}]
[${"abc"?right_pad(5)}]
[${"abcd"?right_pad(5)}]
[${"abcde"?right_pad(5)}]
[${"abcdef"?right_pad(5)}]
[${"abcdefg"?right_pad(5)}]
[${"abcdefgh"?right_pad(5)}]
[${""?right_pad(8, ".oO")}]
[${"a"?right_pad(8, ".oO")}]
[${"ab"?right_pad(8, ".oO")}]
[${"abc"?right_pad(8, ".oO")}]
[${"abcd"?right_pad(8, ".oO")}]</programlisting>
<para>This will output this:</para>
<programlisting role="output">[ ]
[a ]
[ab ]
[abc ]
[abcd ]
[abcde]
[abcdef]
[abcdefg]
[abcdefgh]
[.oO.oO.o]
[aoO.oO.o]
[abO.oO.o]
[abc.oO.o]
[abcdoO.o]</programlisting>
</section>
<section xml:id="ref_builtin_remove_beginning">
<title>remove_beginning</title>
<indexterm>
<primary>remove_beginning built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>Removes the parameter substring from the beginning of the
string, or returns the original string if it doesn't start with the
parameter substring. For example:</para>
<programlisting role="template">${"abcdef"?remove_beginning("abc")}
${"foobar"?remove_beginning("abc")}</programlisting>
<para>will print:</para>
<programlisting role="output">def
foobar</programlisting>
</section>
<section xml:id="ref_builtin_remove_ending">
<title>remove_ending</title>
<indexterm>
<primary>remove_ending built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>Removes the parameter substring from the ending of the string,
or returns the original string if it doesn't end with the parameter
substring. For example:</para>
<programlisting role="template">${"abcdef"?remove_ending("def")}
${"foobar"?remove_ending("def")}</programlisting>
<para>will print:</para>
<programlisting role="output">abc
foobar</programlisting>
</section>
<section xml:id="ref_builtin_rtf">
<title>rtf (deprecated)</title>
<note>
<para>This built-in is <emphasis>deprecated</emphasis> by the
<link linkend="dgui_misc_autoescaping">auto-escaping
mechanism</link> introduced in 2.3.24. To prevent double escaping
and confusion in general, using this built-in on places where
auto-escaping is active is a <link
linkend="gloss.parseTimeError">parse-time error</link>. To help
migration, this built-in silently bypasses RTF <link
linkend="dgui_misc_autoescaping_movalues">markup output
values</link> without changing them.</para>
</note>
<indexterm>
<primary>rtf built-in</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
<secondary>output</secondary>
</indexterm>
<para>The string as Rich text (RTF text). That is, the string with
all:</para>
<itemizedlist>
<listitem>
<para><literal>\</literal> replaced with
<literal>\\</literal></para>
</listitem>
<listitem>
<para><literal>{</literal> replaced with
<literal>\{</literal></para>
</listitem>
<listitem>
<para><literal>}</literal> replaced with
<literal>\}</literal></para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_builtin_split">
<title>split</title>
<indexterm>
<primary>split built-in</primary>
</indexterm>
<para>It is used to split a string into a sequence of strings along
the occurrences of another string. For example:</para>
<programlisting role="template">&lt;#list "someMOOtestMOOtext"?split("MOO") as x&gt;
- ${x}
&lt;/#list&gt;</programlisting>
<para>will print:</para>
<programlisting role="output">- some
- test
- text</programlisting>
<para>Note that it is assumed that all occurrences of the separator
is before a new item (except with <literal>"r"</literal> flag - see
later), thus:</para>
<programlisting role="template">&lt;#list "some,,test,text,"?split(",") as x&gt;
- "${x}"
&lt;/#list&gt;</programlisting>
<para>will print:</para>
<programlisting role="output">- "some"
- ""
- "test"
- "text"
- ""</programlisting>
<para><literal>split</literal> accepts an optional <link
linkend="ref_builtin_string_flags">flags parameter</link>, as its
2nd parameter. There's a historical glitch with the
<literal>r</literal> (regular expression) flag; it removes the empty
elements from the end of the resulting list, so with
<literal>?split(",", "r")</literal> in the last example the last
<literal>""</literal> would be missing from the output.</para>
<para>If the 1st parameter is an empty string, the string will be
split to characters (since FreeMarker 2.3.28 - earlier this has only
worked with the <literal>r</literal> flag).</para>
<note>
<para>To check if a strings ends with something and append it
otherwise, use <link linkend="ref_builtin_ensure_ends_with">the
<literal>ensure_ends_with</literal> built-in</link>.</para>
</note>
</section>
<section xml:id="ref_builtin_starts_with">
<title>starts_with</title>
<indexterm>
<primary>starts_with built-in</primary>
</indexterm>
<para>Returns if this string starts with the specified substring.
For example <literal>"redirect"?starts_with("red")</literal> returns
boolean <literal>true</literal>. Also,
<literal>"red"?starts_with("red")</literal> will return
<literal>true</literal>.</para>
<note>
<para>To check if a strings starts with something and prepend it
otherwise, use <link linkend="ref_builtin_ensure_starts_with">the
<literal>ensure_starts_with</literal> built-in</link>.</para>
</note>
</section>
<section xml:id="ref_builtin_string_for_string">
<title>string (when used with a string value)</title>
<para>Does nothing, just returns the string as-is. The exception is
that if the value is a multi-type value (e.g. it is both string and
sequence at the same time), then the resulting value will be only a
simple string, not a multi-type value. This can be utilized to
prevent the artifacts of multi-typing.</para>
</section>
<section xml:id="ref_builtin_substring">
<title>substring (deprecated)</title>
<indexterm>
<primary>substring built-in</primary>
</indexterm>
<indexterm>
<primary>substring</primary>
</indexterm>
<note>
<para>This built-in is deprecated since FreeMarker 2.3.21 by <link
linkend="dgui_template_exp_stringop_slice">slicing
expressions</link>, like
<literal><replaceable>str</replaceable>[<replaceable>from</replaceable>..&lt;<replaceable>toExclusive</replaceable>]</literal>,
<literal><replaceable>str</replaceable>[<replaceable>from</replaceable>..]</literal>,
and
<literal><replaceable>str</replaceable>[<replaceable>from</replaceable>..*<replaceable>maxLength</replaceable>]</literal>.</para>
<para>A warning if you are processing XML: Since slicing
expressions work both for sequences and strings, and since XML
nodes are typically both sequences and strings at the same time,
there the equivalent expression is
<literal><replaceable>someXmlNode</replaceable>?string[<replaceable>from</replaceable>..&lt;<replaceable>toExclusive</replaceable>]</literal>
and
<literal><replaceable>exp</replaceable>?string[<replaceable>from</replaceable>..]</literal>,
as without <literal>?string</literal> it would slice the node
sequence instead of the text value of the node.</para>
</note>
<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>
<para>Synopsis:
<literal><replaceable>exp</replaceable>?substring(<replaceable>from</replaceable>,
<replaceable>toExclusive</replaceable>)</literal>, also callable as
<literal><replaceable>exp</replaceable>?substring(<replaceable>from</replaceable>)</literal></para>
<para>A substring of the string.
<literal><replaceable>from</replaceable></literal> is the index of
the first character. It must be a number that is at least 0 and less
than or equal with
<literal><replaceable>toExclusive</replaceable></literal>, or else
an error will abort the template processing. The
<literal><replaceable>toExclusive</replaceable></literal> is the
index of the character position after the last character of the
substring, or with other words, it is one greater than the index of
the last character. It must be a number that is at least 0 and less
than or equal to the length of the string, or else an error will
abort the template processing. If the
<literal><replaceable>toExclusive</replaceable></literal> is
omitted, then it defaults to the length of the string. If a
parameter is a number that is not an integer, only the integer part
of the number will be used.</para>
<para>Example:</para>
<programlisting role="template">- ${'abc'?substring(0)}
- ${'abc'?substring(1)}
- ${'abc'?substring(2)}
- ${'abc'?substring(3)}
- ${'abc'?substring(0, 0)}
- ${'abc'?substring(0, 1)}
- ${'abc'?substring(0, 2)}
- ${'abc'?substring(0, 3)}
- ${'abc'?substring(0, 1)}
- ${'abc'?substring(1, 2)}
- ${'abc'?substring(2, 3)}</programlisting>
<para>The output:</para>
<programlisting role="output">- abc
- bc
- c
-
-
- a
- ab
- abc
- a
- b
- c</programlisting>
</section>
<section xml:id="ref_builtin_trim">
<title>trim</title>
<indexterm>
<primary>trim built-in</primary>
</indexterm>
<para>The string without leading and trailing white-space.
Example:</para>
<programlisting role="template">(${" green mouse "?trim})</programlisting>
<para>The output:</para>
<programlisting role="output">(green mouse)</programlisting>
</section>
<section xml:id="ref_builtin_truncate">
<title>truncate, truncate_...</title>
<indexterm>
<primary>truncate built-in</primary>
</indexterm>
<indexterm>
<primary>truncate_c built-in</primary>
</indexterm>
<indexterm>
<primary>truncate_w built-in</primary>
</indexterm>
<indexterm>
<primary>truncate_m built-in</primary>
</indexterm>
<indexterm>
<primary>truncate_c_m built-in</primary>
</indexterm>
<indexterm>
<primary>truncate_w_m built-in</primary>
</indexterm>
<para>Cuts off the end of a string if that's necessary to keep it
under a the length given as parameter, and appends a terminator
string (<literal>[...]</literal> by default) to indicate that the
string was truncated. Example (assuming default FreeMarker
configuration settings):</para>
<programlisting role="template">&lt;#assign shortName='This is short'&gt;
&lt;#assign longName='This is a too long name'&gt;
&lt;#assign difficultName='This isoneveryverylongword'&gt;
No truncation needed:
${shortName?truncate(16)}
Truncated at word boundary:
${longName?truncate(16)}
Truncated at "character boundary":
${difficultName?truncate(16)}</programlisting>
<programlisting role="output">No truncation needed:
This is short
Truncated at word boundary:
This is a [...]
Truncated at "character boundary":
This isonev[...]</programlisting>
<para>Things to note above:</para>
<itemizedlist>
<listitem>
<para>The string is returned as is if its length doesn't exceed
the specified length (16 in this case).</para>
</listitem>
<listitem>
<para>When the string exceeded that length, its end was cut off
in a way so that together with the added terminator string
(<literal>[...]</literal> here) its length won't exceed 16. The
result length is possibly shorter than 16, for the sake of
better look (see later). Actually, the result length can also be
longer than the parameter length, when the desired length is
shorter than the terminator string alone, in which case the
terminator is still returned as is. Also, an algorithms other
than the default might choses to return a longer string, as the
length parameter is in principle just hint for the desired
visual length.</para>
</listitem>
<listitem>
<para><literal>truncate</literal> prefers cutting at word
boundary, rather than mid-word, however, if doing so would give
a result that's shorter than the 75% of the length specified
with the argument, it falls back to cut mid-word. In the last
line of the above example, <quote>This [...]</quote> would be
too short (11 &lt; 16 * 75%), so it was cut mid-word
instead.</para>
</listitem>
<listitem>
<para>If the cut happened at word boundary, there's a space
between the word end and the terminator string, otherwise
there's no space between them. Only whitespace is treated as
word separator, not punctuation, so this generally gives
intuitive results.</para>
</listitem>
</itemizedlist>
<simplesect>
<title>Adjusting truncation rules</title>
<para>Truncation rules are highly configurable by setting the
<literal>truncate_builtin_algorithm</literal> configuration
setting. This can be done by the programmers, not template
authors, so for more details and examples please see the JavaDoc
of <link
xlink:href="api/freemarker/core/Configurable.html#setTruncateBuiltinAlgorithm-freemarker.core.TruncateBuiltinAlgorithm-">Configurable.setTruncateBuiltinAlgorithm</link>.</para>
<para>Truncation rules can also be influenced right in the
template to a smaller extent:</para>
<itemizedlist>
<listitem>
<para>Specifying if the truncation should happen at word
boundary or not:</para>
<itemizedlist>
<listitem>
<para><literal>truncate_w</literal> will always truncate
at word boundary. For example,
<literal>difficultName?truncate_w(16)</literal> returns
<quote>This [...]</quote>, rather than <quote>This
isonev[...]</quote> (as saw in earlier example).</para>
</listitem>
<listitem>
<para><literal>truncate_c</literal> will truncate at any
character, not just at word ends. For example,
<literal>longName?truncate_c(16)</literal> returns
<quote>This is a t[...]</quote>, rather than <quote>This
is a [...]</quote> (as saw in earlier example). This tends
to give a string length closer to the length specified,
but still not an exact length, as it removes white-space
before the terminator string, and re-adds a space if we
are just after the end of a word, etc.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Specifying the terminator string (instead of relying on
its default): <literal>truncate</literal> and all
<literal>truncate_<replaceable>...</replaceable></literal>
built-ins have an additional optional parameter for it. After
that, a further optional parameter can specify the assumed
length of the terminator string (otherwise its real length
will be used). If you find yourself specifying the terminator
string often, then certainly the defaults should be configured
instead (via <literal>truncate_builtin_algorithm
configuration</literal> - see earlier). Example:</para>
<programlisting role="template">${longName?truncate(16, '...')}
${longName?truncate(16, '...', 1)}</programlisting>
<programlisting role="output">This is a ...
This is a too ...</programlisting>
<para>When the terminator string starts with dot
(<literal>.</literal>) or ellipsis (<literal>…</literal>), the
default algorithm will remove the dots and ellipses that the
terminator touches, to prevent ending up with more than 3 dots
at the end:</para>
<programlisting role="template">${'Foo bar.baaz'?truncate(11, '---')}
${'Foo bar.baaz'?truncate(11, '...')} (Not "Foo bar....")
${'Fo bar. baaz'?truncate(11, '...')} (Word separator space prevents touching)</programlisting>
<programlisting role="output">Foo bar.---
Foo bar... (Not "Foo bar....")
Fo bar. ... (Word separator space prevents touching)</programlisting>
</listitem>
</itemizedlist>
</simplesect>
<simplesect>
<title>Using markup as terminator string</title>
<para>Each truncation built-in has a variation whose name ends
with <literal>_m</literal> (for markup). These allow using markup
(like HTML) as terminator, which is useful if you want the
terminator to be styled differently than the truncated text. By
default the markup terminator is <literal>&lt;span
class='truncateTerminator'&gt;[&amp;#8230;]&lt;/span&gt;</literal>,
(where <literal>&amp;#8230;</literal> prints an ellipsis
character), but of course this can be changed with the
<literal>truncate_builtin_algorithm</literal> configuration
setting (see earlier). Example (see the variables used in earlier
example):</para>
<programlisting role="template">${longName?truncate_m(16)}
${difficultName?truncate_w_m(16)}
${longName?truncate_c_m(16)}</programlisting>
<programlisting role="output">This is a &lt;span class='truncateTerminator'&gt;[&amp;#8230;]&lt;/span&gt;
This &lt;span class='truncateTerminator'&gt;[&amp;#8230;]&lt;/span&gt;
This is a to&lt;span class='truncateTerminator'&gt;[&amp;#8230;]&lt;/span&gt;</programlisting>
<para>Note above that the terminator string was considered to be
only 3 characters long (<literal>'['</literal>,
<literal>'…'</literal>, <literal>']'</literal>) by the truncation
built-ins, because inside the terminator string they only count
the characters outside HTML/XML tags and comments, and they can
also interpret numeric character references (but not other entity
references). (The same applies when they decide if the terminator
starts with dot or ellipsis; preceding tags/comments are skipped,
etc.)</para>
<para>If a markup terminator is used (like above), the return
value of the
<literal>truncate<replaceable>...</replaceable>_m</literal>
built-in will be markup as well, which means that <link
linkend="dgui_misc_autoescaping">auto-escaping</link> won't escape
it. Of course, the content of the truncated string itself will be
still auto-escaped:</para>
<programlisting role="template">&lt;#ftl output_format='HTML'&gt;
${'This is auto-escaped: &lt;span&gt;'}
${'This is auto-escaped: &lt;span&gt;, but not the terminator string'?truncate_m(41)}</programlisting>
<programlisting role="output">This is auto-escaped: &amp;lt;span&amp;gt;
This is auto-escaped: &amp;lt;span&amp;gt;, but not &lt;span class='truncateTerminator'&gt;[&amp;#8230;]&lt;/span&gt;</programlisting>
</simplesect>
</section>
<section xml:id="ref_builtin_uncap_first">
<title>uncap_first</title>
<indexterm>
<primary>uncap_first built-in</primary>
</indexterm>
<para>The opposite of <link
linkend="ref_builtin_cap_first"><literal>cap_first</literal></link>.
The string with the very first word of the string
un-capitalized.</para>
</section>
<section xml:id="ref_builtin_upper_case">
<title>upper_case</title>
<indexterm>
<primary>upper_case built-in</primary>
</indexterm>
<para>The upper case version of the string. For example
<literal>"GrEeN MoUsE"</literal> will be <literal>"GREEN
MOUSE"</literal>.</para>
</section>
<section xml:id="ref_builtin_url">
<title>url</title>
<indexterm>
<primary>url built-in</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
<secondary>URL</secondary>
</indexterm>
<indexterm>
<primary>encoding</primary>
<secondary>URL</secondary>
</indexterm>
<indexterm>
<primary>URL escaping</primary>
</indexterm>
<indexterm>
<primary>URL encoding</primary>
</indexterm>
<indexterm>
<primary>url_escaping_charset</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.1. It
doesn't exist in 2.3.</para>
</note>
<para>The string after URL escaping. This means that all
non-US-ASCII and reserved URL characters will be escaped with
<literal>%<replaceable>XX</replaceable></literal>. For
example:</para>
<programlisting role="template">&lt;#assign x = 'a/b c'&gt;
${x?url}</programlisting>
<para>The output will be (assuming that the charset used for the
escaping is an US-ASCII compatible charset):</para>
<programlisting role="output">a%2Fb%20c</programlisting>
<para>Note that it escapes <emphasis>all</emphasis> reserved URL
characters (<literal>/</literal>, <literal>=</literal>,
<literal>&amp;</literal>, ...etc), so this encoding can be used for
encoding query parameter values, for example:</para>
<programlisting role="template">&lt;a href="foo.cgi?x=${x?url}&amp;y=${y?url}"&gt;Click here...&lt;/a&gt;</programlisting>
<note>
<para>Above no HTML encoding (<literal>?html</literal>) was
needed, because URL escaping escapes all reserved HTML characters
anyway. But watch: always quote the attribute value, and always
with normal quotation mark (<literal>"</literal>), never with
apostrophe quotation mark (<literal>'</literal>), because
apostrophe quotation mark is not escaped by the URL
escaping.</para>
</note>
<para>To do URL escaping a <link
linkend="gloss.charset">charset</link> must be chosen that will be
used for calculating the escaped parts
(<literal>%<replaceable>XX</replaceable></literal>). If you are HTML
page author and you don't really understand this, don't worry: the
programmers should configure FreeMarker so that it uses the proper
charset by default (<phrase role="forProgrammers">programmers: see
more below...</phrase>). If you are a more technical minded user,
then you may want to know that the charset used is specified by the
<literal>url_escaping_charset</literal> setting, that can be set in
template execution time (or, preferably, earlier by the
programmers). For example:</para>
<programlisting role="template">&lt;#--
This will use the charset specified by the programmers
before the template execution has started.
--&gt;
&lt;a href="foo.cgi?x=${x?url}"&gt;foo&lt;/a&gt;
&lt;#-- Use UTF-8 charset for URL escaping from now: --&gt;
<emphasis>&lt;#setting url_escaping_charset="UTF-8"&gt;</emphasis>
&lt;#-- This will surely use UTF-8 charset --&gt;
&lt;a href="bar.cgi?x=${x?url}"&gt;bar&lt;/a&gt;</programlisting>
<para>Furthermore, you can explicitly specify a charset for a single
URL escaping as the parameter to the built-in:</para>
<programlisting role="template">&lt;a href="foo.cgi?x=${x?url<emphasis>('ISO-8895-2')</emphasis>}"&gt;foo&lt;/a&gt;</programlisting>
<para><phrase role="forProgrammers"><indexterm>
<primary>output encoding</primary>
</indexterm><indexterm>
<primary>output charset</primary>
</indexterm>If the <literal>url</literal> built-in has no
parameter, then it will use the charset specified as the value of
the <literal>url_escaping_charset</literal> setting. This setting
should be set by the software that encloses FreeMarker (e.g. a Web
application framework), because it is not set
(<literal>null</literal>) by default. If it is not set, then
FreeMarker falls back using the value of the
<literal>output_encoding</literal> setting, which is also not set by
default, so it is again the task of the enclosing software. If the
<literal>output_encoding</literal> setting is not set either, then
the parameterless <literal>url</literal> built-in can't be executed,
and it will cause execution time error. Of course, the
<literal>url</literal> built-in with parameter always
works.</phrase></para>
<para><phrase role="forProgrammers">It's possible to set
<literal>url_escaping_charset</literal> in the template with the
<literal>setting</literal> directive, but it is bad practice, at
least in true MVC applications. The
<literal>output_encoding</literal> setting can't be set with the
<literal>setting</literal> directive, so that's surely the task of
the enclosing software. You may find more information regarding this
<link linkend="pgui_misc_charset">here...</link></phrase></para>
</section>
<section xml:id="ref_builtin_url_path">
<title>url_path</title>
<indexterm>
<primary>url_path built-in</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
<secondary>URL path</secondary>
</indexterm>
<indexterm>
<primary>encoding</primary>
<secondary>URL path</secondary>
</indexterm>
<indexterm>
<primary>URL escaping</primary>
</indexterm>
<indexterm>
<primary>URL encoding</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.21.</para>
</note>
<para>This is the same as <link linkend="ref_builtin_url">the
<literal>url</literal> built-in</link>, except that it doesn't
escape slash (<literal>/</literal>) characters. This meant to be
used for converting paths (like paths coming from the OS or some
content repository) that use slash (not backslash!) to a path the
can be inserted into an URL. The most common reason why this
conversion is needed is that folder names or file names might
contain non-US-ASCII letters (<quote>national</quote>
characters).</para>
<note>
<para>Just like with <link linkend="ref_builtin_url">the
<literal>url</literal> built-in</link>, the desired URL escaping
charset (or as a fall back, the output encoding) must be set in
the FreeMarker configuration settings, or else the built-in will
give error. Or, you you have to specify the charset like
<literal>somePath?url_path('utf-8')</literal>.</para>
</note>
</section>
<section xml:id="ref_builtin_word_list">
<title>word_list</title>
<indexterm>
<primary>word_list built-in</primary>
</indexterm>
<para>A sequence that contains all words of the string in the order
as they appear in the string. Words are continual character
sequences that contain any character but <link
linkend="gloss.whiteSpace">white-space</link>. Example:</para>
<programlisting role="template">&lt;#assign words = " a bcd, . 1-2-3"?word_list&gt;
&lt;#list words as word&gt;[${word}]&lt;/#list&gt;
</programlisting>
<para>will output:</para>
<programlisting role="output">[a][bcd,][.][1-2-3]</programlisting>
</section>
<section xml:id="ref_builtin_xhtml">
<title>xhtml (deprecated)</title>
<note>
<para>This built-in is <emphasis>deprecated</emphasis> by the
<link linkend="dgui_misc_autoescaping">auto-escaping
mechanism</link> introduced in 2.3.24. To prevent double escaping
and confusion in general, using this built-in on places where
auto-escaping is active is a <link
linkend="gloss.parseTimeError">parse-time error</link>. To help
migration, this built-in silently bypasses HTML <link
linkend="dgui_misc_autoescaping_movalues">markup output
values</link> without changing them.</para>
</note>
<indexterm>
<primary>xhtml built-in</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
<secondary>output</secondary>
</indexterm>
<para>The string as XHTML text. That is, the string with all:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>&lt;</literal> replaced with
<literal>&amp;lt;</literal></para>
</listitem>
<listitem>
<para><literal>&gt;</literal> replaced with
<literal>&amp;gt;</literal></para>
</listitem>
<listitem>
<para><literal>&amp;</literal> replaced with
<literal>&amp;amp;</literal></para>
</listitem>
<listitem>
<para><literal>"</literal> replaced with
<literal>&amp;quot;</literal></para>
</listitem>
<listitem>
<para><literal>'</literal> replaced with
<literal>&amp;#39;</literal></para>
</listitem>
</itemizedlist>
<para>The only difference between this built-in and the
<literal>xml</literal> built-in is that the <literal>xhtml</literal>
built-in escapes <literal>'</literal> as
<literal>&amp;#39;</literal> instead of as
<literal>&amp;apos;</literal>, because some older browsers don't
know <literal>&amp;apos;</literal>.</para>
<warning>
<para>When inserting the value of an attribute, always quote it,
or else it can be exploited by attacker! This is WRONG:
<literal>&lt;input name="user" value=${user?xhtml}/&gt;</literal>.
These are good: <literal>&lt;input name="user"
value="${user?xhtml}"/&gt;</literal>, <literal>&lt;input
name="user" value='${user?xhtml}'/&gt;</literal>.</para>
</warning>
</section>
<section xml:id="ref_builtin_xml">
<title>xml (deprecated)</title>
<note>
<para>This built-in is <emphasis>deprecated</emphasis> by the
<link linkend="dgui_misc_autoescaping">auto-escaping
mechanism</link> introduced in 2.3.24. To prevent double escaping
and confusion in general, using this built-in on places where
auto-escaping is active is a <link
linkend="gloss.parseTimeError">parse-time error</link>. To help
migration, this built-in silently bypasses XML and HTML <link
linkend="dgui_misc_autoescaping_movalues">markup output
values</link> without changing them.</para>
</note>
<indexterm>
<primary>xml built-in</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
<secondary>output</secondary>
</indexterm>
<para>The string as XML text. That is, the string with all:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>&lt;</literal> replaced with
<literal>&amp;lt;</literal></para>
</listitem>
<listitem>
<para><literal>&gt;</literal> replaced with
<literal>&amp;gt;</literal></para>
</listitem>
<listitem>
<para><literal>&amp;</literal> replaced with
<literal>&amp;amp;</literal></para>
</listitem>
<listitem>
<para><literal>"</literal> replaced with
<literal>&amp;quot;</literal></para>
</listitem>
<listitem>
<para><literal>'</literal> replaced with
<literal>&amp;apos;</literal></para>
</listitem>
</itemizedlist>
<warning>
<para>When inserting the value of an attribute, always quote it,
or else it can be exploited by attackers! This is WRONG:
<literal>&lt;input name="user" value=${user?xml}/&gt;</literal>.
These are good: <literal>&lt;input name="user"
value="${user?xml}"/&gt;</literal>, <literal>&lt;input name="user"
value='${user?xml}'/&gt;</literal>.</para>
</warning>
</section>
<section xml:id="ref_builtin_string_flags">
<title>Common flags</title>
<para>Many string built-ins accept an optional string parameter, the
so called <quote>flags</quote>. In this string, each letter
influences a certain aspect of the behavior of the built-in. For
example, letter <literal>i</literal> means that the built-in should
not differentiate the lower and upper-case variation of the same
letter. The order of the letters in the flags string is not
significant.</para>
<para>This is the complete list of letters (flags):</para>
<itemizedlist>
<listitem>
<para><literal>i</literal>: Case insensitive: do not
differentiate the lower and upper-case variation of the same
letter.</para>
</listitem>
<listitem>
<para><literal>f</literal>: First only. That is,
replace/find/etc. only the first occurrence of something.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>regular expression</primary>
<secondary>built-ins</secondary>
</indexterm> <literal>r</literal>: The substring to find is a
<link linkend="gloss.regularExpression">regular
expression</link>. FreeMarker uses the variation of regular
expressions described at <link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html</link>
(note that the presence of some pattern features depends on the
Java version used).</para>
</listitem>
<listitem>
<para><literal>m</literal>: Multi-line mode for regular
expressions. In multi-line mode the expressions
<literal>^</literal> and <literal>$</literal> match just after
or just before, respectively, a line terminator or the end of
the string. By default these expressions only match at the
beginning and the end of the entire string. Note that
<literal>^</literal> and <literal>$</literal> doesn't match the
line-break character itself.</para>
</listitem>
<listitem>
<para><literal>s</literal>: Enables dot-all mode for regular
expressions (same as Perl singe-line mode). In dot-all mode, the
expression <literal>.</literal> matches any character, including
a line terminator. By default this expression does not match
line terminators.</para>
</listitem>
<listitem>
<para><literal>c</literal>: Permits whitespace and comments in
regular expressions.</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<programlisting role="template">&lt;#assign s = 'foo bAr baar'&gt;
${s?replace('ba', 'XY')}
i: ${s?replace('ba', 'XY', 'i')}
if: ${s?replace('ba', 'XY', 'if')}
r: ${s?replace('ba*', 'XY', 'r')}
ri: ${s?replace('ba*', 'XY', 'ri')}
rif: ${s?replace('ba*', 'XY', 'rif')}</programlisting>
<para>This outputs this:</para>
<programlisting role="output">foo bAr XYar
i: foo XYr XYar
if: foo XYr baar
r: foo XYAr XYr
ri: foo XYr XYr
rif: foo XYr baar</programlisting>
<para>This is the table of built-ins that use these common flags,
and which supports which flags:</para>
<informaltable border="1">
<thead>
<tr>
<th>Built-in</th>
<th><literal>i</literal> (ignore case)</th>
<th><literal>r</literal> (reg. exp.)</th>
<th><literal>m</literal> (multi-line mode)</th>
<th><literal>s</literal> (dot-all mode)</th>
<th><literal>c</literal> (whitesp. and comments)</th>
<th><literal>f</literal> (first only)</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>replace</literal></td>
<td>Yes</td>
<td>Yes</td>
<td>Only with <literal>r</literal></td>
<td>Only with <literal>r</literal></td>
<td>Only with <literal>r</literal></td>
<td>Yes</td>
</tr>
<tr>
<td><literal>split</literal></td>
<td>Yes</td>
<td>Yes</td>
<td>Only with <literal>r</literal></td>
<td>Only with <literal>r</literal></td>
<td>Only with <literal>r</literal></td>
<td>No</td>
</tr>
<tr>
<td><literal>matches</literal></td>
<td>Yes</td>
<td>Ignored</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td><literal>keep_after</literal></td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Ignored</td>
</tr>
<tr>
<td><literal>keep_after_last</literal></td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Ignored</td>
</tr>
<tr>
<td><literal>keep_before</literal></td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Ignored</td>
</tr>
<tr>
<td><literal>keep_before_last</literal></td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Ignored</td>
</tr>
<tr>
<td><literal>ensure_starts_with</literal></td>
<td>Yes</td>
<td>Ignored</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Ignored</td>
</tr>
</tbody>
</informaltable>
</section>
</section>
<section xml:id="ref_builtins_number">
<title>Built-ins for numbers</title>
<indexterm>
<primary>number</primary>
<secondary>built-ins</secondary>
</indexterm>
<para>Related FAQs: Do you have things like 1,000,000 or 1 000 000
instead of 1000000, or something like 3.14 instead of 3,14 or vice
versa? See <link linkend="faq_number_grouping">this</link> and <link
linkend="faq_number_decimal_point">this</link> FAQ entry, also note
the <literal>c</literal> built-in above.</para>
<section xml:id="ref_builtin_abs">
<title>abs</title>
<indexterm>
<primary>abs built-in</primary>
</indexterm>
<indexterm>
<primary>absolute value</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.20.</para>
</note>
<para>Gives the absolute value of a number. For example
<literal>x?abs</literal> , if <literal>x</literal> is -5, will
evaluate to 5.</para>
</section>
<section xml:id="ref_builtin_c">
<title>c (when used with numerical value)</title>
<indexterm>
<primary>c built-in</primary>
</indexterm>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>number</secondary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.3.</para>
</note>
<para>This built-in converts a number to string for a
<quote>computer language</quote> as opposed to for human audience.
That is, it formats with the rules that programming languages used
to use, which is independent of all the locale and number format
settings of FreeMarker. It always uses dot as decimal separator, and
it never uses grouping separators (like 3,000,000), nor exponential
form (like 5E20), nor superfluous leading or trailing 0-s (like 03
or 1.0), nor + sign (like +1). It will print at most 16 digits after
the decimal dot, and thus numbers whose absolute value is less than
1E-16 will be shown as 0. This built-in is crucial because be
default (like with <literal>${x}</literal>) numbers are converted to
strings with the locale (language, country) specific number
formatting, which is for human readers (like 3000000 is possibly
printed as 3,000,000). When the number is printed not for human
audience (e.g., for a database record ID used as the part of an URL,
or as invisible field value in a HTML form, or for printing
CSS/JavaScript numerical literals) this built-in must be used to
print the number (i.e., use <literal>${x?c}</literal> instead of
<literal>${x}</literal>), or else the output will be possibly broken
depending on the current number formatting settings and locale (like
the decimal point is not dot, but comma in many countries) and the
value of the number (like big numbers are possibly
<quote>damaged</quote> by grouping separators).</para>
<para>If the <literal>incompatible_improvements</literal> FreeMarker
configuration setting is set to 2.3.24 or higher (also if it's set
to 2.3.20 or higher and you are outside a string literal), this
built-in will return <literal>"INF"</literal>,
<literal>"-INF"</literal> and <literal>"NaN"</literal> for
positive/negative infinity and IEEE floating point Not-a-Number,
respectively. These are the XML Schema compatible representations of
these special values. (Earlier it has returned what
<literal>java.text.DecimalFormat</literal> did with US locale, none
of which is understood by any (common) computer language.)</para>
<para>Note that this built-in <link
linkend="ref_builtin_c_boolean">also works on
booleans</link>.</para>
</section>
<section xml:id="ref_builtin_is_infinite">
<title>is_infinite</title>
<indexterm>
<primary>is_infinte built-in</primary>
</indexterm>
<indexterm>
<primary>infinite</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.20.</para>
</note>
<para>Tells if a number is floating point infinite (according to
IEEE 754). For example, <literal>someNumber?is_infinite</literal>
evaluates to <literal>true</literal> or <literal>false</literal>
depending on if the value of <literal>someNumber</literal> is
infinite or not. Of course, if the underlying number is not of
floating point type, this will always return
<literal>false</literal>.</para>
</section>
<section xml:id="ref_builtin_is_nan">
<title>is_nan</title>
<indexterm>
<primary>is_nan built-in</primary>
</indexterm>
<indexterm>
<primary>NaN</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.20.</para>
</note>
<para>Tells if a number is floating point NaN (according to IEEE
754). For example, <literal>someNumber?is_nan</literal> evaluates to
<literal>true</literal> or <literal>false</literal> depending on if
the value of <literal>someNumber</literal> is NaN or not. Of course,
if the underlying number is not of floating point type, this will
always return <literal>false</literal>.</para>
</section>
<section xml:id="ref_builtin_lower_abc">
<title>lower_abc</title>
<indexterm>
<primary>lower_abc built-in</primary>
</indexterm>
<indexterm>
<primary>ABC</primary>
</indexterm>
<indexterm>
<primary>alphabetical ordinals</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.22.</para>
</note>
<para>Converts <literal>1</literal>, <literal>2</literal>,
<literal>3</literal>, etc., to the string <literal>"a"</literal>,
<literal>"b"</literal>, <literal>"c"</literal>, etc. When reaching
<literal>"z"</literal>, it continues like <literal>"aa"</literal>,
<literal>"ab"</literal>, etc. This is the same logic that you can
see in column labels in spreadsheet applications (like Excel or
Calc). The lowest allowed number is <literal>1</literal>. There's no
upper limit. If the number is <literal>0</literal> or less or it
isn't an integer number then the template processing will be aborted
with error.</para>
<para>Example:</para>
<programlisting role="template">&lt;#list 1..30 as n&gt;${n?lower_abc} &lt;/#list&gt;</programlisting>
<para>Prints:</para>
<programlisting role="output">a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad </programlisting>
<para>See also: <link
linkend="ref_builtin_upper_abc"><literal>upper_abc</literal></link></para>
</section>
<section xml:id="ref_builtin_rounding">
<title>round, floor, ceiling</title>
<indexterm>
<primary>rounding</primary>
</indexterm>
<indexterm>
<primary>floor built-in</primary>
</indexterm>
<indexterm>
<primary>ceiling built-in</primary>
</indexterm>
<indexterm>
<primary>round built-in</primary>
</indexterm>
<note>
<para>The rounding built-ins exist since FreeMarker 2.3.13.</para>
</note>
<para>Converts a number to a whole number using the specified
rounding rule:</para>
<itemizedlist>
<listitem>
<para><literal>round</literal>: Rounds to the nearest whole
number. If the number ends with .5, then it rounds upwards
(i.e., towards positive infinity)</para>
</listitem>
<listitem>
<para><literal>floor</literal>: Rounds the number downwards
(i.e., towards neagative infinity)</para>
</listitem>
<listitem>
<para><literal>ceiling</literal>: Rounds the number upwards
(i.e., towards positive infinity)</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<programlisting role="template">&lt;#assign testlist=[
0, 1, -1, 0.5, 1.5, -0.5,
-1.5, 0.25, -0.25, 1.75, -1.75]&gt;
&lt;#list testlist as result&gt;
${result} ?floor=${result?floor} ?ceiling=${result?ceiling} ?round=${result?round}
&lt;/#list&gt;</programlisting>
<para>Prints:</para>
<programlisting role="output"> 0 ?floor=0 ?ceiling=0 ?round=0
1 ?floor=1 ?ceiling=1 ?round=1
-1 ?floor=-1 ?ceiling=-1 ?round=-1
0.5 ?floor=0 ?ceiling=1 ?round=1
1.5 ?floor=1 ?ceiling=2 ?round=2
-0.5 ?floor=-1 ?ceiling=0 ?round=0
-1.5 ?floor=-2 ?ceiling=-1 ?round=-1
0.25 ?floor=0 ?ceiling=1 ?round=0
-0.25 ?floor=-1 ?ceiling=0 ?round=0
1.75 ?floor=1 ?ceiling=2 ?round=2
-1.75 ?floor=-2 ?ceiling=-1 ?round=-2</programlisting>
<para>These built-ins may be useful in pagination operations and
like. If you just want to <emphasis>display</emphasis> numbers in
rounded form, then you should rather use the <link
linkend="ref_builtin_string_for_number"><literal>string</literal>
built-in</link> or the <link
linkend="ref.setting.number_format"><literal>number_format</literal>
setting</link>.</para>
</section>
<section xml:id="ref_builtin_string_for_number">
<title>string (when used with a numerical value)</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>string built-in</primary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>number</secondary>
</indexterm>
<para>Converts a number to a string. In its simplest form
(<literal><replaceable>expression</replaceable>?string</literal>) it
uses the default format that the programmer has specified via the
<literal>number_format</literal> and the <literal>locale</literal>
configuration settings. You can also specify a number format
explicitly with this built-in, as it will be shown later.</para>
<para>There are four predefined number formats:
<literal>computer</literal>, <literal>currency</literal>,
<literal>number</literal>, and <literal>percent</literal>. The exact
meaning of these is locale (nationality) specific, and is controlled
by the Java platform installation, not by FreeMarker, except for
<literal>computer</literal>, which uses the same formatting as <link
linkend="ref_builtin_c">the <literal>c</literal> built-in</link>
(assuming <link
linkend="pgui_config_incompatible_improvements">incompatible
improvements</link> set to 2.3.31, or higher, or else infinity and
NaN isn't formatted like that). There can also be programmer-defined
formats, whose name starts with <literal>@</literal> (programmers
<link linkend="pgui_config_custom_formats">see more here...</link>).
You can use these predefined formats like this:</para>
<programlisting role="template">&lt;#assign x=4200000&gt;
${x}
${x?string} &lt;#-- the same as ${x} --&gt;
${x?string.number}
${x?string.currency}
${x?string.percent}
${x?string.computer}</programlisting>
<para>If your locale is US English, this will print:</para>
<programlisting role="output">4,200,000
4,200,000
4,200,000
$4,200,000.00
420,000,000%
4200000</programlisting>
<para>The output of first three expressions is identical because the
first two expressions use the default format, which is
<quote>number</quote> here. You can change this default using a
setting:</para>
<programlisting role="template">&lt;#setting number_format="currency"&gt;
&lt;#assign x=4200000&gt;
${x}
${x?string} &lt;#-- the same as ${x} --&gt;
${x?string.number}
${x?string.currency}
${x?string.percent}</programlisting>
<para>Will now output:</para>
<programlisting role="output">$4,200,000.00
$4,200,000.00
4,200,000
$4,200,000.00
420,000,000%</programlisting>
<para>since the default number format was set to
<quote>currency</quote>.</para>
<para>You can also refer to named custom formats that were defined
when configuring FreeMarker (programmers <link
linkend="pgui_config_custom_formats">see more here</link>),
like:</para>
<programlisting role="template">${x?string.@price}
${x?string.@weight}</programlisting>
<para>where the custom format names were <quote>price</quote> and
<quote>weight</quote>. This way the templates can just refer to the
application-domain meaning, and the exact format can be specified
outside the templates, on a single central place. (Programmers can
read about <link linkend="pgui_config_custom_formats">defining such
named formats here...</link>)</para>
<para>Beside named formats, you can specify number format patterns
directly, using the <link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html">Java
decimal number format syntax</link> (with some FreeMarker-specific
extensions; <link linkend="topic.extendedJavaDecimalFormat">see
later</link>):</para>
<programlisting role="template">&lt;#assign x = 1.234&gt;
${x?string["0"]}
${x?string["0.#"]}
${x?string["0.##"]}
${x?string["0.###"]}
${x?string["0.####"]}
${1?string["000.00"]}
${12.1?string["000.00"]}
${123.456?string["000.00"]}
${1.2?string["0"]}
${1.8?string["0"]}
${1.5?string["0"]} &lt;-- 1.5, rounded towards even neighbor
${2.5?string["0"]} &lt;-- 2.5, rounded towards even neighbor
${12345?string["0.##E0"]}</programlisting>
<programlisting role="output">1
1.2
1.23
1.234
1.234
001.00
012.10
123.46
1
2
2 &lt;-- 1.5, rounded towards even neighbor
2 &lt;-- 2.5, rounded towards even neighbor
1.23E4</programlisting>
<para>Note that as in FreeMarker <literal>foo.bar</literal> is
equivalent with <literal>foo["bar"]</literal>, you could also write
<literal>x?string.currency</literal> as
<literal>x?string["currency"]</literal>, but of course that wouldn't
be practical. But in the above examples we have to use the square
bracket syntax, because the characters involved (numbers, dot,
<literal>#</literal>) aren't allowed syntactically after the dot
operator.</para>
<para>For historical reasons, you could also write things like
<literal>x?string("0.#")</literal>, which does exactly the same as
<literal>x?string["0.#"]</literal>.</para>
<para>Following the financial and statistics practice, by default
the rounding goes according the so called half-even rule, which
means rounding towards the nearest <quote>neighbor</quote>, unless
both neighbors are equidistant, in which case, it rounds towards the
even neighbor. This was visible in the above example if you look at
the rounding of 1.5 and of 2.5, as both were rounded to 2, since 2
is even, but 1 and 3 are odds. The other popular rounding rule,
where we always round up when the neighbors are equidistant (and so
2.5 is rounded to 3) is called the half-up rule, and it can be
activated as <link
linkend="topic.extendedJavaDecimalFormat">described
later</link>.</para>
<para>As it was shown for the predefined formats earlier, the
default formatting of the numbers can be set in the template:</para>
<programlisting role="template">&lt;#setting number_format="0.##"&gt;
${1.234}</programlisting>
<programlisting role="output">1.23</programlisting>
<para>The default number format also can be specified outside the
templates with the FreeMarker API (like with
<literal>Configuration.setNumberFormat(String)</literal>).</para>
<para>Note that as number formatting is locale sensitive, the locale
setting also plays role in the formatting:</para>
<programlisting role="template">&lt;#setting number_format=",##0.00"&gt;
&lt;#setting locale="en_US"&gt;
US people write: ${12345678}
&lt;#setting locale="de_DE"&gt;
German people write: ${12345678}</programlisting>
<programlisting role="output">US people write: 12,345,678.00
German people write: 12.345.678,00</programlisting>
<simplesect xml:id="topic.extendedJavaDecimalFormat">
<title>Extended Java decimal format</title>
<indexterm>
<primary>extended Java decimal format</primary>
</indexterm>
<note>
<para>You need at least FreeMarker 2.3.24 for these to work.
Before that, extended Java decimal format parts are just
silently ignored by
<literal>java.text.DecimalFormat</literal>.</para>
</note>
<para>FreeMarker extends the Java decimal format patterns with
extra options. These options are name-value pairs, specified after
two semicolons (<literal>;;</literal>) at the end of the format
string, or if you had a negative pattern (which is separated from
the normal patter with a semicolon, like in <literal>"0.0;minus
0.0"</literal>), the after only one semicolon. For example:</para>
<programlisting role="template">Standard decimal format: ${10002.5?string[",000"]}
Extended decimal format: ${10002.5?string[",000<emphasis>;; roundingMode=halfUp groupingSeparator=_</emphasis>"]}</programlisting>
<programlisting role="output">Standard decimal format: 10,002
Extended decimal format: 10<emphasis>_</emphasis>00<emphasis>3</emphasis></programlisting>
<warning>
<para>A very easy mistake to make is just using a single
semicolon instead of two. It won't even result in an error, as
<literal>java.text.DecimalFormat</literal> thinks you have just
specified some weird format for negative numbers. So remember to
use two semicolons.</para>
</warning>
<para>Above, in the extended decimal format, we have specified
half-up rounding mode and group separator <literal>"_"</literal>.
The table of all options follows (note that these are defined by
<literal>java.text.DecimalFormat</literal> and
<literal>java.text.DecimalFormatSymbols</literal>, not by
FreeMarker):</para>
<informaltable border="1">
<thead>
<tr>
<th>Name</th>
<th>Meaning / value</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>roundingMode</literal></td>
<td>The value is one of <literal>up</literal>,
<literal>down</literal>, <literal>ceiling</literal>,
<literal>floor</literal>, <literal>halfUp</literal>,
<literal>halfDown</literal>, <literal>halfEven</literal>,
and <literal>unnecessary</literal>. The behavior that most
people learns in school is <literal>halfUp</literal>, but
the Java default is <literal>halfEven</literal> (also called
bankers' rounding). (See <link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html">the
<literal>java.math.RoundingMode</literal> API</link> for
explanations.)</td>
</tr>
<tr>
<td><literal>multiplier</literal> since 2.3.29;
<literal>multipier</literal> since 2.3.24</td>
<td>The number will be shown after multiplied with this
integer number.</td>
</tr>
<tr>
<td><literal>decimalSeparator</literal></td>
<td>The character separating the integer part from the
fraction part (like <literal>"."</literal> in
<literal>3.14</literal>).</td>
</tr>
<tr>
<td><literal>monetaryDecimalSeparator</literal></td>
<td>This is used instead of
<literal>decimalSeparator</literal> when the pattern
contains parts that make it a monetary format. (See the
<link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html">Java
decimal number format documentation</link> for more.)</td>
</tr>
<tr>
<td><literal>groupingSeparator</literal></td>
<td>The single character used for grouping the integer part
(like <literal>","</literal> in
<literal>1,000,000</literal>) Note that grouping is turned
on by using <literal>","</literal> in the pattern, as shown
in the earlier example. If it's not turned on, this option
won't have visible effect.</td>
</tr>
<tr>
<td><literal>exponentSeparator</literal></td>
<td>This string (of arbitrary length) is used to separate
the exponent from the part before it. (like
<literal>"E"</literal> in <literal>1.23E6</literal>). Only
has visible effect if the pattern specifies exponential
(also known as scientific) format, like
<literal>"0.##E0"</literal>.</td>
</tr>
<tr>
<td><literal>minusSign</literal></td>
<td>The single character used as minus sign (like
<literal>"-"</literal> in <literal>-1</literal>).</td>
</tr>
<tr>
<td><literal>infinity</literal></td>
<td>The string (of arbitrary length) used to show
infinity.</td>
</tr>
<tr>
<td><literal>nan</literal></td>
<td>The string (of arbitrary length) used to show
not-a-number (NaN).</td>
</tr>
<tr>
<td><literal>percent</literal></td>
<td>The single character used as the percent symbol (like
<literal>"%"</literal> in <literal>50%</literal>). Only has
visible effect if the pattern contains
<literal>%</literal>.</td>
</tr>
<tr>
<td><literal>perMill</literal></td>
<td>The single character used as the per-mill symbol (like
<literal>"‰"</literal> in <literal>50021‰</literal>). Only
has visible effect if the pattern contains
<literal>‰</literal>.</td>
</tr>
<tr>
<td><literal>zeroDigit</literal></td>
<td>The first character in the 10 character range (of
character codes) that contains the digits to be used. For
example, if this is <literal>A</literal>, then 1 will
<literal>B</literal>, 2 will be <literal>C</literal>, and so
on.</td>
</tr>
<tr>
<td><literal>currencyCode</literal></td>
<td>Currency ISO 4217 code. Only has effect when the pattern
contains parts that make it a monetary format. It's an error
to specify a code that's not a known ISO 4217 code in the
Java installation.</td>
</tr>
<tr>
<td><literal>currencySymbol</literal></td>
<td>Currency symbol; shown where the localized currency name
is present in the pattern. Overrides the symbol determined
based on the <literal>currencyCode</literal>.</td>
</tr>
</tbody>
</informaltable>
<para>Regarding the syntax of the options:</para>
<itemizedlist>
<listitem>
<para>The option name and value are separated by equals
character (<literal>=</literal>).</para>
</listitem>
<listitem>
<para>Options are separated by whitespace and/or optional
comma (<literal>,</literal>)</para>
</listitem>
<listitem>
<para>The option value can be quoted with apostrophe
(<literal>'</literal>) or normal quotation mark
(<literal>"</literal>) , like
<literal>exponentSeparator='*10^'</literal> or
<literal>exponentSeparator="*10^"</literal>. If the value
itself has to contain the character used for quotation, then
it has to be entered twice (like <literal>infinity='It''s
infinite'</literal>, but you could also write
<literal>infinity="It's infinite"</literal>). Backslash has no
special meaning.</para>
</listitem>
<listitem>
<para>Non-string values must not be quoted. Strings only has
to be quoted if they contain punctuation or whitespace, or any
other non-letter non-digit non-<literal>"_"</literal>
non-<literal>"$"</literal> characters. Thus, for example, both
<literal>roundingMode=down</literal> and
<literal>roundingMode="down"</literal> are legal.</para>
</listitem>
</itemizedlist>
</simplesect>
</section>
<section xml:id="ref_builtin_upper_abc">
<title>upper_abc</title>
<indexterm>
<primary>upper_abc built-in</primary>
</indexterm>
<indexterm>
<primary>ABC</primary>
</indexterm>
<indexterm>
<primary>alphabetical ordinals</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.22.</para>
</note>
<para>Same as <link
linkend="ref_builtin_lower_abc"><literal>lower_abc</literal></link>,
but converts to upper case letters, like <literal>"A"</literal>,
<literal>"B"</literal>, <literal>"C"</literal>, …,
<literal>"AA"</literal>, <literal>"AB"</literal>, etc.</para>
</section>
</section>
<section xml:id="ref_builtins_date">
<title>Built-ins for date/time/date-time values</title>
<indexterm>
<primary>date</primary>
<secondary>built-ins</secondary>
</indexterm>
<indexterm>
<primary>time</primary>
<secondary>built-ins</secondary>
</indexterm>
<indexterm>
<primary>datetime</primary>
<secondary>built-ins</secondary>
</indexterm>
<indexterm>
<primary>timestamp</primary>
<secondary>built-ins</secondary>
</indexterm>
<section xml:id="ref_builtin_date_datetype">
<title>date, time, datetime (when used with a date/time/date-time
value)</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>date built-in</primary>
</indexterm>
<indexterm>
<primary>time built-in</primary>
</indexterm>
<indexterm>
<primary>datetime built-in</primary>
</indexterm>
<para>These built-ins can be used to specify which parts of the
date-like variable are in use:</para>
<itemizedlist>
<listitem>
<para><literal>date</literal>: Date only, no time of the
day.</para>
</listitem>
<listitem>
<para><literal>time</literal>: Only the time of the day, no date
part</para>
</listitem>
<listitem>
<para><literal>datetime</literal>: Both date and time</para>
</listitem>
</itemizedlist>
<para>Ideally, you do not need to use these built-ins.
Unfortunately, because of the technical limitations of the Java
platform, FreeMarker sometimes can't find out which parts of a
date-like value is a date, a time or a date-time; ask the
programmers which variables has this problem. If FreeMarker has to
execute an operation where this information is needed -- such as
displaying the value as text -- but it does not know which parts are
in use, it will stop with error. This is when you have to use these
built-ins. For example, assume <literal>openingTime</literal> is a
such problematic variable:</para>
<programlisting role="template">&lt;#assign x = openingTime&gt; &lt;#-- no problem can occur here --&gt;
${openingTime?time} &lt;#-- without ?time it would fail --&gt;
&lt;#-- For the sake of better understanding, consider this: --&gt;
&lt;#assign openingTime = openingTime?time&gt;
${openingTime} &lt;#-- this will work now --&gt;</programlisting>
<para>These built-ins can also be used to convert date-time values
to date or time. For example:</para>
<programlisting role="template">Last updated: ${lastUpdated} &lt;#-- assume that lastUpdated is a date-time value --&gt;
Last updated date: ${lastUpdated?date}
Last updated time: ${lastUpdated?time}</programlisting>
<para>will output something like:</para>
<programlisting role="output">Last updated: 04/25/2003 08:00:54 PM
Last updated date: 04/25/2003
Last updated time: 08:00:54 PM</programlisting>
<para>If the left side of the <literal>?</literal> is string, then
these built-ins <link linkend="ref_builtin_string_date">convert
strings to date/time/date-time</link>.</para>
</section>
<section xml:id="ref_builtin_date_if_unknown">
<title>date_if_unknown, time_if_unknown, datetime_if_unknown</title>
<note>
<para>This built-in exists since FreeMarker 2.3.21.</para>
</note>
<para>The <literal>date_if_unknown</literal>,
<literal>time_if_unknown</literal>,
<literal>datetime_if_unknown</literal> built-ins mark a date-like
value with some of the sub-types: date without time, time, or
date-time, respectively. However, if the value already holds this
information, the built-in has no effect. That is, it will never
convert the sub-type of a value, it only adds the sub-type if it was
unknown.</para>
</section>
<section xml:id="ref_builtin_date_iso">
<title>iso_...</title>
<indexterm>
<primary>iso built-in</primary>
</indexterm>
<indexterm>
<primary>iso_... built-ins</primary>
</indexterm>
<note>
<para><emphasis>These built-ins are deprecated</emphasis> since
FreeMarker 2.3.21, where the <literal>date_format</literal>,
<literal>time_format</literal> and
<literal>datetime_format</literal> settings understand
<literal>"iso"</literal> (for ISO 8601:2004 format) and
<literal>"xs"</literal> (for XML Schema format) in additionally to
the Java <literal>SimpleDateFormat</literal> patterns. Thus the
default format can be set to ISO 8601, or for one time ISO
formatting you can use <literal>myDate?string.iso</literal>. <link
linkend="topic.dateTimeFormatSettings">See more
here...</link></para>
</note>
<para>These built-ins convert a date, time or date-time value to
string that follows ISO 8601:2004 "extended" format.</para>
<para>This built-in has several variations:
<literal>iso_utc</literal>, <literal>iso_local</literal>,
<literal>iso_utc_nz</literal>, <literal>iso_local_nz</literal>,
<literal>iso_utc_m</literal>, <literal>iso_utc_m_nz</literal>, etc.
The name is constructed from the following words in this order, each
separated with a <literal>_</literal> from the next:</para>
<orderedlist>
<listitem>
<para><literal>iso</literal> (required)</para>
</listitem>
<listitem>
<para>Either <literal>utc</literal> or <literal>local</literal>
(required (except when it's given with a parameter, but see that
later)): Specifies whether you want to print the
date/time/date-time according to UTC or according the current
time zone. The current time zone is decided by the
<literal>time_zone</literal> FreeMarker setting and is normally
configured by the programmers outside the templates (but it can
also be set in a template, like <literal>&lt;#setting
time_zone="America/New_York"&gt;</literal> for example). Note
that if the <literal>sql_date_and_time_time_zone</literal>
FreeMarker setting is set and non-<literal>null</literal>, then
for <literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal> values (i.e., for date-only and
time-only values that are coming from database via SQL)
<literal>local</literal> will mean that time zone instead of the
value of the <literal>time_zone</literal> setting.</para>
</listitem>
<listitem>
<para>Either <literal>h</literal> or <literal>m</literal> or
<literal>ms</literal> (optional): The accuracy of the time part.
When omitted, it defaults to seconds accuracy (like
<literal>12:30:18</literal>). <literal>h</literal> means hours
accuracy (like <literal>12</literal>), <literal>m</literal>
means minutes accuracy (<literal>12:30</literal>), and
<literal>ms</literal> means milliseconds accuracy
(<literal>12:30:18.25</literal>, where we have 250 ms). Note
that when using <literal>ms</literal>, the milliseconds are
displayed as fraction seconds (following the standard) and will
not have trailing <literal>0</literal>-s. Thus, if the the
millisecond part happens to be <literal>0</literal>, the whole
fraction second part will be omitted. Also note that the
fraction seconds are always separated with a dot , not with
comma (to follow the Web conventions and XML Schema
time/dateTime canonical format).</para>
</listitem>
<listitem>
<para><literal>nz</literal> (optional): <literal>nz</literal>
(like in <literal>${foo?utc_local_nz}</literal>) stands for
<quote>no zone</quote>, which means that the time zone offset
(like <literal>+02:00</literal> or or <literal>-04:30</literal>
or <literal>Z</literal>) will not be displayed. If this part is
omitted (like in <literal>${foo?utc_local}</literal>) the zone
will be displayed, except in two cases:</para>
<itemizedlist>
<listitem>
<para>If the value is a date (no time part) value (again,
ISO 8901 doesn't allow it then)</para>
</listitem>
<listitem>
<para>If the value is a <literal>java.sql.Time</literal> and
the <literal>incompatible_improvements</literal> (often set
via the Java <literal>Configuration</literal> constructor
parameter) FreeMarker configuration setting is at least
2.3.21 (or 2.3.24 when you are inside a string literal).
This is because most databases store time values that aren't
in any time zone, but just store hour, minute, second, and
decimal second field values, so showing the time zone
doesn't make sense.</para>
</listitem>
</itemizedlist>
<para>Note that since FreeMarker 2.3.19, the offset always
contains the minutes for XML Schema date/time/dateTime format
compliance. (However, if you primarily generate for the XML
Schema format, use the xs format.)</para>
</listitem>
</orderedlist>
<para>Example:</para>
<programlisting role="template">&lt;#assign aDateTime = .now&gt;
&lt;#assign aDate = aDateTime?date&gt;
&lt;#assign aTime = aDateTime?time&gt;
Basic formats:
${aDate?iso_utc}
${aTime?iso_utc}
${aDateTime?iso_utc}
Different accuracies:
${aTime?iso_utc_ms}
${aDateTime?iso_utc_m}
Local time zone:
${aDateTime?iso_local}</programlisting>
<para>A possible output (depends on current time and time
zone):</para>
<programlisting role="output">Basic formats:
2011-05-16
21:32:13Z
2011-05-16T21:32:13Z
Different accuracies:
21:32:13.868Z
2011-05-16T21:32Z
Local time zone:
2011-05-16T23:32:13+02:00</programlisting>
<para>There is yet another group of <literal>iso_...</literal>
built-in variants, where you omit the <literal>local</literal> or
<literal>utc</literal> word from the name and instead specify the
time zone as a parameter to the built-in. Example:</para>
<programlisting role="template">&lt;#assign aDateTime = .now&gt;
${aDateTime?iso("UTC")}
${aDateTime?iso("GMT-02:30")}
${aDateTime?iso("Europe/Rome")}
The usual variations are supported:
${aDateTime?iso_m("GMT+02")}
${aDateTime?iso_m_nz("GMT+02")}
${aDateTime?iso_nz("GMT+02")}</programlisting>
<para>A possible output (depends on current time and time
zone):</para>
<programlisting role="output">2011-05-16T21:43:58Z
2011-05-16T19:13:58-02:30
2011-05-16T23:43:58+02:00
The usual variations are supported:
2011-05-16T23:43+02:00
2011-05-16T23:43
2011-05-16T23:43:58</programlisting>
<para>If the time zone parameter can't be interpreted, the template
processing will be terminated with error.</para>
<para role="forProgrammers">The parameter can be a
<literal>java.util.TimeZone</literal> object too (which is possibly
the return value of a Java method, or it's in the data-model), not
just a string.</para>
</section>
<section xml:id="ref_builtin_string_for_date">
<title>string (when used with a date/time/date-time value)</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>string built-in</primary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>date</secondary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>time</secondary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>date-time</secondary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>timestamp</secondary>
</indexterm>
<indexterm>
<primary>converting date to string</primary>
</indexterm>
<indexterm>
<primary>converting time to string</primary>
</indexterm>
<indexterm>
<primary>time to string</primary>
</indexterm>
<indexterm>
<primary>date to string</primary>
</indexterm>
<para>This built-in converts a date to a string, with the specified
formatting.</para>
<note>
<para>You should need this built-in rarely, as the default format
of date/time/date-time values can be specified globally <link
linkend="topic.dateTimeFormatSettings">with the
<literal>date_format</literal>, <literal>time_format</literal> and
<literal>datetime_format</literal> settings</link> of FreeMarker.
Use this built-in only at the places where the desired format
differs from the one normally used. For the other places the
default format should be set properly by the programmers, outside
the templates.</para>
</note>
<para>The desired format can be specified like
<literal>?string.<replaceable>format</replaceable></literal> or
<literal>?string["<replaceable>format</replaceable>"]</literal>(or
the historical equivalent,
<literal>?string("<replaceable>format</replaceable>")</literal>).
These are equivalent, except that with the quoted formats you can
include any characters in the
<literal><replaceable>format</replaceable></literal>, like spaces.
The syntax of <literal><replaceable>format</replaceable></literal>
is exactly the same as of the <literal>date_format</literal>,
<literal>time_format</literal> and
<literal>datetime_format</literal> configuration settings; <link
linkend="topic.dateTimeFormatSettings">see the documentation of the
possible values there</link>.</para>
<para>Example: If the locale of the output is U.S. English, and the
time zone is the U.S. Pacific Time zone, and
<literal>openingTime</literal> is a
<literal>java.sql.Time</literal>, <literal>nextDiscountDay</literal>
is <literal>java.sql.Date</literal> and
<literal>lastUpdated</literal> is
<literal>java.sql.Timestamp</literal> or
<literal>java.util.Date</literal> then this:</para>
<programlisting role="template">&lt;#-- Predefined format names: --&gt;
${openingTime?string.short}
${openingTime?string.medium}
${openingTime?string.long}
${openingTime?string.full}
${openingTime?string.xs} &lt;#-- XSD xs:time --&gt;
${openingTime?string.iso} &lt;#-- ISO 8601 time --&gt;
${nextDiscountDay?string.short}
${nextDiscountDay?string.medium}
${nextDiscountDay?string.long}
${nextDiscountDay?string.full}
${nextDiscountDay?string.xs} &lt;#-- XSD xs:date --&gt;
${nextDiscountDay?string.iso} &lt;#-- ISO 8601 date --&gt;
${lastUpdated?string.short}
${lastUpdated?string.medium}
${lastUpdated?string.long}
${lastUpdated?string.full}
${lastUpdated?string.medium_short} &lt;#-- medium date, short time --&gt;
${lastUpdated?string.xs} &lt;#-- XSD xs:dateTime --&gt;
${lastUpdated?string.iso} &lt;#-- ISO 8601 combined date and time --&gt;
&lt;#-- <link linkend="pgui_config_custom_formats">Programmer-defined named format</link> (@ + name): --&gt;
${lastUpdated?string.@fileDate}
&lt;#-- Advanced ISO 8601 and XSD formatting: --&gt;
${lastUpdated?string.iso_m_u}
${lastUpdated?string.xs_ms_nz}
&lt;#-- SimpleDateFormat patterns: --&gt;
${lastUpdated?string["dd.MM.yyyy, HH:mm"]}
${lastUpdated?string["EEEE, MMMM dd, yyyy, hh:mm a '('zzz')'"]}
${lastUpdated?string["EEE, MMM d, ''yy"]}
${lastUpdated?string.yyyy} &lt;#-- Same as ${lastUpdated?string["yyyy"]} --&gt;
</programlisting>
<para>will print something like this:</para>
<programlisting role="output">01:45 PM
01:45:09 PM
01:45:09 PM PST
01:45:09 PM PST
13:45:09-08:00
13:45:09-08:00
2/20/07
Apr 20, 2007
April 20, 2007
Friday, April 20, 2007
2007-02-20-08:00
2007-02-20
2/20/07 01:45 PM
Feb 20, 2007 01:45:09 PM
February 20, 2007 01:45:09 PM PST
Friday, February 20, 2007 01:45:09 PM PST
Feb 8, 2003 9:24 PM
2007-02-20T13:45:09-08:00
2007-02-20T13:45:09-08:00
Apr/20/2007 13:45
2007-02-20T21:45Z
2007-02-20T13:45:09.000
08.04.2003 21:24
Tuesday, April 08, 2003, 09:24 PM (PDT)
Tue, Apr 8, '03
2003</programlisting>
<para>Note that with custom formats like in
<literal>lastUpdated?string.@fileDate</literal> above, templates can
just refer to the application-domain meaning, and the exact format
can be specified outside the templates, on a central place.
(Programmers can read about <link
linkend="pgui_config_custom_formats">defining such named formats
here...</link>)</para>
<warning>
<para>Unfortunately, because of the limitations of the Java
platform, it can happen that you have date-like variables in the
data-model, where FreeMarker can't decide if the variable is a
date (year, month, day), or a time (hour, minute, second,
millisecond) or a date-time. In this case, FreeMarker doesn't know
how to display the value when you write something like
<literal>${lastUpdated?string.short}</literal> or
<literal>${lastUpdated?string.xs}</literal>, i.e., a format that
doesn't specify the exact fields to display, or if you simply use
<literal>${lastUpdated}</literal>. Then it will have to stop with
error. To prevent this, you can help FreeMarker with the <link
linkend="ref_builtin_date_datetype"><literal>?date</literal>,
<literal>?time</literal> and <literal>?datetime</literal>
built-ins</link>. For example:
<literal>${lastUpdated?datetime?string.short}</literal>. Ask the
programmers if certain variables of the data-model have this
problem, or always use <literal>?date</literal>,
<literal>?time</literal> and <literal>?datetime</literal>
built-ins to be on the safe side.</para>
</warning>
<note>
<para>You never need to use <literal>?date</literal>,
<literal>?time</literal> or <literal>?datetime</literal> with
format patterns like <literal>"yyyy.MM.dd HH:mm"</literal>, since
with the pattern you tell FreeMarker what parts of the date to
show. However, FreeMarker will trust you blindly, so you can show
"noise" if you display parts that are actually not stored in the
variable. For example, <literal>${openingTime?string["yyyy-MM-dd
hh:mm:ss a"]}</literal>, where <literal>openingTime</literal>
stores only time, will display <literal>1970-01-01 09:24:44
PM</literal>.</para>
</note>
<para>To prevent misunderstandings, the format need not be a string
literal, it can be a variable or any other expression as far as it
evaluates to a string. For example, it can be like
<literal>"<replaceable>...</replaceable>"?string[myFormat]</literal>.</para>
<para>See also: <link
linkend="dgui_template_valueinserion_universal_date">the
interpolation of dates</link></para>
</section>
</section>
<section xml:id="ref_builtins_boolean">
<title>Built-ins for booleans</title>
<indexterm>
<primary>boolean</primary>
<secondary>built-ins</secondary>
</indexterm>
<section xml:id="ref_builtin_c_boolean">
<title>c (when used with boolean)</title>
<indexterm>
<primary>c built-in</primary>
</indexterm>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>boolean</secondary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.20.</para>
</note>
<para>This built-in converts a boolean to string for a
<quote>computer language</quote> as opposed to for human audience.
The result will be <literal>"true"</literal> or
<literal>"false"</literal>, regardless of the
<literal>boolean_format</literal> configuration setting, as that
setting is meant to specify the format for human consumption. When
generating boolean literals for JavaScript and such, this should be
used.</para>
<para>If you only generate output that's computer language and isn't
read by end-users, you may want to set the
<literal>boolean_format</literal> configuration setting to
<literal>c</literal> (since FreeMarker 2.3.29), in which case
<literal>${<replaceable>aBoolean</replaceable>}</literal> will have
the same output as
<literal>${<replaceable>aBoolean</replaceable>?c}</literal>.</para>
<para>Note that this built-in <link linkend="ref_builtin_c">also
works on strings</link>.</para>
</section>
<section xml:id="ref_builtin_string_for_boolean">
<title>string (when used with a boolean value)</title>
<indexterm>
<primary>boolean</primary>
<secondary>printing</secondary>
</indexterm>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>string built-in</primary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>boolean</secondary>
</indexterm>
<para>Converts a boolean to a string. You can use it in two
ways:</para>
<itemizedlist>
<listitem>
<para>As <literal>foo?string("yes", "no")</literal>: Formats the
boolean value to the first parameter (here:
<literal>"yes"</literal>) if the boolean is true, and to the
second parameter (here: <literal>"no"</literal>) if it's false.
Unless you only meant to format a boolean with simple literals,
use <link
linkend="ref_builtin_then"><literal>?then(<replaceable>whenTrue</replaceable>,
<replaceable>whenFalse</replaceable>)</literal></link> instead,
as that has less type limitations, and it evaluate its
parameters lazily! The return value of
<literal>?string</literal> is always a string (unlike for
<literal>?then</literal>), because if the parameters aren't
strings, they will be converted to strings. Also note that both
parameters are evaluated (unlike for <literal>?then</literal>),
despite that only one of them will be used; this might has
negative impact if the parameters aren't just literals.</para>
</listitem>
<listitem>
<para><literal>foo?string</literal>: <emphasis>Deprecated
starting from FreeMarker 2.3.20: use <link
linkend="ref_builtin_c_boolean"><literal>?c</literal></link>
instead, or set the <literal>boolean_format</literal> <link
linkend="ref_directive_setting">setting</link> to something like
<literal>"yes,no"</literal> and then the conversion can happen
automatically</emphasis>. If you still need to know about this,
this will convert the boolean to string using the default
strings for representing true and false values. By default, true
is rendered as <literal>"true"</literal> and false is rendered
as <literal>"false"</literal>. This is mostly only useful if you
generate source code with FreeMarker <emphasis>(but use
<literal>?c</literal> for that starting from 2.3.20)</emphasis>.
To change these default strings, you can use the
<literal>boolean_format</literal> <link
linkend="ref_directive_setting">setting</link>.</para>
<para role="forProgrammers">Note that in the very rare case when
a value is multi-typed and is both a boolean and a string, then
the string value of the variable will be returned, and so the
<literal>boolean_format</literal> setting will have no
effect.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_builtin_then">
<title>then</title>
<indexterm>
<primary>then built-in</primary>
</indexterm>
<indexterm>
<primary>ternary operator</primary>
</indexterm>
<indexterm>
<primary>format; boolean</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.23.</para>
</note>
<para>Used like
<literal><replaceable>booleanExp</replaceable>?then(<replaceable>whenTrue</replaceable>,
<replaceable>whenFalse</replaceable>)</literal>, fills the same role
as the ternary operator in C-like languages (i.e.,
<literal><replaceable>booleanExp</replaceable> ?
<replaceable>whenTrue</replaceable> :
<replaceable>whenFalse</replaceable></literal>). If
<literal><replaceable>booleanExp</replaceable></literal> evaluates
to boolean true then it evaluates and returns its first argument, or
else if <literal><replaceable>booleanExp</replaceable></literal>
evaluates to boolean false then it evaluates and return its second
argument. Off course, all three expression can be arbitrary complex.
The argument expressions can have any type, even different
types.</para>
<para>An important special property of this built-in is that only
one of the argument expressions will be evaluated. This is unlike
with normal method calls, where all argument expressions are
evaluated, regardless if the method will need them. This also means
that the argument that's not needed can even refer to missing
variables without causing error. (It still can't be syntactically
invalid of course.)</para>
<para>Example:</para>
<programlisting role="template">&lt;#assign foo = true&gt;
${foo?then('Y', 'N')}
&lt;#assign foo = false&gt;
${foo?then('Y', 'N')}
&lt;#assign x = 10&gt;
&lt;#assign y = 20&gt;
&lt;#-- Prints 100 plus the maximum of x and y: --&gt;
${100 + (x &gt; y)?then(x, y)}</programlisting>
<programlisting role="output">Y
N
120</programlisting>
<note>
<para>If you need to choose based on a non-boolean value, you
should use the <link
linkend="ref_builtin_switch"><literal>switch</literal>
built-in</link> instead of nesting multiple
<literal>then</literal>-s into each other, like
<literal>priority?switch(1, "low", 2, "medium", 3,
"high")</literal>, or even <literal>true?switch(priority &lt;= 1,
"low", priority == 2, "medium", priority &gt;= 3,
"high")</literal>.</para>
</note>
</section>
</section>
<section xml:id="ref_builtins_sequence">
<title>Built-ins for sequences</title>
<indexterm>
<primary>sequence</primary>
<secondary>built-ins</secondary>
</indexterm>
<section xml:id="ref_builtin_chunk">
<title>chunk</title>
<indexterm>
<primary>chunk built-in</primary>
</indexterm>
<indexterm>
<primary>tabular printing of sequences</primary>
</indexterm>
<indexterm>
<primary>columnar printing of sequences</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.3.</para>
</note>
<para>This built-in splits a sequence into multiple sequences of the
size given with the 1st parameter to the built-in (like
<literal>mySeq?chunk(3)</literal>). The result is the sequence of
these sequences. The last sequence is possibly shorter than the
given size, unless the 2nd parameter is given (like
<literal>mySeq?chunk(3, '-')</literal>), that is the item used to
make up the size of the last sequence to the given size.
Example:</para>
<programlisting role="template">&lt;#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']&gt;
&lt;#list seq?chunk(4) as row&gt;
&lt;#list row as cell&gt;${cell} &lt;/#list&gt;
&lt;/#list&gt;
&lt;#list seq?chunk(4, '-') as row&gt;
&lt;#list row as cell&gt;${cell} &lt;/#list&gt;
&lt;/#list&gt;</programlisting>
<para>The output will be:</para>
<programlisting role="output">
a b c d
e f g h
i j
a b c d
e f g h
i j - -
</programlisting>
<para>This built in is mostly for outputting sequnces in
tabular/columnar format. When used with HTML tables, the 2nd
parameter is often <literal>"\xA0"</literal> (that is the code of
the no-break space character, also known as <quote>nbsp</quote>), so
the border of the empty TD-s will not be missing.</para>
<para>The 1st parameter must be a number that is at least 1. If the
number is not integer, it will be silently rounded down to integer
(i.e. both 3.1 and 3.9 will be rounded to 3). The 2nd parameter can
be of any type and value.</para>
</section>
<section xml:id="ref_builtin_drop_while">
<title>drop_while</title>
<indexterm>
<primary>drop_while built-in</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>drop while</secondary>
</indexterm>
<para>Returns a new sequence that contains the elements from the
input sequence starting with from the first element that does
<emphasis>not</emphasis> match the parameter predicate (condition).
After that, all elements are included, regardless if they match the
predicate or not. See the <link
linkend="ref_builtin_filter"><literal>filter</literal>
built-in</link> for more details about parameters, and other
details, but note that the condition in <literal>filter</literal>
has opposite meaning (what to keep, instead of what to drop).</para>
<para>Example and comparison with <literal>filter</literal>:</para>
<programlisting role="template">&lt;#assign xs = [1, 2, -3, 4, -5, 6]&gt;
Drop while positive:
&lt;#list xs?drop_while(x -&gt; x &gt; 0) as x&gt;${x} &lt;/#list&gt;
Filer for positives:
&lt;#list xs?filter(x -&gt; x &gt; 0) as x&gt;${x} &lt;/#list&gt;</programlisting>
<programlisting role="output">Drop while positive:
-3 4 -5 6
Filer for positives:
1 2 4 6 </programlisting>
<para>As you can see, <literal>drop_while</literal> has stopped
dropping the elements once it ran into the first element that didn't
match the predicate (<literal>x &gt; 0</literal>). On the other
hand, <literal>filter</literal> keeps the elements that match the
same predicate, and it doesn't stop.</para>
<para>See also: <link
linkend="ref_builtin_take_while"><literal>take_while</literal>
built-in</link></para>
</section>
<section xml:id="ref_builtin_filter">
<title>filter</title>
<indexterm>
<primary>filter built-in</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>filter</secondary>
</indexterm>
<note>
<para>This built-in is available since 2.3.29</para>
</note>
<para>Returns a new sequence that only contains the elements for
which the parameter condition (the predicate) returns
<literal>true</literal>. For example:</para>
<programlisting role="template">&lt;#assign xs = [1, -2, 3, 4, -5]&gt;
Positives:
&lt;#list xs?<emphasis>filter(x -&gt; x &gt; 0)</emphasis> as x&gt;${x} &lt;/#list&gt;
Negatives:
&lt;#list xs?<emphasis>filter(x -&gt; x &lt; 0)</emphasis> as x&gt;${x} &lt;/#list&gt;</programlisting>
<programlisting role="output">Positives:
1 3 4
Negatives:
-2 -5 </programlisting>
<para>This built-in has a single required parameter, the predicate
(filter condition, what to keep). The predicate can be specified in
3 ways:</para>
<itemizedlist>
<listitem>
<para>As a single argument <link
linkend="dgui_template_exp_lambda">lambda expression</link>:
<literal><replaceable>element</replaceable> -&gt;
<replaceable>predicate</replaceable></literal>. In that,
<literal><replaceable>element</replaceable></literal> is the
variable name with which you can refer to the current element in
the <literal><replaceable>predicate</replaceable></literal>, and
the <literal><replaceable>predicate</replaceable></literal> is
an arbitrarily complex <link
linkend="dgui_template_exp">expression</link> that must return a
boolean value (<literal>true</literal> or
<literal>false</literal>). An example this was shown above. Note
again the predicates can be arbitrarily complex, like the
predicate in <literal>products?filter(product -&gt;
product.discounted &amp;&amp;
!user.hasBought(product))</literal>.</para>
</listitem>
<listitem>
<para>As a <link
linkend="ref_directive_function">function</link> or method that
has a single argument, and returns boolean. For example, the
<quote>Negatives</quote> example above could be implemented like
this:</para>
<programlisting role="template">&lt;#function negative(x)&gt;
&lt;#return x &lt; 0&gt;
&lt;/#function&gt;
<replaceable>...</replaceable>
Negatives:
&lt;#list xs<emphasis>?filter(negative)</emphasis> as x&gt;${x} &lt;/#list&gt;</programlisting>
<para>Note how we just referred to the function by name, and did
not call it. Similarly, if you have a Java object called
<literal>utils</literal> in the data-model, and it has a
<literal>boolean isNegative(Number n)</literal> method, then you
could use that like
<literal>xs?filter(utils.isNegative)</literal>.</para>
</listitem>
</itemizedlist>
<note>
<para>Remember, the condition (predicate) that you specify tells
<emphasis>what to keep</emphasis>, not what to filter out! That
is, the element will be in the result sequence when you return
<literal>true</literal>, not when you return
<literal>false</literal>. (It's like the <literal>WHERE</literal>
condition in SQL, if you know that.)</para>
</note>
<para>While <literal>filter</literal> is most often used in the
<link linkend="ref.directive.list"><literal>list</literal>
directive</link>, naturally it can be used anywhere where a filtered
sequence is needed, and so this works as well:</para>
<programlisting role="template">&lt;#assign negatives = xs?filter(x -&gt; x &lt; 0)&gt;
Negatives:
&lt;#list negatives as x&gt;${x} &lt;/#list&gt;</programlisting>
<para>Note however, that for a very long sequences, the above
solution can consume significantly more memory. That's because
<literal>&lt;list
<replaceable>seq</replaceable>?filter(<replaceable>pred</replaceable>)
<replaceable>...</replaceable>&gt;</literal> is optimized to do
filtering without building an intermediate filtered sequence, while
the n above example, <literal>assign</literal> will first build the
whole filtered sequence in memory, and we pass that filtered
sequence later to <literal>list</literal>. But again, this only
matters for very long sequences.</para>
<para>See also: <link
linkend="ref_builtin_take_while"><literal>take_while</literal>
built-in</link>, <link
linkend="ref_builtin_drop_while"><literal>drop_while</literal>
built-in</link></para>
<simplesect xml:id="topic.filterLazyEval">
<title>Lazy evaluation and its consequences</title>
<note>
<para>Identical rules apply to these built-ins as well: <link
linkend="ref_builtin_map"><literal>map(<replaceable>mapper</replaceable>)</literal></link>,
<link
linkend="ref_builtin_take_while"><literal>take_while(<replaceable>predicate</replaceable>)</literal></link>,
<link
linkend="ref_builtin_drop_while"><literal>drop_while(<replaceable>predicate</replaceable>)</literal></link>.</para>
</note>
<para>To optimize processing, <literal>filter</literal> might
delays fetching the elements of the input sequence, and applying
the predicate on them. But it's guaranteed that those operations
are not delayed past the point where the execution of the
directive or interpolation, whose parameter contains the
<literal><replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)</literal>,
is finished. Some examples:</para>
<itemizedlist>
<listitem>
<para>In the case of <literal>&lt;list
<replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)
<replaceable>...</replaceable>&gt;<replaceable>nested
content</replaceable>&lt;/#list&gt;</literal>, when the
execution enters the <literal><replaceable>nested
content</replaceable></literal>, it's not true that all
elements of <literal><replaceable>seq</replaceable></literal>
was already consumed and filtered. Consuming and filtering
<literal><replaceable>seq</replaceable></literal> is instead
done bit by bit as <literal>list</literal> repeats the nested
content. But it's guaranteed that past the
<literal>&lt;/#list&gt;</literal> tag (the end of the
execution of the <literal>list</literal> directive), there are
no delayed readings of
<literal><replaceable>seq</replaceable></literal>, or delayed
evaluation of the
<literal><replaceable>predicate</replaceable></literal>. So
avoid changing a such variable (or other system state) in the
nested content of <literal>list</literal>, which influences
the result of the
<literal><replaceable>predicate</replaceable></literal>. Doing
so could change the filtering for the rest of the
<literal><replaceable>seq</replaceable></literal>.</para>
</listitem>
<listitem>
<para>In the case of <literal>&lt;#assign
<replaceable>filteredSeq</replaceable> =
<replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)&gt;</literal>
it's guaranteed that all elements of
<literal><replaceable>seq</replaceable></literal> were
processed, and thus
<literal><replaceable>predicate</replaceable></literal> won't
be evaluated after the <literal>assign</literal>
directive.</para>
</listitem>
<listitem>
<para>In the case of
<literal>${<replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)?join(',
')}</literal> it's guaranteed that all elements of
<literal><replaceable>seq</replaceable></literal> were
processed, and thus
<literal><replaceable>predicate</replaceable></literal> won't
be evaluated after the <literal>assign</literal>
directive.</para>
</listitem>
</itemizedlist>
<para>Inside <link linkend="dgui_template_exp">expressions</link>
however, there's no promise regarding when the elements are
consumed and when the predicate is evaluated. Like in the case of
<literal><replaceable>seq</replaceable>?filter(<replaceable>predicate1</replaceable>)?filter(<replaceable>predicate2</replaceable>)</literal>,
it's not guaranteed that
<literal><replaceable>predicate1</replaceable></literal> will only
be evaluated before
<literal><replaceable>predicate2</replaceable></literal>. (Most
likely they will be called alternately:
<literal><replaceable>predicate1</replaceable></literal> for the
1st element, then
<literal><replaceable>predicate2</replaceable></literal> for the
1st element, then
<literal><replaceable>predicate1</replaceable></literal> for the
2nd element, then
<literal><replaceable>predicate2</replaceable></literal> for the
2nd element, and so on.)</para>
<para>If you pass a filtered sequence to a
<emphasis>custom</emphasis> directive (a macro) or function or
method, as in <literal>&lt;@<replaceable>myMacro</replaceable>
<replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)
/&gt;</literal> or
<literal><replaceable>myFunction</replaceable>(<replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>))</literal>,
then it's guaranteed that the filtering is not delayed past the
point when the custom directive/function/method is invoked. That
is, your macro/function/method will aways receive a fully
constructed filtered sequence.</para>
<para>Also note that in it's <emphasis>not</emphasis> guaranteed
that all elements of the input sequence will be read, and
therefore that the predicate will be evaluated for all elements.
Some examples of such cases:</para>
<itemizedlist>
<listitem>
<para>You may <link
linkend="ref.directive.list.break"><literal>break</literal></link>
out from <literal>&lt;list
<replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)
<replaceable>...</replaceable>&gt;</literal> before it reaches
the last element, in which case the rest of the
<literal><replaceable>seq</replaceable></literal> elements
won't be fetched and filtered.</para>
</listitem>
<listitem>
<para>In the case of
<literal><replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)[2]</literal>,
which reads the 3rd element of the filtered sequence,
FreeMarker stops fetching and filtering the elements of
<literal><replaceable>seq</replaceable></literal> when we have
found the 3rd element that matches the
<literal><replaceable>predicate</replaceable></literal>.</para>
</listitem>
<listitem>
<para>In the case of
<literal><replaceable>seq</replaceable>?filter(<replaceable>predicate</replaceable>)?size
!= 0</literal>, which tells whether the filtered sequence is
non-empty, we stop fetching and filtering the elements of
<literal><replaceable>seq</replaceable></literal> when we have
found the 1st element that matches the
<literal><replaceable>predicate</replaceable></literal>.
(That's certainly surprising as <literal>?size</literal> needs
to process the whole sequence to tell the size. But in this
case FreeMarker notices that we don't really need the exact
size.)</para>
</listitem>
</itemizedlist>
<para>If you are a Java programmer, note how the
<literal>filter</literal> built-in differs from Java
<literal>Stream.filter</literal>. <literal>Stream.filter</literal>
is <quote>lazy</quote>, while FreeMarker <literal>filter</literal>
is basically <quote>eager</quote>, and is only <quote>lazy</quote>
in special cases, and within a limited scope. Thus, unlike in
Java, calling <literal>filter</literal> is not always free. In
particular, if you assign a filtered sequence to a variable, or
pass it to a custom directive/function/method, the filtered
sequence will be created eagerly.</para>
</simplesect>
<simplesect xml:id="topic.filterLongInput">
<title>Filtering very long input that you don't hold in
memory</title>
<note>
<para>Identical rules apply to these built-ins as well: <link
linkend="ref_builtin_map"><literal>map(<replaceable>mapper</replaceable>)</literal></link>,
<link
linkend="ref_builtin_take_while"><literal>take_while(<replaceable>predicate</replaceable>)</literal></link>,
<link
linkend="ref_builtin_drop_while"><literal>drop_while(<replaceable>predicate</replaceable>)</literal></link>.</para>
</note>
<para>Some applications, particularly those that render huge
tables, use <link linkend="dgui_datamodel_container">sequence-like
values</link> in the data-model that are not held in memory at
once, instead they are like a stream of elements that you can only
read in the order as they are given to you (on the Java side these
are <literal>java.util.Iterator</literal>-s, or
<literal>java.util.Iterables</literal>, or the like). These will
have <quote>collection</quote> type in the template language,
which is like a restricted sequence.</para>
<para><literal>filter</literal> works with collection input too.
As you have seen earlier, <literal>filter</literal> might stores
the entire filtered sequence in the memory, which in this case
sounds concerning, because if the input was too big to fit into
the memory (hence it wasn't exposed as a sequence), then the
filtered collection can be too big as well. For that reason, if
the input is not a sequence (but a collection),
<literal>filter</literal> never collects its result into the
memory, and never fetches and processes the input elements until
they are really needed (<quote>lazy</quote> behavior). Furthermore
the result of <literal>filter</literal> is then a collection, not
a sequence, therefor sequence operations (like
<literal><replaceable>seq</replaceable>[<replaceable>index</replaceable>]</literal>)
will not work on it.</para>
<para>Unlike with sequence input, any operation that would cause
collecting the whole filtered result into the memory will now
fail. Let's see that through examples. Let's say we have
<literal>hugeTable</literal> in the data-model, which is not a
sequence, but still a collection (probably an
<literal>Iterator</literal> in Java). Then, consider:</para>
<programlisting role="template">&lt;#-- Works: --&gt;
&lt;#list hugeTable?filter(<replaceable>predicate</replaceable>) as row&gt;<replaceable>nested content</replaceable>&lt;/#list&gt;</programlisting>
<para>This works fine, since <literal>list</literal> doesn't
require collecting the result into the memory</para>
<para>Consider this:</para>
<programlisting role="template">&lt;#-- Fails if hugeTable is not a sequence, just a collection: --&gt;
&lt;#assign filteredHugeTable = hugeTable?filter(<replaceable>predicate</replaceable>)&gt;</programlisting>
<para>This fails, as filtering can't be postponed beyond the
containing directive (<literal>assign</literal>), so FreeMareker
had to put the entire filtered result into
<literal>filteredHugeTable</literal>. If, however, you know that
<literal>filteredHugeTable</literal> won't be too big, you can
explicitly collect the result into a sequence via the <link
linkend="ref_builtin_sequence"><literal>sequence</literal>
built-in</link>:</para>
<programlisting role="template">&lt;#-- Works, but be sure filtredHugeTable fits into the memory: --&gt;
&lt;#assign filteredHugeTable = hugeTable?filter(predicate)<emphasis>?sequence</emphasis>&gt;</programlisting>
<para>Naturally, applying the <literal>sequence</literal> built-in
allows all sequence operations, such as
<literal><replaceable>seq</replaceable>[<replaceable>index</replaceable>]</literal>,
<literal><replaceable>seq</replaceable>[<replaceable>range</replaceable>]</literal>,
or
<literal><replaceable>seq</replaceable>?<replaceable>size</replaceable></literal>.
If these operations are directly applied on a sequence that was
converted from a collection, then FreeMarker optimizes out
actually creating the sequence in memory. So these won't consume
much memory regardless of the size of the filtered
<literal>hugeTable</literal>:</para>
<itemizedlist>
<listitem>
<para><literal>hugeTable?filter(<replaceable>predicate</replaceable>)?sequence[index]</literal>:
FreeMarker will just fetch and drop the elements till it
reaches the element at the desired position.</para>
</listitem>
<listitem>
<para><literal>hugeTable?filter(<replaceable>predicate</replaceable>)?sequence[0..9]</literal>:
FreeMarker will just collect the first 10 elements.</para>
</listitem>
<listitem>
<para><literal>hugeTable?filter(<replaceable>predicate</replaceable>)?sequence?size</literal>:
In this case the whole <literal>hugeTable</literal> will be
fetched, which is possibly slow, but the fetched elements are
still not collected into the memory, as they only need to be
counted.</para>
</listitem>
</itemizedlist>
</simplesect>
<simplesect xml:id="topic.filterMissing">
<title>Filtering missing (null) values</title>
<para>The argument to a lambda expression can hold the missing
(Java <literal>null</literal>) value, and reading such value will
not fall back to a higher scope. Thus, something like
<literal>seq?filter(it -&gt; it??)</literal>, which filters out
missing element from the sequence, will work reliably.</para>
</simplesect>
</section>
<section xml:id="ref_builtin_first">
<title>first</title>
<indexterm>
<primary>first built-in</primary>
</indexterm>
<para>Returns the first item of the sequence. Thus
<literal><replaceable>value</replaceable>?first</literal> is the
same as <literal><replaceable>value</replaceable>[0]</literal>,
except that, since FreeMarker 2.3.26,
<literal><replaceable>value</replaceable>?first</literal> also works
if <literal><replaceable>value</replaceable></literal> doesn't
support getting items with numerical index, but still supports to be
listed (i.e., with FTL collection values).</para>
<para>If the sequence or collection is empty, the result will be a
missing value (as in
<literal><replaceable>empty</replaceable>?first!'No item was
found'</literal>).</para>
</section>
<section xml:id="ref_builtin_join">
<title>join</title>
<indexterm>
<primary>join built-in</primary>
</indexterm>
<para>Concatenates the items of a sequence to a single string, with
the given separator. For example:</para>
<programlisting role="template">&lt;#assign colors = ["red", "green", "blue"]&gt;
${colors?join(", ")}</programlisting>
<para>will output:</para>
<programlisting role="output">red, green, blue</programlisting>
<para>Sequence items that are not strings will be converted to
string with the same conversion rules as of
<literal>${<replaceable>...</replaceable>}</literal> (except, of
course, no automatic escaping is applied at this stage).</para>
<para><literal>?join(<replaceable>...</replaceable>)</literal> can
have up to 3 parameters:</para>
<orderedlist>
<listitem>
<para>Separator, required: The string that is inserted between
items</para>
</listitem>
<listitem>
<para>Empty value, defaults to <literal>""</literal> (empty
string): The value used if the sequence contains no
items.</para>
</listitem>
<listitem>
<para>List ending, defaults to <literal>""</literal> (empty
string): The value printed after the last value, if the list
sequence wasn't empty.</para>
</listitem>
</orderedlist>
<para>So this (where <literal>[]</literal> means an empty
sequence):</para>
<programlisting role="template">${colors?join(", ", "-")}
${[]?join(", ", "-")}
${colors?join(", ", "-", ".")}
${[]?join(", ", "-", ".")}</programlisting>
<para>will output:</para>
<programlisting role="output">red, green, blue
-
red, green, blue.
-</programlisting>
<para role="forProgrammers">Sequences coming from Java might contain
<literal>null</literal> values. Those values will be ignored by this
built-in, exactly like if they were removed from the list.</para>
</section>
<section xml:id="ref_builtin_last">
<title>last</title>
<indexterm>
<primary>last built-in</primary>
</indexterm>
<para>The last subvariable of the sequence. Template processing will
die with error if the sequence is empty.</para>
</section>
<section xml:id="ref_builtin_map">
<title>map</title>
<indexterm>
<primary>map built-in</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>filter</secondary>
</indexterm>
<para>Returns an new sequence where all elements are replaced with
the result of the parameter lambda, function, or method. For
example, you have a list of user objects in
<literal>users</literal>, but instead you need a list of user names
in variable, then you could do this:</para>
<programlisting role="template">&lt;#assign userNames = users?map(user -&gt; user.name)&gt;</programlisting>
<para>The parameter work like the parameter of the with <link
linkend="ref_builtin_filter"><literal>filter</literal>
built-in</link> (so see there), except that the
lambda/function/method you specify can return values of any
type.</para>
<para>Regarding lazy evaluation, and handling of very long inputs,
it also <link linkend="topic.filterLazyEval">works on the same
way</link> as the <link
linkend="ref_builtin_filter"><literal>filter</literal>
built-in</link>.</para>
</section>
<section xml:id="ref_builtin_min_max">
<title>min, max</title>
<indexterm>
<primary>min built-in</primary>
</indexterm>
<indexterm>
<primary>max built-in</primary>
</indexterm>
<para>Returns the smaller (<literal>min</literal>) or greatest
(<literal>max</literal>) item of the sequence (or collection). The
items must be either all numbers, or all date/time values of the
same kind (date-only, time-only, date-time), or else a comparison
error will occur. These are the same restrictions as for the <link
linkend="dgui_template_exp_comparison"><literal>&lt;</literal> and
<literal>&gt;</literal> operators</link>.</para>
<para>Missing items (i.e., Java <literal>null</literal>-s) will be
silently ignored. If the sequence is empty or it only contains
missing (Java <literal>null</literal>) items, the result itself will
be missing.</para>
<para>Example:</para>
<programlisting role="template">${[1, 2, 3]?min}
${[1, 2, 3]?max}
${[]?min!'-'}</programlisting>
<programlisting role="output">1
3
-</programlisting>
</section>
<section xml:id="ref_builtin_reverse">
<title>reverse</title>
<indexterm>
<primary>reverse built-in</primary>
</indexterm>
<para>The sequence with reversed order.</para>
</section>
<section xml:id="ref_builtin_seq_contains">
<title>seq_contains</title>
<indexterm>
<primary>seq_contains built-in</primary>
</indexterm>
<note>
<para>The <literal>seq_</literal> prefix is required in the
built-in name to differentiate it from the <link
linkend="ref_builtin_contains"><literal>contains</literal>
built-in</link> that searches a substring in a string (since a
variable can be both string and sequence on the same time).</para>
</note>
<para>Tells if the sequence contains the specified value (according
the <link
linkend="dgui_template_exp_comparison"><literal>==</literal>
operator</link> of the template language, not according Java's
<literal>Object.equals</literal>). It has 1 parameter, the value to
find. Example:</para>
<programlisting role="template">&lt;#assign x = ["red", 16, "blue", "cyan"]&gt;
"blue": ${x?seq_contains("blue")?string("yes", "no")}
"yellow": ${x?seq_contains("yellow")?string("yes", "no")}
16: ${x?seq_contains(16)?string("yes", "no")}
"16": ${x?seq_contains("16")?string("yes", "no")}</programlisting>
<para>The output will be:</para>
<programlisting role="output">"blue": yes
"yellow": no
16: yes
"16": no</programlisting>
<para>To find the value the built-in uses FreeMarker's comparison
rules (as if you was using <link
linkend="dgui_template_exp_comparison"><literal>==</literal>
operator</link>), except that comparing two values of different
types or of types for which FreeMarker doesn't support comparison
will not cause error, just will be evaluated as the two values are
not equal. Thus, you can use it only to find scalar values (i.e.
string, number, boolean or date/time values). For other types the
result will be always <literal>false</literal>.</para>
<para>For fault tolerance, this built-in also works with
collections.</para>
</section>
<section xml:id="ref_builtin_seq_index_of">
<title>seq_index_of</title>
<indexterm>
<primary>seq_index_of built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.1. It
doesn't exist in 2.3.</para>
</note>
<note>
<para>The <literal>seq_</literal> prefix is required in the
built-in name to differentiate it from the <link
linkend="ref_builtin_index_of"><literal>index_of</literal>
built-in</link> that searches a substring in a string (since a
variable can be both string and sequence on the same time).</para>
</note>
<para>Returns the index of the first occurrence of a value in the
sequence, or <literal>-1</literal> if the sequence doesn't contain
the specified value. The value to find is specified as the first
parameter. For example this template:</para>
<programlisting role="template">&lt;#assign colors = ["red", "green", "blue"]&gt;
${colors?seq_index_of("blue")}
${colors?seq_index_of("red")}
${colors?seq_index_of("purple")}</programlisting>
<para>will output this:</para>
<programlisting role="output">2
0
-1</programlisting>
<para>To find the value the built-in uses FreeMarker's comparison
rules (as if you was using <link
linkend="dgui_template_exp_comparison"><literal>==</literal>
operator</link>), except that comparing two values of different
types or of types for which FreeMarker doesn't support comparison
will not cause error, just will be evaluated as the two values are
not equal. Thus, you can use it only to find scalar values (i.e.
string, number, boolean or date/time values). For other types the
result will be always <literal>-1</literal>.</para>
<para>The index where the searching is started can be optionally
given as the 2nd parameter. This may be useful if the same item can
occur for multiple times in the same sequence. There is no
restriction on the numerical value of the second parameter: if it is
negative, it has the same effect as if it were zero, and if it is
greater than the length of the sequence, it has the same effect as
if it were equal to the length of the sequence. Decimal values will
be truncated to integers. For example:</para>
<programlisting role="template">&lt;#assign names = ["Joe", "Fred", "Joe", "Susan"]&gt;
No 2nd param: ${names?seq_index_of("Joe")}
-2: ${names?seq_index_of("Joe", -2)}
-1: ${names?seq_index_of("Joe", -1)}
0: ${names?seq_index_of("Joe", 0)}
1: ${names?seq_index_of("Joe", 1)}
2: ${names?seq_index_of("Joe", 2)}
3: ${names?seq_index_of("Joe", 3)}
4: ${names?seq_index_of("Joe", 4)}</programlisting>
<para>will output this:</para>
<programlisting role="output">No 2nd param: 0
-2: 0
-1: 0
0: 0
1: 2
2: 2
3: -1
4: -1</programlisting>
</section>
<section xml:id="ref_builtin_seq_last_index_of">
<title>seq_last_index_of</title>
<indexterm>
<primary>seq_last_index_of built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.1. It
doesn't exist in 2.3.</para>
</note>
<note>
<para>The <literal>seq_</literal> prefix is required in the
built-in name to differentiate it from the <link
linkend="ref_builtin_last_index_of"><literal>last_index_of</literal>
built-in</link> that searches a substring in a string (since a
variable can be both string and sequence on the same time).</para>
</note>
<para>Returns the index of the last occurrence of a value in the
sequence, or <literal>-1</literal> if the sequence doesn't contain
the specified value. That is, it is the same as <link
linkend="ref_builtin_seq_index_of"><literal>seq_index_of</literal></link>,
just it searches backward starting from the last item of the
sequence. It also supports the optional 2nd parameter that specifies
the index where the searching is started. For example:</para>
<programlisting role="template">&lt;#assign names = ["Joe", "Fred", "Joe", "Susan"]&gt;
No 2nd param: ${names?seq_last_index_of("Joe")}
-2: ${names?seq_last_index_of("Joe", -2)}
-1: ${names?seq_last_index_of("Joe", -1)}
0: ${names?seq_last_index_of("Joe", 0)}
1: ${names?seq_last_index_of("Joe", 1)}
2: ${names?seq_last_index_of("Joe", 2)}
3: ${names?seq_last_index_of("Joe", 3)}
4: ${names?seq_last_index_of("Joe", 4)}</programlisting>
<para>will output this:</para>
<programlisting role="output">No 2nd param: 2
-2: -1
-1: -1
0: 0
1: 0
2: 2
3: 2
4: 2</programlisting>
</section>
<section xml:id="ref_builtin_size">
<title>size</title>
<indexterm>
<primary>size built-in</primary>
</indexterm>
<para>The number of sub variables in sequence (as a numerical
value). The highest possible index in sequence <literal>s</literal>
is <literal>s?size - 1</literal> (since the index of the first
subvariable is 0) assuming that the sequence has at least one
subvariable.</para>
</section>
<section xml:id="ref_builtin_sort">
<title>sort</title>
<indexterm>
<primary>sort built-in</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>sorting</secondary>
</indexterm>
<para>Returns the sequence sorted in ascending order. (For
descending order use this and then the <link
linkend="ref_builtin_reverse"><literal>reverse</literal> built
in</link>.) This will work only if all sub variables are strings, or
if all sub variables are numbers, or if all sub variables are date
values (date, time, or date+time), or if all sub variables are
booleans (since 2.3.17). If the sub variables are strings, it uses
locale (language) specific lexical sorting (which is usually not
case sensitive). For example:</para>
<programlisting role="template">&lt;#assign ls = ["whale", "Barbara", "zeppelin", "aardvark", "beetroot"]?sort&gt;
&lt;#list ls as i&gt;${i} &lt;/#list&gt;</programlisting>
<para>will print (with US locale at least):</para>
<programlisting role="output">aardvark Barbara beetroot whale zeppelin</programlisting>
</section>
<section xml:id="ref_builtin_sort_by">
<title>sort_by</title>
<indexterm>
<primary>sort_by built-in</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>sorting</secondary>
</indexterm>
<para>Returns the sequence of hashes sorted by the given hash
subvariable in ascending order. (For descending order use this and
then the <link
linkend="ref_builtin_reverse"><literal>reverse</literal> built
in</link>.) The rules are the same as with the <link
linkend="ref_builtin_sort"><literal>sort</literal> built-in</link>,
except that the sub variables of the sequence must be hashes, and
you have to give the name of a hash subvariable that will decide the
order. For example:</para>
<programlisting role="template">&lt;#assign ls = [
{"name":"whale", "weight":2000},
{"name":"Barbara", "weight":53},
{"name":"zeppelin", "weight":-200},
{"name":"aardvark", "weight":30},
{"name":"beetroot", "weight":0.3}
]&gt;
Order by name:
&lt;#list ls?sort_by("name") as i&gt;
- ${i.name}: ${i.weight}
&lt;/#list&gt;
Order by weight:
&lt;#list ls?sort_by("weight") as i&gt;
- ${i.name}: ${i.weight}
&lt;/#list&gt;</programlisting>
<para>will print (with US locale at least):</para>
<programlisting role="output">Order by name:
- aardvark: 30
- Barbara: 53
- beetroot: 0.3
- whale: 2000
- zeppelin: -200
Order by weight:
- zeppelin: -200
- beetroot: 0.3
- aardvark: 30
- Barbara: 53
- whale: 2000</programlisting>
<para>If the subvariable that you want to use for the sorting is on
a deeper level (that is, if it is a subvariable of a subvariable and
so on), then you can use a sequence as parameter, that specifies the
names of the sub variables that lead down to the desired
subvariable. For example:</para>
<programlisting role="template">&lt;#assign members = [
{"name": {"first": "Joe", "last": "Smith"}, "age": 40},
{"name": {"first": "Fred", "last": "Crooger"}, "age": 35},
{"name": {"first": "Amanda", "last": "Fox"}, "age": 25}]&gt;
Sorted by name.last:
&lt;#list members?sort_by(['name', 'last']) as m&gt;
- ${m.name.last}, ${m.name.first}: ${m.age} years old
&lt;/#list&gt;</programlisting>
<para>will print (with US locale at least):</para>
<programlisting role="output">Sorted by name.last:
- Crooger, Fred: 35 years old
- Fox, Amanda: 25 years old
- Smith, Joe: 40 years old</programlisting>
</section>
<section xml:id="ref_builtin_take_while">
<title>take_while</title>
<indexterm>
<primary>take_while built-in</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>take while</secondary>
</indexterm>
<para>Returns a sequence that only contains the elements of the
input sequence which are before the first element that doesn't match
the parameter predicate (filter condition). This is very similar to
the <link linkend="ref_builtin_filter"><literal>filter</literal>
built-in</link>, so see further details there.</para>
<para>Example and comparison with <literal>filter</literal>:</para>
<programlisting role="template">&lt;#assign xs = [1, 2, -3, 4, -5, 6]&gt;
Take while positive:
&lt;#list xs<emphasis>?take_while</emphasis>(x -&gt; x &gt; 0) as x&gt;${x} &lt;/#list&gt;
Filer for positives:
&lt;#list xs?filter(x -&gt; x &gt; 0) as x&gt;${x} &lt;/#list&gt;</programlisting>
<programlisting role="output">Take while positive:
1 2
Filer for positives:
1 2 4 6 </programlisting>
<para>As you can see, <literal>take_while</literal> has stopped at
the first number that didn't match the predicate (<literal>x &gt;
0</literal>), while <literal>filter</literal> has continued finding
further matches.</para>
<para>See also: <link
linkend="ref_builtin_drop_while"><literal>drop_while</literal>
built-in</link></para>
</section>
</section>
<section xml:id="ref_builtins_hash">
<title>Built-ins for hashes</title>
<indexterm>
<primary>hash</primary>
<secondary>built-ins</secondary>
</indexterm>
<section xml:id="ref_builtin_keys">
<title>keys</title>
<indexterm>
<primary>keys built-in</primary>
</indexterm>
<para>A sequence that contains all the lookup keys in the
hash.</para>
<programlisting role="template">&lt;#assign myHash = { "name": "mouse", "price": 50 }&gt;
&lt;#list myHash?keys as k&gt;
${k}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> name
price</programlisting>
<para>Note that not all hashes support this (ask the programmer if a
certain hash allows this or not).</para>
<para>Since hashes do not define an order for their sub variables in
general, the order in which key names are returned can be arbitrary.
However, some hashes maintain a meaningful order (ask the programmer
if a certain hash does that or not). For example, hashes created
with the above <literal>{<replaceable>...</replaceable>}</literal>
syntax preserve the same order as you have specified the sub
variables.</para>
<note>
<para>To list both the keys and the values, you can use
<literal>&lt;#list attrs as key,
value&gt;...&lt;#list&gt;</literal>; see the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link>.</para>
</note>
</section>
<section xml:id="ref_builtin_values">
<title>values</title>
<indexterm>
<primary>values built-in</primary>
</indexterm>
<para>A sequence that contains all the variables (the values in the
key-value pairs) in the hash.</para>
<programlisting role="template">&lt;#assign myHash = { "name": "mouse", "price": 50 }&gt;
&lt;#list myHash?values as v&gt;
${v}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> mouse
50</programlisting>
<para>Note that not all hashes support this (ask the programmer if a
certain hash allows this or not).</para>
<para>As of the order in which the values are returned, the same
applies as with the <literal>keys</literal> built-in; see there.
Furthermore, it's not guaranteed that the order of the values
corresponds to the order of the keys returned by the
<literal>keys</literal> build-in.</para>
<note>
<para>To list both the keys and the values, you can use
<literal>&lt;#list attrs as key,
value&gt;...&lt;#list&gt;</literal>; see the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link>.</para>
</note>
</section>
</section>
<section xml:id="ref_builtins_node">
<title>Built-ins for nodes (for XML)</title>
<indexterm>
<primary>node</primary>
<secondary>built-ins</secondary>
</indexterm>
<para>Note that the variables returned by these built-ins are
generated by the node variable implementation it is used with. This
means that the returned variables can have extra features in
additional to what it stated here, for example, with the <link
linkend="xgui_expose_dom">XML DOM nodes</link> the sequence retuned by
the <literal>children</literal> built-in also can be used as hash and
maybe as string, as it is described in the <link linkend="xgui">part
about XML processing</link>.</para>
<section xml:id="ref_builtin_ancestors">
<title>ancestors</title>
<indexterm>
<primary>ancestors built-in</primary>
</indexterm>
<para>A sequence that contains all the node's ancestors, starting
with the immediate parent and ending with the root node. The result
of this built-in is also a method, by which you can filter the
result with the <link
linkend="gloss.fullQualifiedName">full-qualified name</link> of the
node. For example as <literal>node?ancestors("section")</literal> to
get the sequence of all ancestors with name
<literal>section</literal>.</para>
</section>
<section xml:id="ref_builtin_children">
<title>children</title>
<indexterm>
<primary>children built-in</primary>
</indexterm>
<para>A sequence that contains all of this node's child nodes (i.e.
immediate descendant nodes).</para>
<para>XML: This is almost the same as special hash key
<literal>*</literal>, except that it returns all nodes, not only
elements. So the possible children are element nodes, text nodes,
comment nodes, processing instruction nodes, etc. but
<emphasis>not</emphasis> attribute nodes. Attribute nodes are
excluded from the sequence.</para>
</section>
<section xml:id="ref_builtin_node_name">
<title>node_name</title>
<indexterm>
<primary>node_name built-in</primary>
</indexterm>
<para>Returns the string that is used to determine what user-defined
directive to invoke to handle this node when it is
<quote>visited</quote>. See: the <link
linkend="ref.directive.visit">visit</link> and <link
linkend="ref.directive.recurse">recurse</link> directives.</para>
<para>XML: If the node is an element or attribute, then the string
will be the local (prefix free) name of the element or attribute.
Otherwise the name usually starts with <literal>@</literal> followed
by the node type. See <link linkend="misc.xguiTable">this
table</link>. Note that this node name is not the same as the node
name returned in the DOM API; the goal of FreeMarker node names is
to give the name of the used-defined directive that will process the
node.</para>
</section>
<section xml:id="ref_builtin_next_sibling">
<title>next_sibling</title>
<indexterm>
<primary>next_sibling built-in</primary>
</indexterm>
<note>
<para>This built-in is only available since 2.3.26</para>
</note>
<para>Returns the following sibling node of the node. (Two nodes in
a tree are said to be siblings if they are on the same level and are
directly next to each other.) If there's no such node, the
expression
<literal><replaceable>node</replaceable>?next_sibling??</literal>
evaluates to <literal>false</literal>.</para>
<para>XML: Note that the value returned by this built-in is also a
sequence of length 1 (same as the result of some XPath expressions),
however if there's no next sibling, the result is a missing value
(null) instead of an empty sequence. Also note that for XML element
nodes you can also use
<literal><replaceable>node</replaceable>.@@next_sibling_element</literal>,
which is practical if you want to ignore the whitespace that
separates two apparently sibling elements; see more <link
linkend="xgui_imperative_formal">here...</link></para>
<note>
<para>For custom node implementations this built-in is only
supported if that implements the
<literal>freemarker.template.TemplateNodeModelEx</literal>
interface.</para>
</note>
</section>
<section xml:id="ref_builtin_node_namespace">
<title>node_namespace</title>
<indexterm>
<primary>node_namespace built-in</primary>
</indexterm>
<para>Returns the namespace string of the node. FreeMarker does not
define the exact meaning of node namespace; it depends on what your
node variables are modeling. It's possible that a node doesn't have
any node namespace defined. In this case, the built-in should
evaluate to undefined variable (i.e.
<literal>node?<replaceable>node_namespace</replaceable>??</literal>
is <literal>false</literal>), so you can't use the returned
value.</para>
<para>XML: In the case of XML, it's the XML namespace URI (such as
<literal>"http://www.w3.org/1999/xhtml"</literal>). If an element or
attribute node does not use XML namespace, then this built-in
evaluates to an empty string. For other XML nodes this built-in
always return undefined variable.</para>
</section>
<section xml:id="ref_builtin_node_type">
<title>node_type</title>
<indexterm>
<primary>node_type built-in</primary>
</indexterm>
<para>A string that describes the type of the node. FreeMarker does
not define the exact meaning of node type; it depends on what your
variables are modeling. It's possible that a node doesn't support
node type at all. In this case, the built-in evaluates to an
undefined value, so you can't use the returned value. (You can still
check if a node supports the type property with
<literal><replaceable>node</replaceable>?node_type??</literal>.)</para>
<para>XML: The possible values are: <literal>"attribute"</literal>,
<literal>"text"</literal>, <literal>"comment"</literal>,
<literal>"document_fragment"</literal>,
<literal>"document"</literal>, <literal>"document_type"</literal>,
<literal>"element"</literal>, <literal>"entity"</literal>,
<literal>"entity_reference"</literal>,
<literal>"notation"</literal>, <literal>"pi"</literal>. Note that a
there is no <literal>"cdata"</literal> type, because CDATA is
considered as plain text node.</para>
</section>
<section xml:id="ref_builtin_parent">
<title>parent</title>
<indexterm>
<primary>parent built-in</primary>
</indexterm>
<para>Returns the node that is this node's immediate parent in the
node tree. The root node has no parent node, so for the root node,
the expression
<literal><replaceable>node</replaceable>?parent??</literal>
evaluates to <literal>false</literal>.</para>
<para>XML: Note that the value returned by this built-in is also a
sequence (same as the result of XPath expression
<literal>..</literal>, when you write
<literal>someNode[".."]</literal>), however if there's no parent,
the result is a missing value (null) instead of an empty sequence.
Also note that for attribute nodes, it returns the element the
attribute belongs to, despite that attribute nodes are not counted
as children of the element.</para>
</section>
<section xml:id="ref_builtin_previous_sibling">
<title>previous_sibling</title>
<indexterm>
<primary>previous_sibling built-in</primary>
</indexterm>
<note>
<para>This built-in is only available since 2.3.26</para>
</note>
<para>Returns the previous sibling node of the node. Apart from the
direction, this is the same as <literal>next_sibling</literal>, so
see more details <link
linkend="ref_builtin_next_sibling">there...</link></para>
<note>
<para>For custom node implementations this built-in is only
supported if that implements the
<literal>freemarker.template.TemplateNodeModelEx</literal>
interface.</para>
</note>
</section>
<section xml:id="ref_builtin_root">
<title>root</title>
<indexterm>
<primary>root built-in</primary>
</indexterm>
<para>The node that is the root of the tree of nodes to which this
node belongs.</para>
<para>XML: According to W3C, the root of an XML document is not the
topmost element node, but the document itself, which is the parent
of the topmost element. For example, if you want to get the topmost
<emphasis>element</emphasis> of the XML (the so called
<quote>document element</quote>; do not mix it with the
<quote>document</quote>), which is called <literal>foo</literal>,
then you have to write <literal>someNode?root.foo</literal>. If you
write just <literal>someNode?root</literal>, then you get the
document itself, and not the document element.</para>
</section>
</section>
<section xml:id="ref_builtins_loop_var">
<title>Loop variable built-ins</title>
<note>
<para>Loop variable built-ins only exists since FreeMarker
2.3.23.</para>
</note>
<para>These built-ins you can only use with the loop variable of the
<link linkend="ref_directive_list"><literal>list</literal> and
<literal>items</literal> directives</link> (and of the deprecated
<literal>foreach</literal> directive). Some explanation of that
follows (<literal><replaceable>loopVar</replaceable>?index</literal>
returns the 0-based index in the listable value we iterate
through):</para>
<programlisting role="template">&lt;#-- Note: x is a loop variable --&gt;
&lt;#list ['a', 'b', 'c'] as x&gt;
${x?index}
&lt;/#list&gt;</programlisting>
<programlisting role="output">0
1
2</programlisting>
<para>When the <literal>list</literal> directive doesn't specify the
loop variable, these built-ins are used with the loop variable of the
<literal>items</literal> directive:</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c']&gt;
&lt;ul&gt;
&lt;#items as x&gt;
&lt;li&gt;${x?index}&lt;/li&gt;
&lt;/#items&gt;
&lt;/ul&gt;
&lt;/#list&gt;</programlisting>
<para>Loop variable built-ins only use the <emphasis>name</emphasis>
of loop variable, so that they can identify the related ongoing
iteration. They don't read the <emphasis>value</emphasis> of the loop
variable. Hence, this is a parsing error:</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c'] as x&gt;
&lt;#assign y = x&gt;
${y?index} &lt;#-- ERROR: y isn't a loop variable --&gt;
&lt;/#list&gt;</programlisting>
<section xml:id="ref_builtin_counter">
<title>counter</title>
<indexterm>
<primary>counter built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Returns the 1-based index where the iteration (which is
identified by the loop variable name) currently stands.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c'] as i&gt;
${i?counter}: ${i}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> 1: a
2: b
3: c</programlisting>
<note>
<para>For the 0-based index, use the <link
linkend="ref_builtin_index"><literal>index</literal>
built-in</link>.</para>
</note>
</section>
<section xml:id="ref_builtin_has_next">
<title>has_next</title>
<indexterm>
<primary>has_next built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Tells if the item where the iteration (which is identified by
the loop variable name) currently stands is not the last
item.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c'] as i&gt;${i?has_next?c} &lt;/#list&gt;</programlisting>
<programlisting role="output">true true false </programlisting>
<note>
<para>For separating items with commas and such, use
<literal>&lt;#sep&gt;<replaceable>separator</replaceable>&lt;/#sep&gt;</literal>
instead of <literal>&lt;#if
<replaceable>var</replaceable>?has_next&gt;<replaceable>separator</replaceable>&lt;/#if&gt;</literal>,
as it's more readable. (Furthermore the
<literal>&lt;/#sep&gt;</literal> can be often omitted, like in
<literal>&lt;#list <replaceable>...</replaceable> as
<replaceable>var</replaceable>&gt;<replaceable>...</replaceable>${<replaceable>var</replaceable>}<replaceable>...</replaceable>&lt;#sep&gt;<replaceable>separator</replaceable>&lt;/#list&gt;</literal>)</para>
</note>
<note>
<para>If you need the inverse of this built-in, use
<literal><replaceable>var</replaceable>?is_last</literal> instead
of <literal>!<replaceable>var</replaceable>?has_next</literal>,
because it's more readable.</para>
</note>
</section>
<section xml:id="ref_builtin_index">
<title>index</title>
<indexterm>
<primary>index built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Returns the 0-based index where the iteration (which is
identified by the loop variable name) currently stands.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c'] as i&gt;
${i?index}: ${i}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> 0: a
1: b
2: c</programlisting>
<note>
<para>For the 1-based index, use the <link
linkend="ref_builtin_counter"><literal>counter</literal>
built-in</link>.</para>
</note>
</section>
<section xml:id="ref_builtin_is_even_item">
<title>is_even_item</title>
<indexterm>
<primary>is_even_item built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Tells if the item where the iteration (which is identified by
the loop variable name) currently stands has an even 1-based
index.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c', 'd'] as i&gt;${i?is_even_item?c} &lt;/#list&gt;</programlisting>
<programlisting role="output">false true false true</programlisting>
<note>
<para>To make tables with alternating row colors and such, use
<link
linkend="ref_builtin_item_parity"><literal><replaceable>var</replaceable>?item_parity</literal></link>
or <link
linkend="ref_builtin_item_cycle"><literal><replaceable>var</replaceable>?item_cycle(...)</literal></link>
instead.</para>
</note>
</section>
<section xml:id="ref_builtin_is_first">
<title>is_first</title>
<indexterm>
<primary>is_first built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Tells if the item where the iteration (which is identified by
the loop variable name) currently stands is the first item.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c'] as i&gt;${i?is_first?c} &lt;/#list&gt;</programlisting>
<programlisting role="output">true false false </programlisting>
</section>
<section xml:id="ref_builtin_is_last">
<title>is_last</title>
<indexterm>
<primary>is_last built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Tells if the item where the iteration (which is identified by
the loop variable name) currently stands is the last item.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c'] as i&gt;${i?is_last?c} &lt;/#list&gt;</programlisting>
<programlisting role="output">false false true</programlisting>
<note>
<para>If you need the inverse of this built-in, use
<literal><replaceable>var</replaceable>?has_next</literal> instead
of <literal>!<replaceable>var</replaceable>?is_last</literal>,
because it's more readable.</para>
</note>
<note>
<para>For separating items with commas and such, use
<literal>&lt;#sep&gt;<replaceable>separator</replaceable>&lt;/#sep&gt;</literal>
instead of <literal>&lt;#if
<replaceable>var</replaceable>?has_next&gt;<replaceable>separator</replaceable>&lt;/#if&gt;</literal>,
as it's more readable. (Furthermore the
<literal>&lt;/#sep&gt;</literal> can be often omitted, like in
<literal>&lt;#list <replaceable>...</replaceable> as
<replaceable>var</replaceable>&gt;<replaceable>...</replaceable>${<replaceable>var</replaceable>}<replaceable>...</replaceable>&lt;#sep&gt;<replaceable>separator</replaceable>&lt;/#list&gt;</literal>)</para>
</note>
</section>
<section xml:id="ref_builtin_is_odd_item">
<title>is_odd_item</title>
<indexterm>
<primary>is_odd_item built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Tells if the item where the iteration (which is identified by
the loop variable name) currently stands has an odd 1-based
index.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c', 'd'] as i&gt;${i?is_odd_item?c} &lt;/#list&gt;</programlisting>
<programlisting role="output">true false true false </programlisting>
<note>
<para>To make tables with alternating row colors and such, use
<link
linkend="ref_builtin_item_parity"><literal><replaceable>var</replaceable>?item_parity</literal></link>
or <link
linkend="ref_builtin_item_cycle"><literal><replaceable>var</replaceable>?item_cycle(...)</literal></link>
instead.</para>
</note>
</section>
<section xml:id="ref_builtin_item_cycle">
<title>item_cycle</title>
<indexterm>
<primary>item_cycle built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>This is a more generic version of the <link
linkend="ref_builtin_item_parity"><literal>item_parity</literal>
built-in</link>, where you can specify what value to use instead of
<literal>"odd"</literal> and <literal>"even"</literal>. It also
allows more than 2 values that it will cycle through.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c', 'd', 'e', 'f', 'g'] as i&gt;
&lt;tr class="${i?item_cycle('row1', 'row2', 'row3')}"&gt;${i}&lt;/tr&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;tr class="row1"&gt;a&lt;/tr&gt;
&lt;tr class="row2"&gt;b&lt;/tr&gt;
&lt;tr class="row3"&gt;c&lt;/tr&gt;
&lt;tr class="row1"&gt;d&lt;/tr&gt;
&lt;tr class="row2"&gt;e&lt;/tr&gt;
&lt;tr class="row3"&gt;f&lt;/tr&gt;
&lt;tr class="row1"&gt;g&lt;/tr&gt;</programlisting>
<para>Some details:</para>
<itemizedlist>
<listitem>
<para>The number of arguments must be at least 1, and has no
upper limit.</para>
</listitem>
<listitem>
<para>The type of the arguments can be anything, they doesn't
have to be strings.</para>
</listitem>
</itemizedlist>
<note>
<para>Use the <link
linkend="ref_builtin_item_parity"><literal>item_parity</literal>
built-in</link> instead if the values you need are
<literal>"odd"</literal> and <literal>"even"</literal>.</para>
</note>
</section>
<section xml:id="ref_builtin_item_parity">
<title>item_parity</title>
<indexterm>
<primary>item_parity built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Returns <literal>"odd"</literal> or <literal>"even"</literal>
string value, depending on the parity of the 1-based index where the
iteration (which is identified by the loop variable name) currently
stands. This is commonly used for alternating color for table
rows:</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c', 'd'] as i&gt;
&lt;tr class="${i?item_parity}Row"&gt;${i}&lt;/tr&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;tr class="oddRow"&gt;a&lt;/tr&gt;
&lt;tr class="evenRow"&gt;b&lt;/tr&gt;
&lt;tr class="oddRow"&gt;c&lt;/tr&gt;
&lt;tr class="evenRow"&gt;d&lt;/tr&gt;</programlisting>
<note>
<para>Use the <link
linkend="ref_builtin_item_parity"><literal>item_parity_cap</literal>
built-in</link> for capitalized <literal>"Odd"</literal> and
<literal>"Even"</literal>. Use the <link
linkend="ref_builtin_item_cycle"><literal>item_cycle</literal>
built-in</link> to specify custom values, or more then two
values.</para>
</note>
</section>
<section xml:id="ref_builtin_item_parity_cap">
<title>item_parity_cap</title>
<indexterm>
<primary>item_parity_cap built-in</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.23.</para>
</note>
<para>Returns <literal>"Odd"</literal> or <literal>"Even"</literal>
string value (note the capitalization), depending on the parity of
the 1-based index where the iteration (which is identified by the
loop variable name) currently stands.</para>
<programlisting role="template">&lt;#list ['a', 'b', 'c', 'd'] as i&gt;
&lt;tr class="row${i?item_parity_cap}"&gt;${i}&lt;/tr&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;tr class="rowOdd"&gt;a&lt;/tr&gt;
&lt;tr class="rowEven"&gt;b&lt;/tr&gt;
&lt;tr class="rowOdd"&gt;c&lt;/tr&gt;
&lt;tr class="rowEven"&gt;d&lt;/tr&gt;</programlisting>
<note>
<para>Use the <link
linkend="ref_builtin_item_parity"><literal>item_parity</literal>
built-in</link> for lower case <literal>"odd"</literal> and
<literal>"even"</literal>.</para>
</note>
</section>
</section>
<section xml:id="ref_builtins_type_independent">
<title>Type independent built-ins</title>
<para>These are the built-ins that don't care (much) about the type of
their left hand argument.</para>
<section xml:id="ref_builtin_switch">
<title>switch</title>
<indexterm>
<primary>switch built-in</primary>
</indexterm>
<indexterm>
<primary>switch expression</primary>
</indexterm>
<note>
<para>This built-in exists since FreeMarker 2.3.23.</para>
</note>
<para>This is basically the in-line (expression) version of the
<link
linkend="ref_directive_switch"><literal>switch</literal>-<literal>case</literal>-<literal>default</literal>
directives</link>. Its generic format is like
<literal><replaceable>matchedValue</replaceable>?switch(<replaceable>case1</replaceable>,
<replaceable>result1</replaceable>,
<replaceable>case2</replaceable>,
<replaceable>result2</replaceable>, ...
<replaceable>caseN</replaceable>,
<replaceable>resultN</replaceable>,
<replaceable>defaultResult</replaceable>)</literal>, where
<literal><replaceable>defaultResult</replaceable></literal> can be
omitted. Example:</para>
<programlisting role="template">&lt;#list ['r', 'w', 'x', 's'] as flag&gt;
${flag<emphasis>?switch('r', 'readable', 'w' 'writable', 'x', 'executable', 'unknown flag: ' + flag)</emphasis>}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> readable
writable
executable
unknown flag: s
</programlisting>
<para>That is, <literal>switch</literal> will find the first
<literal><replaceable>case</replaceable></literal> parameter (left
to right) whose value equals to
<literal><replaceable>matchedValue</replaceable></literal>, then it
returns the value of the
<literal><replaceable>result</replaceable></literal> parameter
that's directly after that
<literal><replaceable>case</replaceable></literal> parameter. If it
doesn't find an equal
<literal><replaceable>case</replaceable></literal>, then it will
return the value of the
<literal><replaceable>defaultResult</replaceable></literal>, or if
there's no
<literal><replaceable>defaultResult</replaceable></literal>
parameter (i.e., if the number of parameters is even) then it stops
the template processing with error.</para>
<para>Further details:</para>
<itemizedlist>
<listitem>
<para>The comparison of
<literal><replaceable>matchedValue</replaceable></literal> to
the <literal><replaceable>case</replaceable></literal> parameter
value behaves exactly like <link
linkend="dgui_template_exp_comparison">the <literal>==</literal>
operator</link>. Hence it only compares scalars and only
same-type values. Thus, something like <literal>x?switch(1,
"r1", "c2", "r2")</literal> doesn't make sense, as if
<literal>x</literal> is non-numerical then the first case will
cause error, and if <literal>x</literal> is numerical then the
second case will cause error (unless <literal>x</literal> is
<literal>1</literal>, as then we won't do further comparisons
after the first one).</para>
</listitem>
<listitem>
<para>Unlike with normal method calls, only those parameters of
<literal>switch(<replaceable>...</replaceable>)</literal> are
evaluated that are indeed needed. For example, in
<literal>two()?switch(c1(), r1(), c2(), r2(), c3(),
r3())</literal>, if <literal>two()</literal> returns
<literal>2</literal>, <literal>c1()</literal> returns
<literal>1</literal>, and <literal>c2()</literal> returns
<literal>2</literal>, then only the following functions will be
called, and in this order: <literal>m()</literal>,
<literal>c1()</literal>, <literal>c2()</literal>,
<literal>r2()</literal>. (Naturally, arguments that aren't
evaluated can refer to missing variables without causing error.)
It's guaranteed that the
<literal><replaceable>case</replaceable></literal> parameter
expressions are evaluated left to right, and only until the
first match was found. It's also guaranteed that only the
<literal><replaceable>result</replaceable></literal> expression
that belongs to the first matching
<literal><replaceable>case</replaceable></literal> will be
evaluated. It's also guaranteed that the
<literal><replaceable>defaultResult</replaceable></literal>
expression will only be evaluated if there was no matching
<literal><replaceable>case</replaceable></literal>
parameter.</para>
</listitem>
<listitem>
<para>The <literal><replaceable>case</replaceable></literal>
parameter expressions need not be constant values, they can be
arbitrary complex expressions. Of course, the same goes for and
the <literal><replaceable>result</replaceable></literal>,
<literal><replaceable>defaultResult</replaceable></literal>, and
<literal><replaceable>matchedValue</replaceable></literal>.</para>
</listitem>
<listitem>
<para>There's no restriction regarding the type of the
<literal><replaceable>case</replaceable></literal> parameter
values, like they can be strings, or numbers, or dates, etc.
However, because of how the <literal>==</literal> operator
works, it doesn't make sense to use
<literal><replaceable>case</replaceable></literal> parameters of
different types inside the <replaceable>same</replaceable>
<literal>switch</literal> (see earlier why).</para>
</listitem>
<listitem>
<para>Unlike with the <link
linkend="ref_directive_switch"><literal>case</literal>
directive</link>, there's no fall-through behavior there, that
is, there's no need for an equivalent of the
<literal>break</literal> directive.</para>
</listitem>
</itemizedlist>
<note>
<para>If you need to switch by a boolean value, you should use the
<link linkend="ref_builtin_then"><literal>then</literal>
built-in</link> instead, like
<literal><replaceable>matchedBoolean</replaceable>?then(<replaceable>whenTrue</replaceable>,
<replaceable>whenFalse</replaceable>)</literal>.</para>
</note>
<note>
<para>If you need to do arbitrary logical tests instead of simple
equality comparisons at the
<literal><replaceable>case</replaceable></literal> parameters, you
can do something like this (here we tests for ranges):
<literal>true?switch(priority &lt;= 1, "low", priority == 2,
"medium", priority &gt;= 3, "high")</literal></para>
</note>
</section>
</section>
<section xml:id="ref_builtins_expert">
<title>Seldom used and expert built-ins</title>
<para>These are the built-ins that normally you should not use, but in
exceptional situations (debugging, advanced macros) they can be
useful. If you need to use these in your normal page templates, you
may revisit the data-model so you don't need to use these.</para>
<section xml:id="ref_builtin_absolute_template_name">
<title>absolute_template_name</title>
<indexterm>
<primary>absolute_template_name built-in</primary>
</indexterm>
<para>Converts a template name to an absolute name, which can be
safely passed to <literal>&lt;#include
<replaceable>name</replaceable>&gt;</literal> or
<literal>&lt;#import <replaceable>name</replaceable> as
<replaceable>ns</replaceable>&gt;</literal> or
<literal>.get_optional_template(<replaceable>name</replaceable>)</literal>
and such in <emphasis>another</emphasis> template, as it won't be
misinterpreted to be relative to the directory of the template that
contains the <literal>include</literal>, <literal>import</literal>,
etc. For example, if you are in template
<literal>"dir/here.ftl"</literal>, then
<literal>"target.ftl"</literal> is converted to
<literal>"/dir/target.ftl"</literal> (note the initial
<literal>/</literal>). If now you pass this value to a template in
<literal>"other-dir/there.ftl"</literal>, where it's passed to the
<literal>include</literal> directive, then it won't be
misinterpreted as <literal>"other-dir/target.ftl"</literal>, like
<literal>"target.ftl"</literal> would have been.</para>
<para>Optionally, you can specify a root based name (a name that's
either relative to the template root directory, or is absolute) that
will be used instead of the name of the current template, like
<literal><replaceable>pathToConver</replaceable>?absolute_template_name(<replaceable>otherTemplateName</replaceable>)</literal>.</para>
<para>Example of an application (also uses <link
linkend="ref_specvar_caller_template_name"><literal>.caller_template_name</literal></link>
and <link
linkend="ref_specvar_get_optional_template"><literal>.get_optional_template</literal></link>):</para>
<programlisting role="template">&lt;#--
&lt;@smileyInclude name /&gt; behaves like &lt;#include name&gt;, but prints a "(:" before the
template, or prints "):" instead if the template is missing.
Note that just like with #include, if name is relative, it's resolved based on the
directory of the caller template, not of the template that defines this macro. As
.get_optional_template resolves relative names based on the current template, we
had to convert the name to an absolute name based on the caller template before
passing it to it.
--&gt;
&lt;#macro smileyInclude name&gt;
&lt;#local t = .get_optional_template(
name<emphasis>?absolute_template_name</emphasis>(.caller_template_name))&gt;
&lt;#if t.exists&gt;
(:
&lt;@t.include /&gt;
&lt;#else&gt;
):
&lt;/#if&gt;
&lt;/#macro&gt;</programlisting>
</section>
<section xml:id="ref_buitin_api_and_has_api">
<title>api, has_api</title>
<indexterm>
<primary>api built-in</primary>
</indexterm>
<indexterm>
<primary>has_api built-in</primary>
</indexterm>
<note>
<para>These built-ins exists since FreeMarker 2.3.22</para>
</note>
<para><literal><replaceable>value</replaceable>?api</literal>
provides access to the API (usually, the Java API) of
<literal><replaceable>value</replaceable></literal>, like
<literal><replaceable>value</replaceable>?api.<replaceable>someJavaMethod()</replaceable></literal>
or
<literal><replaceable>value</replaceable>?api.<replaceable>someBeanProperty</replaceable></literal>,
if the value itself supports exposing its API. This meant to be used
rarely, when you need to call a Java method of an object, but the
by-design simplistic view of the value that FreeMarker exposes to
the templates hides that, and there's no equivalent built-in either.
For example, when you put a <literal>Map</literal> into the
data-model (and you are using the default object wrapper),
<literal>myMap.myMethod()</literal> in a template basically
translates to <literal>((Method)
myMap.get("myMethod")).invoke(...)</literal> in Java, thus you can't
call <literal>myMethod</literal>. If, however, you write
<literal>myMap?api.myMethod()</literal> instead, that means
<literal>myMap.myMethod()</literal> in Java. Similarly,
<literal>myMap?api.myProperty</literal> translates to
<literal>myMap.getMyProperty()</literal> in Java, instead of to
<literal>myMap.get("myProperty")</literal>.</para>
<para><emphasis>You should avoid using <literal>api</literal>, and
rely on the capabilities of the FTL types and the related built-ins
as far as possible.</emphasis> For example, don't use
<literal>users?api.size()</literal>, but
<literal>users?size</literal>. The variation that uses
<literal>?api</literal> is more verbose, slower, more easily breaks
when FreeMarker configuration settings are changed, and most
importantly, more prone to break as the technical details of the
data-model change. For example, if <literal>users</literal> is
changed from a <literal>List</literal> to an array,
<literal>users?size</literal> will keep working, while
<literal>users?api.size()</literal> will break.</para>
<para>Avoid calling methods that <emphasis>modify</emphasis> an
object (especially <literal>Map</literal>-s and
<literal>Collection</literal>-s) or that aren't thread safe from
other reasons. Templates usually aren't expected to modify the
objects exposed to them, just to display them. Thus the application
may passes some objects to multiple (possibly concurrent) template
processings.</para>
<para>The <literal>api</literal> built-in is not everywhere
available, some requirements has to be met:</para>
<itemizedlist>
<listitem>
<para>The <literal>api_builtin_enabled</literal> configuration
setting must be set to <literal>true</literal>. Its default is
<literal>false</literal> (at least as of 2.3.22) for not
lowering the security of existing applications.</para>
</listitem>
<listitem>
<para>The value itself has to support it. We are talking about
the value as the template sees it, which is created from the
original object (that's coming from the data-model or from a
Java method return value) value via <link
linkend="pgui_datamodel_objectWrapper">object wrapping</link>.
Hence, this depends on the <literal>object_wrapper</literal>
FreeMarker configuration setting, and on the class of the
wrapped (the original) object:</para>
<itemizedlist>
<listitem>
<para>When the object wrapper is a
<literal>DefaultObjectWrapper</literal> with its
<literal>incompatibleImprovements</literal> set to 2.3.22 or
higher (<link linkend="topic.defaultObjectWrapperIcI">see
how to set it here</link>), FTL values made from
<literal>Map</literal>-s and <literal>List</literal>-s
support <literal>?api</literal>. (Actually, what matters is
that its <literal>useAdaptersForContainer</literal> property
is set to <literal>true</literal>, but that's the default
with said <literal>incompatibleImprovements</literal>.)
Other <literal>java.util.Collections</literal> (such as
<literal>Set</literal>-s) only support
<literal>?api</literal> if
<literal>DefaultObjectWrapper</literal>'s
<literal>forceLegacyNonListCollections</literal> property is
set to <literal>false</literal> (the default is
<literal>true</literal> for better out-of-the-box backward
compatibility).</para>
</listitem>
<listitem>
<para>When wrapped with pure
<literal>BeansWrapper</literal>, all values support
<literal>?api</literal>.</para>
</listitem>
<listitem>
<para>Custom <literal>TemplateModel</literal>-s can support
<literal>?api</literal> by implementing the
<literal>freemarker.template.TemplateModelWithAPISupport</literal>
interface.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>Using <literal>?api</literal> when it's not allowed in the
configuration or when the value doesn't support it will abort
template processing with error.</para>
<para>Whether a value supports <literal>?api</literal> can be
checked like
<literal><replaceable>value</replaceable>?has_api</literal>, which
returns a boolean value. Note that the result of
<literal>?has_api</literal> isn't influenced by the
<literal>api_builtin_enabled</literal> setting.</para>
</section>
<section xml:id="ref_builtin_numType">
<title>byte, double, float, int, long, short</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>byte built-in</primary>
</indexterm>
<indexterm>
<primary>double built-in</primary>
</indexterm>
<indexterm>
<primary>float built-in</primary>
</indexterm>
<indexterm>
<primary>int built-in</primary>
</indexterm>
<indexterm>
<primary>long built-in</primary>
</indexterm>
<indexterm>
<primary>short built-in</primary>
</indexterm>
<indexterm>
<primary>converting date to long</primary>
</indexterm>
<indexterm>
<primary>date to long</primary>
</indexterm>
<para>Returns a <literal>SimpleNumber</literal> which contains the
same value as the original variable, but uses
<literal>java.lang.<replaceable>Type</replaceable></literal> for the
internal representation of the value. This is useful if a method is
overloaded, or if a <literal>TemplateModel</literal> unwrapper has
problem with automatically choosing the suitable
<literal>java.lang.*</literal> type. Note that since version 2.3.9
the unwrapper has been improved substantially, so you will hardly
ever need to use these built-ins to convert between numerical types,
except for resolving ambiguity in overloaded method
invocation.</para>
<para>The <literal>long</literal> built-in can also be used with
date, time and date-time values to get the value as
<literal>java.util.Date.getTime()</literal> would return. This is
useful if you have to call a Java methods that expect a timestamp as
a <literal>long</literal>.</para>
</section>
<section xml:id="ref_builtin_eval">
<title>eval</title>
<indexterm>
<primary>eval</primary>
</indexterm>
<indexterm>
<primary>evaluate string</primary>
</indexterm>
<para>This built-in evaluates a string as an FTL
<emphasis>expression</emphasis>. For example
<literal>"1+2"?eval</literal> returns the number 3. (To render a
template that's stored in a string, use the <link
linkend="ref_builtin_interpret"><literal>interpret</literal>
built-in</link> instead.)</para>
<warning>
<para>Do not use this to evaluate JSON! For that use the <link
linkend="ref_builtin_eval_json"><literal>eval_json</literal>
built-in</link> instead. While FTL expression language looks
similar to JSON, not all JSON is valid FTL expression. Also, FTL
expressions can access variables, and call Java methods on them,
so if you <literal>?eval</literal> strings coming from untrusted
source, it can become an attack vector.</para>
</warning>
<para>The evaluated expression sees the same variables (such as
locals) that are visible at the place of the invocation of
<literal>eval</literal>. That is, it behaves similarly as if in
place of <literal><replaceable>s</replaceable>?eval</literal> you
had the <emphasis>value of</emphasis>
<literal><replaceable>s</replaceable></literal> there. Except, it
can't use <link linkend="ref_builtins_loop_var">loop variable
built-ins</link> that refer to a loop variable that was created
outside <literal><replaceable>s</replaceable></literal>.</para>
<para>Regarding the configuration settings that affect the parsing
(like syntax) and evaluation the rules are the same as with the
<link linkend="ref_builtin_interpret"><literal>interpret</literal>
built-in</link>.</para>
</section>
<section xml:id="ref_builtin_eval_json">
<title>eval_json</title>
<indexterm>
<primary>eval_json</primary>
</indexterm>
<indexterm>
<primary>evaluate string</primary>
</indexterm>
<indexterm>
<primary>JSON</primary>
</indexterm>
<note>
<para>This built-in is available since FreeMarker 2.3.31.</para>
</note>
<para>This built-in evaluates a string as a JSON
<emphasis>expression</emphasis>, so that you can extract data from
inside it. For example, if you receive data in the
<literal>dataJson</literal> variable, but it's unfortunately just a
flat string that contains <literal>{"name": "foo", "ids": [11,
22]}</literal>, then you can extract data from it like this:</para>
<programlisting role="template">&lt;#assign data = dataJson<emphasis>?eval_json</emphasis>&gt;
&lt;p&gt;Name: ${data.name}
&lt;p&gt;Ids:
&lt;ul&gt;
&lt;#list data.ids as id&gt;
&lt;li&gt;${id}
&lt;/#list&gt;
&lt;/ul&gt;</programlisting>
<para>Ideally, you shouldn't need <literal>eval_json</literal>,
since the template should receive data already parsed (to
<literal>List</literal>-s, <literal>Map</literal>-s, Java beans,
etc.). This built-in is there as a workaround, if you can't improve
the data-model.</para>
<para>The evaluated JSON expression doesn't have to be a JSON object
(key-value pairs), it can be any kind of JSON value, like JSON
array, JSON number, etc.</para>
<para>The syntax understood by this built-in is a superset of
JSON:</para>
<itemizedlist>
<listitem>
<para>Java-style comments are supported
(<literal>/*<replaceable>...</replaceable>*/</literal> and
<literal>//<replaceable>...</replaceable></literal>)</para>
</listitem>
<listitem>
<para>BOM (byte order mark) and non-breaking space
(<quote>nbsp</quote>) are treated as whitespace (in a stricter
JSON parser they are errors of occurring around tokens).</para>
</listitem>
</itemizedlist>
<para>No other non-JSON extras are implemented, notably, it's
impossible to refer to variables (unlike in the <link
linkend="ref_builtin_eval"><literal>eval</literal> built-in</link>).
This is important for safety, when receiving JSON from untrusted
sources.</para>
</section>
<section xml:id="ref_builtin_has_content">
<title>has_content</title>
<indexterm>
<primary>has_content built-in</primary>
</indexterm>
<para>It is <literal>true</literal> if the variable exists (and
isn't Java <literal>null</literal>) and is not <quote>empty</quote>,
otherwise it is <literal>false</literal>. The meaning of
<quote>empty</quote> depends on the concrete case. This follows
intuitive common-sense ideas. The following are empty: a string with
0 length, a <link linkend="dgui_misc_autoescaping_movalues">markup
output value</link> with 0 length markup, a sequence or hash with no
sub variables, a collection which has passed the last element. If
the value is not of any of these types, then it counts as non-empty
if it's a number or a date or a boolean (e.g. <literal>0</literal>
and <literal>false</literal> are not empty), otherwise it counts as
empty. Note that when your data-model implements multiple template
model interfaces you may get unexpected results. However, when in
doubt you can use always use <literal>expr!?size &gt; 0</literal> or
<literal>expr!?length &gt; 0</literal> instead of
<literal>expr?has_content</literal>.</para>
<para>This buit-in is exceptional in that you can use the
parentheses trick like with the <link
linkend="dgui_template_exp_missing_default">default value
operator</link>. That is, you can write both
<literal>product.color?has_content</literal> and
<literal>(product.color)?has_content</literal>. The first doesn't
handle the case when <literal>product</literal> is missing, the last
does.</para>
</section>
<section xml:id="ref_builtin_interpret">
<title>interpret</title>
<indexterm>
<primary>interpret built-in</primary>
</indexterm>
<para>This built-in parses a string as an FTL template, and returns
an user-defined directive that executes that template, just as if a
template with that content were <link
linkend="ref_directive_include"><literal>include</literal>-d</link>
at that point. Example:</para>
<programlisting role="template">&lt;#assign x=["a", "b", "c"]&gt;
&lt;#assign templateSource = r"&lt;#list x as y&gt;${y}&lt;/#list&gt;"&gt;
&lt;#-- Note: That r was needed so that the ${y} is not interpreted above --&gt;
&lt;#assign inlineTemplate = templateSource?interpret&gt;
&lt;@inlineTemplate /&gt;</programlisting>
<para>The output:</para>
<programlisting role="output">abc</programlisting>
<para>As you can see, <literal>inlineTemplate</literal> is a
user-defined directive that, when executed, runs the template whose
content is the value of <literal>templateSource</literal>.</para>
<para>The name of the template created by
<literal>interpret</literal> is the name of the template that calls
<literal>interpret</literal>, plus
<literal>"-&gt;anonymous_interpreted"</literal>. For example, if the
template that calls the built-in is
<literal>"foo/bar.ftl"</literal>, then the name of the resulting
template is
<literal>"foo/bar.ftl-&gt;anonymous_interpreted"</literal>. Thus,
relative paths inside the interpreted template are relative to this
path (i.e., the base directory will be <literal>"foo"</literal>),
and errors inside the interpreted template will point to this
generated template name.</para>
<para>For more helpful error messages, you can override the template
name part after the <literal>"-&gt;"</literal>. For example, let's
say <literal>mailTemplateSource</literal> comes from the
<literal>mail_template</literal> database table, and in the case of
error, you want the error log to contain the database ID of the
failing template:</para>
<programlisting role="template">&lt;#assign inlineTemplate = [mailTemplateSource, "mail_templates id=${mailTemplateId}"]?interpret&gt;</programlisting>
<para>As you can see, <literal>interpret</literal> can be applied on
a sequence of two items, in which case the first item is the FTL
string to interpret, and the second items is the template name used
after the <literal>"-&gt;"</literal>.</para>
<para>The configuration settings that affect the interpreted
template are the same as of the surrounding template, except that
parser settings specified in the <link
linkend="ref.directive.ftl"><literal>ftl</literal> directive</link>
or was established via tag syntax or naming convention
auto-detection are instead coming from the
<literal>Configuration</literal> object (or naturally, from the
<link
linkend="pgui_config_templateconfigurations"><literal>TemplateConfiguration</literal></link>,
if there's any). Thus the tag syntax, naming convention, whitespace
handling, etc. of the interpreted template is independent of that
established <emphasis>inside</emphasis> the surrounding template. An
important exception from this rule is that the <link
linkend="dgui_misc_autoescaping_outputformat">output format</link>
and auto-escaping policy is inherited from the lexical context where
<literal>interpret</literal> is called from. For example in a
template that has <literal>&lt;#ftl
output_format="XML"&gt;</literal> header (or if you are inside a
<literal>&lt;#output_format
"XML"&gt;<replaceable>...</replaceable>&lt;/#output_format&gt;</literal>
block), <literal>interpret</literal> calls in it will produce
directives with XML output format.</para>
</section>
<section xml:id="ref_builtin_isType">
<title>is_...</title>
<indexterm>
<primary>is_... built-in</primary>
</indexterm>
<indexterm>
<primary>type checking</primary>
</indexterm>
<para>These built-ins check the type of a variable, and returns
<literal>true</literal> or <literal>false</literal> depending on the
type. The list of
<literal>is_<replaceable>...</replaceable></literal>
built-ins:</para>
<informaltable border="1">
<thead>
<tr>
<th>Built-in</th>
<th>Returns <literal>true</literal> if the value is a ...</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>is_string</literal></td>
<td>string</td>
</tr>
<tr>
<td><literal>is_number</literal></td>
<td>number</td>
</tr>
<tr>
<td><literal>is_boolean</literal></td>
<td>boolean</td>
</tr>
<tr>
<td><literal>is_date</literal></td>
<td>Don't use it! Same as <literal>is_date_like</literal>, use
that instead. Later may changes meaning to
<literal>date_only</literal>.</td>
</tr>
<tr>
<td><literal>is_date_like</literal></td>
<td>date-like, means either date, time or date-time, or
date-like with unknown precise type (since FreeMarker
2.3.21)</td>
</tr>
<tr>
<td><literal>is_date_only</literal></td>
<td>date (no time of the day part) (since FreeMarker
2.3.21)</td>
</tr>
<tr>
<td><literal>is_time</literal></td>
<td>time (no year-month-day part) (since FreeMarker
2.3.21)</td>
</tr>
<tr>
<td><literal>is_datetime</literal></td>
<td>date-time (contains both year-month-day and time of the
day)</td>
</tr>
<tr>
<td><literal>is_unknown_date_like</literal></td>
<td>date-like where we don't know if it's a date or a time or
a date-time</td>
</tr>
<tr>
<td><literal>is_method</literal></td>
<td>method</td>
</tr>
<tr>
<td><literal>is_transform</literal></td>
<td>transform</td>
</tr>
<tr>
<td><literal>is_macro</literal></td>
<td>macro or function (yes, also for function; a historical
glitch)</td>
</tr>
<tr>
<td><literal>is_hash</literal></td>
<td>hash (including extended hash)</td>
</tr>
<tr>
<td><literal>is_hash_ex</literal></td>
<td>extended hash (supports <literal>?keys</literal> and
<literal>?values</literal>)</td>
</tr>
<tr>
<td><literal>is_sequence</literal></td>
<td>sequence (Historical quirk: Before <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incompatible_improvements</literal></link>
2.3.24 it returns <literal>true</literal> for Java methods as
they implement the
<literal>[<replaceable>index</replaceable>]</literal>
operator, however, they fail on
<literal>?size</literal>.)</td>
</tr>
<tr>
<td><literal>is_collection</literal></td>
<td>collection (including extended collection)</td>
</tr>
<tr>
<td><literal>is_collection_ex</literal></td>
<td>extended collection (supports
<literal>?size</literal>)</td>
</tr>
<tr>
<td><literal>is_enumerable</literal></td>
<td>sequence or collection</td>
</tr>
<tr>
<td><literal>is_indexable</literal></td>
<td>sequence (Historical quirk: it returns
<literal>true</literal> for Java methods as they implement the
<literal>[<replaceable>index</replaceable>]</literal>
operator.)</td>
</tr>
<tr>
<td><literal>is_directive</literal></td>
<td>Whatever kind of directive (for example a macro, <phrase
role="forProgrammers">or
<literal>TemplateDirectiveModel</literal>,
<literal>TemplateTransformModel</literal>, etc.</phrase>), or
function (a historical glitch)</td>
</tr>
<tr>
<td><literal>is_node</literal></td>
<td>node</td>
</tr>
<tr>
<td><literal>is_markup_output</literal></td>
<td>markup output (a value that won't be <link
linkend="dgui_misc_autoescaping">auto-escaped</link>)</td>
</tr>
</tbody>
</informaltable>
</section>
<section xml:id="ref_builtin_markup_string">
<title>markup_string</title>
<para><indexterm>
<primary>markup_string built-in</primary>
</indexterm></para>
<note>
<para>This built-in is available since FreeMarker 2.3.24.</para>
</note>
<para>Returns the markup stored inside a <link
linkend="dgui_misc_autoescaping_movalues">markup output value</link>
as string. This is useful if the value has to be passed to a Java
method for a <literal>String</literal> parameter, or if we want to
manipulate the markup directly in the template. Note that the
resulting string can be converted back to markup output value with
<link
linkend="ref_builtin_no_esc"><literal>?no_esc</literal></link>.</para>
</section>
<section xml:id="ref_builtin_namespace">
<title>namespace</title>
<indexterm>
<primary>namespace built-in</primary>
</indexterm>
<para>This built-in returns the namespace (i.e. the
<quote>gate</quote> hash to the namespace) associated with a macro
or function variable. You can use it with macros and functions
only.</para>
</section>
<section xml:id="ref_builtin_new">
<title>new</title>
<indexterm>
<primary>instantiating variable</primary>
</indexterm>
<indexterm>
<primary>new built-in</primary>
</indexterm>
<para>This is to create a variable of a certain
<literal>TemplateModel</literal> implementation.</para>
<para>On the left side of <literal>?</literal> you specify a string,
the full-qualified class name of a <literal>TemplateModel</literal>
implementation. The result is a method variable that calls the
constructor, and returns the new variable.</para>
<para>Example:</para>
<programlisting role="template">&lt;#-- Creates an user-defined directive be calling the parameterless constructor of the class --&gt;
&lt;#assign word_wrapp = "com.acmee.freemarker.WordWrapperDirective"?new()&gt;
&lt;#-- Creates an user-defined directive be calling the constructor with one numerical argument --&gt;
&lt;#assign word_wrapp_narrow = "com.acmee.freemarker.WordWrapperDirective"?new(40)&gt;</programlisting>
<para>For more information about how the constructor parameters are
unwrapped and how overloaded constructor is chosen, read: <xref
linkend="pgui_misc_beanwrapper"/></para>
<para>This built-in can be a security concern because the template
author can create arbitrary Java objects and then use them, as far
as they implement <literal>TemplateModel</literal>. Also the
template author can trigger static initialization for classes that
don't even implement <literal>TemplateModel</literal>. You can
(since 2.3.17) restrict the classes accessible with this built-in
using
<literal>Configuration.setNewBuiltinClassResolver(TemplateClassResolver)</literal>
or the <literal>new_builtin_class_resolver</literal> setting. See
the Java API docs for more information. If you are allowing
not-so-much-trusted users to upload templates then you should
definitely look into this topic.</para>
</section>
<section xml:id="ref_builtin_numToDate">
<title>number_to_date, number_to_time, number_to_datetime</title>
<indexterm>
<primary>type-casting</primary>
</indexterm>
<indexterm>
<primary>converting between types</primary>
</indexterm>
<indexterm>
<primary>number_to_date built-in</primary>
</indexterm>
<indexterm>
<primary>number_to_datetime built-in</primary>
</indexterm>
<indexterm>
<primary>number_to_time built-in</primary>
</indexterm>
<indexterm>
<primary>converting long to date</primary>
</indexterm>
<indexterm>
<primary>long to date</primary>
</indexterm>
<para>These are used to convert a number (usually a Java
<literal>long</literal>) to a date, time or date-time, respectively.
This does them same as <literal>new java.util.Date(long)</literal>
in Java, that is, the number is interpreted as the milliseconds
passed since the epoch. The number can be anything and of any type
as far as its value fits into a <literal>long</literal>. If the
number isn't a whole number, it will be rounded to whole with
half-up rule.</para>
<para>Example:</para>
<programlisting role="template">${1305575275540?number_to_datetime}
${1305575275540?number_to_date}
${1305575275540?number_to_time}</programlisting>
<para>The output will be something like this (depending on the
current locale and time zone):</para>
<programlisting role="output">May 16, 2011 3:47:55 PM
May 16, 2011
3:47:55 PM</programlisting>
</section>
<section xml:id="ref_builtin_sequence">
<title>sequence</title>
<indexterm>
<primary>seq_sequence built-in</primary>
</indexterm>
<para>This built-in is used to convert a listable value (one that
you can iterate through with the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link>) to a more capable <link
linkend="dgui_datamodel_container">sequence</link> value. Sequences
support operations like <literal>xs[index]</literal> and
<literal>xs?size</literal>. Also, the resulting value is listable
for multiple times, even if the original value was backed by a
<literal>java.util.Iterator</literal> (which gives error when you
try to list it for the 2nd time). This built-in is typically used to
work around data-model problems, in case you can't fix the
data-model itself. If you can, always fix the data-model instead
(give a <literal>java.util.List</literal> or array to the template
instead of a more restricted object, like a
non-<literal>List</literal> <literal>java.util.Collection</literal>,
or a <literal>java.util.Iterator</literal>).</para>
<para>If the value is already a sequence, then this built-in just
returns that as is. If the value is not something that the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link> could list, then template processing will be
aborted with error. Otherwise, it usually fetches all the values,
and stores them into a sequence. Be careful if you can have a huge
number of items, as all of them will be held in memory on the same
time. However, in some special cases fetching and/or storing all
elements is avoided; see about the <link
linkend="ref_builtin_sequence_optimizations">optimizations</link>
later.</para>
<para>You should convert a value with <literal>sequence</literal>
only once. If you need the resulting sequence at multiple places,
always assign the result to a variable, because if the value you
convert is only listable once, converting it for the second time
will result in error or an empty sequence. Also the conversion is
somewhat costly for big collections, so it's better to do it only
once.</para>
<para>Example: Let's say you find that <literal>users</literal> is
only listable once (because it's a
<literal>java.util.Iterator</literal>), but you need to list it for
multiple times in the template, and you can't fix the data-model.
Then you could do this:</para>
<programlisting role="template">&lt;#-- Collect all the users into a sequence: --&gt;
&lt;#assign usersSeq = users?sequence&gt;
&lt;#list usersSeq as user&gt;...&lt;/#list&gt;
Again:
&lt;#list usersSeq as user&gt;...&lt;/#list&gt;
</programlisting>
<simplesect xml:id="ref_builtin_sequence_optimizations">
<title>Optimizations</title>
<para>Since version 2.3.29, if the result of the
<literal>sequence</literal> built-in is directly the input of to
the <link
linkend="dgui_template_exp_var_sequence"><literal>[<replaceable>index</replaceable>]</literal></link>
or <link
linkend="dgui_template_exp_seqenceop_slice"><literal>[<replaceable>range</replaceable>]</literal></link>
operator, or of <literal>?size</literal>, or of
<literal>?first</literal>, or a chain of these operations, then
the elements will not be collected into the memory, and only as
many elements as strictly necessary will be fetched. For example
<literal>anIterator?sequence[1]</literal> will just fetch the
first 2 items (instead of building a sequence that contains all
the elements, and then getting the 2nd element from that). Or, if
you write <literal>anIterator?sequence?size</literal>, it will
just skip through all elements to count them, but won't store them
in memory.</para>
<para>The optimizations will only work within the same chain of
built-in calls, so for example in <literal>&lt;#assign seq =
anIterator?sequence&gt;${seq[1]}</literal> the
<literal>?sequence</literal> step will collect all the elements
into the memory, as <literal>anIterator?sequence</literal> and
<literal>seq[1]</literal> are separated. On the other hand, the
optimizations will work in
<literal>anIterator?sequence[10..]?size</literal>, as both
<literal>[<replaceable>range</replaceable>]</literal> and
<literal>?size</literal> supports it, and they are directly
chained together.</para>
</simplesect>
</section>
<section xml:id="ref_builtin_with_args">
<title>with_args</title>
<note>
<para>This built-in is available since 2.3.30</para>
</note>
<para>The goal of this built-in is to add parameters
<emphasis>dynamically</emphasis> to the call of a directive (like a
macro), function or method. Dynamically means that parameters are
added based on a hash value (like <literal>{'a': 1, 'b': 2, 'c':
3}</literal> or a Java <literal>Map</literal>), or a sequence value
(like <literal>[1, 2, 3]</literal> or a Java
<literal>List</literal>), whose actual content is might only known
at the moment when the call happens.</para>
<para>For example, we have this macro <literal>m</literal>:</para>
<programlisting role="template">&lt;#macro m a b c&gt;a=${a}, b=${b}, c=${c}&lt;/#macro&gt;</programlisting>
<para>Normally you call it like:</para>
<programlisting role="template">&lt;@m a=1 b=2 c=3 /&gt;</programlisting>
<para>Below call does the same, assuming <literal>dynArgs</literal>
is the hash <literal>{'a': 1, 'b': 2, 'c': 3}</literal>:</para>
<programlisting role="template">&lt;@m?with_args(dynArgs) /&gt;</programlisting>
<programlisting role="output">a=1, b=1, c=1</programlisting>
<para>Below call also does the same, but combines dynamic arguments
from <literal>dynArgsAB</literal>, assumed to be <literal>{'a': 1,
'b': 2}</literal>, and argument <literal>c</literal> specified
directly:</para>
<programlisting role="template">&lt;@m?with_args(dynArgsAB) c=3 /&gt;</programlisting>
<programlisting role="output">a=1, b=1, c=1</programlisting>
<para>To understand why this works, you need to realize that macros,
custom directives, functions, and methods in FreeMarker are just
values, just like numbers, strings, etc. <literal>&lt;#macro m
<replaceable>...</replaceable>&gt;</literal> just creates a value
that's a macro (as opposed to a number, or string, etc.), and then
assigns it to variable <literal>m</literal>. Thus,
<literal>m</literal> in itself is a valid expression, which
evaluates to the macro (but it doesn't <emphasis>call</emphasis> the
macro). <literal>&lt;@m <replaceable>...</replaceable>
/&gt;</literal> evaluates the expression <literal>m</literal> (and
you can use arbitrarily complex expressions there too, like
<literal>m?with_args(<replaceable>...</replaceable>)</literal>), and
then <emphasis>calls</emphasis> the resulting macro.
<literal>m?with_args(<replaceable>dynArgs</replaceable>)</literal>
returns a macro that's very similar to the original macro (that's
stored in <literal>m</literal>), but its arguments
<emphasis>default</emphasis> to the values specified in
<literal><replaceable>dynArgs</replaceable></literal>. So the result
of <literal>m?with_args({'b': 22, 'c': 33})</literal> is similar to
a modified macro that was created as <literal>&lt;#macro
<replaceable>unspefiedName</replaceable> a b=22 c=33&gt;</literal>.
With an example:</para>
<programlisting role="template">&lt;#assign mWithDefs = m?with_args({'b': 22, 'c': 33})&gt;
&lt;@myWithDefs a=1 c='overridden'/&gt;</programlisting>
<programlisting role="output">a=1, b=22, c=overridden</programlisting>
<para>Above we have created a new macro based on the value of
<literal>m</literal>, stored it in variable
<literal>mWithDefs</literal>, and then later we called it with
<literal>&lt;@myWithDefs <replaceable>...</replaceable>
/&gt;</literal>.</para>
<para><literal>with_args</literal> can also be applied on functions
(crated with <literal>&lt;#function
<replaceable>...</replaceable>&gt;</literal>) and Java methods
(usually get from the data-model, like
<literal>myObject.myMethod</literal>). But because functions and
methods can only be called with positional arguments (like
<literal>f(1, 2, 3)</literal>, and <emphasis>not</emphasis> as
<literal>f(a=1, b=2, c=3)</literal>), the argument to
<literal>with_args</literal> must be a sequence instead of a hash.
Other than that, the same tricks work as with macros:</para>
<programlisting role="template">&lt;#function f(a, b, c)&gt;&lt;#return "a=${a}, b=${b}, c=${c}"&gt;&lt;/#function&gt;
&lt;#assign dynArgs=[1, 2, 3]&gt;
${f(1, 2, 3)}
Same as:
${f?with_args(dynArgs)()}
or as:
${f?with_args([1, 2])(3)}
or as:
${f?with_args([1])(2, 3)}
&lt;#assign fWithOneAsFirstArg = f?with_args([1])&gt;
${fWithOneAsFirstArg(2, 3)} &lt;#-- same as f(1, 2, 3) --&gt;</programlisting>
<para>Note the double application of
<literal>(<replaceable>...</replaceable>)</literal> above, like in
<literal>f?with_args(<replaceable>dynArgs</replaceable>)()</literal>.
That's because
<literal>f?with_args(<replaceable>dynArgs</replaceable>)</literal>
just returns a new function (which is just a value), but doesn't
call it. So if you want to call that new function immediately (as
opposed to assigning it to a variable for example), you need the
second <literal>()</literal>.</para>
<para>Because macro calls support both named and positional
arguments, the <literal>with_args</literal> argument can be a
sequence for macros as well (though using a hash is usually a better
practice):</para>
<programlisting role="template">&lt;#macro m a b c&gt;a=${a}, b=${b}, c=${c}&lt;/#macro&gt;
&lt;#-- Called with named parameters: --&gt;
&lt;@m a=1 b=2 c=3 /&gt;
Same as:
&lt;#-- Called with positional parameters: --&gt;
&lt;@m 1 2 3 /&gt;
Same as:
&lt;@m?with_args([1, 2, 3]) /&gt;
Same as:
&lt;#-- Sequence with_args with positional c parameter: --&gt;
&lt;@m?with_args([1, 2]) 3 /&gt;
Same as:
&lt;#-- Sequence with_args with named c parameter: --&gt;
&lt;@m?with_args([1, 2]) c=3 /&gt;</programlisting>
<para>To summarize, depending on the type of the value
<literal>with_args</literal> is applied on, the type of argument to
<literal>with_args</literal> can be:</para>
<itemizedlist>
<listitem>
<para>Function or method: sequence. Note that WRONG
<literal>f?with_args(1, 2)</literal> is WRONG, the correct form
is <literal>f?with_args([1, 2])</literal>.</para>
</listitem>
<listitem>
<para>Macro: hash or sequence</para>
</listitem>
<listitem>
<para>Directive (user defined): hash</para>
</listitem>
</itemizedlist>
<para>The return type of <literal>with_args</literal> is the same as
the type of value it was applied on, like if it's applied on a
method (like <literal>myObj.myMethod?with_args(dynArgs)</literal>),
then it returns a method.</para>
<para>Note that it's not possible to apply
<literal>with_args</literal> on built-in directives, like
<literal>&lt;#if <replaceable>...</replaceable>&gt;</literal>,
<literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>,
etc., because they aren't available as values.</para>
<para>This built-in is often used together with the <link
linkend="specvar.args"><literal>.args</literal> special
variable</link>. For example:</para>
<programlisting role="template">&lt;#macro m1 a b c&gt;
m1 does things with ${a}, ${b}, ${c}
&lt;/#macro&gt;
&lt;#macro m2 a b c&gt;
m2 does things with ${a}, ${b}, ${c}
Delegate to m1:
&lt;@m1?with_args(.args) /&gt;
&lt;/#macro&gt;
&lt;@m2 a=1 b=2 c=3 /&gt;</programlisting>
<programlisting role="output"> m2 does things with 1, 2, 3
Delegate to m1:
m1 does things with 1, 2, 3</programlisting>
<para>FreeMarker syntax allows using the name before the
<literal>?with_args(<replaceable>...</replaceable>)</literal> in the
end-tag, just as if the
<literal>?with_args(<replaceable>...</replaceable>)</literal> wasn't
there:</para>
<programlisting role="template">&lt;@myMacro?with_args({'a': 1})&gt;...&lt;/<emphasis>@myMacro</emphasis>&gt;</programlisting>
<para>Note that as far as the order of arguments is concerned,
arguments coming from
<literal>with_args(<replaceable>...</replaceable>)</literal> are
added before the arguments specified in the call to the returned
directive/function/method. In some use cases it's more desirable to
add them at the end instead, in which case use the <link
linkend="ref_builtin_with_args_last"><literal>with_args_last</literal>
built-in</link>.</para>
</section>
<section xml:id="ref_builtin_with_args_last">
<title>with_args_last</title>
<note>
<para>This built-in is available since 2.3.30</para>
</note>
<para>Same as <link
linkend="ref_builtin_with_args"><literal>with_args</literal></link>,
but if the order of the arguments in resulting final argument list
may differs (but not the values in it). This only matters if you
pass parameters by position (typically, when calling functions or
methods), or when there's catch-all argument.</para>
<para>A typical example with positional arguments is when you want
to add the dynamic argument to the end of the parameter list:</para>
<programlisting role="template">&lt;#function f a b c d&gt;
&lt;#return "a=${a}, b=${b}, c=${c}, d=${d}"&gt;
&lt;/#function&gt;
&lt;#assign dynamicArgs=[3, 4]&gt;
with_args:
${f?with_args(dynamicArgs)(1, 2)}
with_args_last:
${f?with_args_last(dynamicArgs)(1, 2)}</programlisting>
<programlisting role="output">with_args:
a=3, b=4, c=1, d=2
with_args_last:
a=1, b=2, c=3, d=4</programlisting>
<para>In the case of name arguments, while the primary mean of
identifying an argument is the its name, catch-all arguments
(<literal>others...</literal> below) still have an order:</para>
<programlisting role="template">&lt;#macro m a b others...&gt;
a=${a}
b=${b}
others:
&lt;#list others as k, v&gt;
${k} = ${v}
&lt;/#list&gt;
&lt;/#macro&gt;
&lt;#assign dynamicArgs={'e': 5, 'f': 6}&gt;
with_args:
&lt;@m?with_args(dynamicArgs) a=1 b=2 c=3 d=4 /&gt;
with_args_last:
&lt;@m?with_args_last(dynamicArgs) a=1 b=2 c=3 d=4 /&gt;</programlisting>
<programlisting role="output">with_args:
a=1
b=2
others:
e = 5
f = 6
c = 3
d = 4
with_args_last:
a=1
b=2
others:
c = 3
d = 4
e = 5
f = 6</programlisting>
<para>If you specify a named parameter that are not catch-all, so
they are declared in the <literal>macro</literal> tag (as
<literal>a</literal> and <literal>b</literal> below), then
<literal>with_args</literal> and <literal>with_args_last</literal>
are no different, since the argument order is specified by the macro
definition, not the macro call:</para>
<programlisting role="template">&lt;#macro m a=0 b=0&gt;
&lt;#-- We use .args to demonstrate the ordering of a and b: --&gt;
&lt;#list .args as k, v&gt;
${k} = ${v}
&lt;/#list&gt;
&lt;/#macro&gt;
&lt;#assign dynamicArgs={'b': 1}&gt;
with_args:
&lt;@m?with_args(dynamicArgs) a=1 /&gt;
with_args_last:
&lt;@m?with_args_last(dynamicArgs) a=1 /&gt;</programlisting>
<programlisting role="output">with_args:
a = 1
b = 1
with_args_last:
a = 1
b = 1</programlisting>
<para>If both the macro or directive call, and the
<literal>with_args_last</literal> argument specifies named catch-all
argument with the same name (like <literal>b</literal> below), then
the placement of those parameters is decide by the macro/directive
call:</para>
<programlisting role="template">&lt;#macro m others...&gt;
&lt;#list others as k, v&gt;
${k} = ${v}
&lt;/#list&gt;
&lt;/#macro&gt;
&lt;#assign dynamicArgs={'b': 0, 'd': 4}&gt;
with_args:
&lt;@m?with_args(dynamicArgs) a=1 b=2 c=3 /&gt;
with_args_last:
&lt;@m?with_args_last(dynamicArgs) a=1 b=2 c=3 /&gt;</programlisting>
<programlisting role="output">with_args:
<emphasis> b = 2
d = 4
</emphasis> a = 1
c = 3
with_args_last:
a = 1
<emphasis> b = 2
</emphasis> c = 3
<emphasis> d = 4</emphasis></programlisting>
</section>
</section>
</chapter>
<chapter xml:id="ref_directives">
<title>Directive Reference</title>
<indexterm>
<primary>directive</primary>
</indexterm>
<section xml:id="ref_directive_alphaidx">
<title>Alphabetical index</title>
<note>
<para>As of FreeMarker 2.3.23, you can use camel case instead of
all-lower-case for directive names, like <literal>noParse</literal>
instead of <literal>noparse</literal>. But know that then within the
same template, FreeMarker will enforce the usage of camel case for
all identifiers that are part of the template language (user defined
names are not affected).</para>
</note>
<indexterm>
<primary>directive</primary>
</indexterm>
<itemizedlist spacing="compact">
<listitem>
<para><link linkend="ref.directive.assign">assign</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.attempt">attempt</link></para>
</listitem>
<listitem>
<para><link linkend="ref_directive_autoesc">autoesc</link></para>
</listitem>
<listitem>
<para>break: <link linkend="ref.directive.switch.break">in
switch</link>, <link linkend="ref.directive.list.break">in
list</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.case">case</link></para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.compress">compress</link></para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.list.continue">continue</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.default">default</link></para>
</listitem>
<listitem>
<para>else: <link linkend="ref.directive.else">in if</link>, <link
linkend="ref.directive.list.else">in list</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.elseif">elseif</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.escape">escape</link></para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.fallback">fallback</link></para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.function">function</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.flush">flush</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.ftl">ftl</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.global">global</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.if">if</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.import">import</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.include">include</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.items">items</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.list">list</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.local">local</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.lt">lt</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.macro">macro</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.nested">nested</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_directive_noautoesc">noautoesc</link></para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.noescape">noescape</link></para>
</listitem>
<listitem>
<para><link linkend="ref_directive_noparse">noparse</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.nt">nt</link></para>
</listitem>
<listitem>
<para><link
linkend="ref_directive_outputformat">outputformat</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.attempt">recover</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.recurse">recurse</link></para>
</listitem>
<listitem>
<para>return: <link linkend="ref.directive.macro.return">in
macro</link>, <link linkend="ref.directive.function.return">in
function</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.rt">rt</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.sep">sep</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.setting">setting</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.stop">stop</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.switch">switch</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.t">t</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.userDefined">User-defined
directive (&lt;@...&gt;)</link></para>
</listitem>
<listitem>
<para><link linkend="ref.directive.visit">visit</link></para>
</listitem>
</itemizedlist>
<para>If you don't find a directive here that you have seen in a
working template, probably you will find it in: <xref
linkend="ref_deprecated"/></para>
</section>
<section xml:id="ref_directive_assign">
<title>assign</title>
<anchor xml:id="ref.directive.assign"/>
<indexterm>
<primary>assign directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#assign <replaceable>name1</replaceable>=<replaceable>value1</replaceable> <replaceable>name2</replaceable>=<replaceable>value2</replaceable> <replaceable>... nameN</replaceable>=<replaceable>valueN</replaceable>&gt;</literal>
or
<literal>&lt;#assign <replaceable>same as above...</replaceable> in <replaceable>namespacehash</replaceable>&gt;</literal>
or
<literal>&lt;#assign <replaceable>name</replaceable>&gt;
<replaceable>capture this</replaceable>
&lt;/#assign&gt;</literal>
or
<literal>&lt;#assign <replaceable>name</replaceable> in <replaceable>namespacehash</replaceable>&gt;
<replaceable>capture this</replaceable>
&lt;/#assign&gt;</literal></programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: name
of the variable. It is not expression. However, it can be
written as a string literal, which is useful if the variable
name contains reserved characters, for example
<literal>&lt;#assign "foo-bar" = 1&gt;</literal>. Note that this
string literal does not expand interpolations (as
<literal>"${foo}"</literal>); if you need to assign to a
dynamically constructed name, the you have to use <link
linkend="faq_assign_to_dynamic_variable_name">a different
trick</link>. Note that because the FreeMarker template language
assumes that sequences (lists, arrays, etc.) and hashes (maps,
beans, etc.) are immutable, you can <emphasis>not</emphasis>
write something like <literal>&lt;#assign myObj.someProperty =
'will NOT work'&gt;</literal> or <literal>&lt;#assign myList[0]
= 'will NOT work'&gt;</literal>. However, adding sequences or
hashes with the <literal>+</literal> operator to form another
value is supported; see in the <link
linkend="exp_cheatsheet">chapter about expressions</link>, and
please note the performance consequences.</para>
</listitem>
<listitem>
<para><literal>=</literal>: Assignment operator. It can also be
one of the assignment shorthand operators (since FreeMarker
2.3.23): <literal>++</literal>, <literal>--</literal>,
<literal>+=</literal>, <literal>-=</literal>,
<literal>*=</literal>, <literal>/=</literal> or
<literal>%=</literal>. Like <literal>&lt;#assign
x++&gt;</literal> is similar to <literal>&lt;#assign x = x +
1&gt;</literal>, and <literal>&lt;#assign x += 2&gt;</literal>
is the same as <literal>&lt;#assign x = x + 2&gt;</literal>.
Note that <literal>++</literal> always means arithmetical
addition (an so it will fail on non-numbers), unlike
<literal>+</literal> or <literal>+=</literal> that are
overloaded to do string concatenation and such.</para>
</listitem>
<listitem>
<para><literal><replaceable>value</replaceable></literal>: the
value to store. Expression.</para>
</listitem>
<listitem>
<para><literal><replaceable>namespacehash</replaceable></literal>:
a hash that was created for a <link
linkend="dgui_misc_namespace">namespace</link> (by <link
linkend="ref.directive.import"><literal>import</literal></link>).
Expression. If not specified, it defaults to the namespace that
belongs to the containing template.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>With this you can create a new variable, or replace an
existing variable. Note that only top-level variables can be
created/replaced (i.e. you can't create/replace
<literal>some_hash.subvar</literal>, but
<literal>some_hash</literal>).</para>
<para>For more information about variables, read this: <xref
linkend="dgui_misc_var"/></para>
<note>
<para>A frequent mistake is trying to use
<literal>assign</literal> to change a local variable like:
<literal>&lt;#macro m&gt;&lt;#local x = 1&gt;${x}&lt;#assign x =
2&gt;${x}&lt;/#macro&gt;</literal>. This prints
<literal>11</literal>, not <literal>12</literal>, because
<literal>assign</literal> creates/replaces the
<literal>x</literal> of the namespace that the template belongs
to, and doesn't change the <literal>x</literal> local variable.
Local variables should be always set with the <link
linkend="ref.directive.local"><literal>local</literal>
directive</link>, not just for the fist time.</para>
</note>
<para>Example: variable <literal>seq</literal> will store a
sequence:</para>
<programlisting role="template">&lt;#assign seq = ["foo", "bar", "baz"]&gt;</programlisting>
<para>Example: Increments the numerical value stored in variable
<literal>x</literal>:</para>
<programlisting role="template">&lt;#assign x++&gt;</programlisting>
<para>As a convenience feature, you can do more assignments with one
<literal>assign</literal> tag. For example this will do the same as
the two previous examples:</para>
<programlisting role="template">&lt;#assign
seq = ["foo", "bar", "baz"]
x++
&gt;</programlisting>
<para>If you know what namespaces are: <literal>assign</literal>
directive creates variables in a namespace. Normally it creates the
variable in the current namespace (i.e. in the namespace associated
with the template where the tag is). However, if you use <literal>in
<replaceable>namespacehash</replaceable></literal> then you can
create/replace a variable of another <link
linkend="dgui_misc_namespace">namespace</link> than the current
namespace. For example, here you create/replace variable
<literal>bgColor</literal> of the namespace used for
<literal>/mylib.ftl</literal>:</para>
<programlisting role="template">&lt;#import "/mylib.ftl" as my&gt;
&lt;#assign bgColor="red" in my&gt;</programlisting>
<para>An extreme usage of <literal>assign</literal> is when it
captures the output generated between its start-tag and end-tag.
That is, things that are printed between the tags will not be shown
on the page, but will be stored in the variable. For example:</para>
<programlisting role="template">&lt;#macro myMacro&gt;foo&lt;/#macro&gt;
&lt;#assign x&gt;
&lt;#list 1..3 as n&gt;
${n} &lt;@myMacro /&gt;
&lt;/#list&gt;
&lt;/#assign&gt;
Number of words: ${x?word_list?size}
${x}</programlisting>
<para>will print:</para>
<programlisting role="output">Number of words: 6
1 foo
2 foo
3 foo
</programlisting>
<para>Please note that you should not to use this to insert
variables into strings:</para>
<programlisting role="template">&lt;#assign x&gt;Hello ${user}!&lt;/#assign&gt; &lt;#-- BAD PRACTICE! --&gt;</programlisting>
<para>You should simply write:</para>
<programlisting role="template">&lt;#assign x="Hello ${user}!"&gt;</programlisting>
</section>
</section>
<section xml:id="ref_directive_attempt">
<title>attempt, recover</title>
<anchor xml:id="ref.directive.attempt"/>
<indexterm>
<primary>attempt directive</primary>
</indexterm>
<indexterm>
<primary>recover directive</primary>
</indexterm>
<indexterm>
<primary>error handling</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#attempt&gt;
<replaceable>attempt block</replaceable>
&lt;#recover&gt;
<replaceable>recover block</replaceable>
&lt;/#attempt&gt;
</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>attempt
block</replaceable></literal>: Template block with any content.
This will be always executed, but if an error occurs during
that, all output from this block is rolled back, and the
<literal><replaceable>recover block</replaceable></literal> will
be executed.</para>
</listitem>
<listitem>
<para><literal><replaceable>recover
block</replaceable></literal>: Template block with any content.
This will be executed only if there was an error during the
execution of the <literal><replaceable>attempt
block</replaceable></literal>. You may print an error messages
here and such.</para>
</listitem>
</itemizedlist>
<para>The <literal><replaceable>recover</replaceable></literal> is
mandatory. <literal>attempt</literal>/<literal>recover</literal> can
be nested freely into other <literal><replaceable>attempt
block</replaceable></literal>s or <literal><replaceable>recover
block</replaceable></literal>s.</para>
<note>
<para>The format shown here is supported starting from 2.3.3;
earlier it was
<literal>&lt;#attempt&gt;<replaceable>...</replaceable>&lt;#recover&gt;<replaceable>...</replaceable>&lt;/#recover&gt;</literal>,
which is still supported for backward compatibility. Furthermore,
these directives were introduced with FreeMarker 2.3.1, so they
aren't exist in 2.3.</para>
</note>
</section>
<section>
<title>Description</title>
<para>These directives are used if you want the page successfully
outputted even if the outputting of a certain part of the page
fails. If an error occurs during the execution of the
<literal><replaceable>attempt block</replaceable></literal>, then
the output of the <literal><replaceable>attempt
block</replaceable></literal> is rolled back <phrase
role="forProgrammers">(and the error is logged, with the default
configuration at least)</phrase>, and the
<literal><replaceable>recover block</replaceable></literal> is
executed instead, then template execution continues normally after
the <literal><replaceable>recover block</replaceable></literal>. If
no error occurs during the execution of the
<literal><replaceable>attempt block</replaceable></literal>, then
the <literal><replaceable>recover block</replaceable></literal> is
ignored. A simple example:</para>
<programlisting role="template">Primary content
&lt;#attempt&gt;
Optional content: ${thisMayFails}
&lt;#recover&gt;
Ops! The optional content is not available.
&lt;/#attempt&gt;
Primary content continued</programlisting>
<para>If the <literal>thisMayFails</literal> variable doesn't exist
(or any other error occurs at that place), then the output
is:</para>
<programlisting role="output">Primary content
Ops! The optional content is not available.
Primary content continued</programlisting>
<para>If the <literal>thisMayFails</literal> variable exists and
it's value is <literal>123</literal>, then the output is:</para>
<programlisting role="output">Primary content
Optional content: 123
Primary content continued</programlisting>
<para>The <literal><replaceable>attempt
block</replaceable></literal> has an all-or-none semantic: either
the entire content of the <literal><replaceable>attempt
block</replaceable></literal> is output (when there was no error),
or no output at all results from the execution of the
<literal><replaceable>attempt block</replaceable></literal> (when
there was an error). For example, above, the failure happens after
<quote>Optional content: </quote> was printed, still it is not there
in the output before the <quote>Ops!</quote>. (<phrase
role="forProgrammers">This is implemented with the aggressive
buffering of the output inside the <literal><replaceable>attempt
block</replaceable></literal>. Not even the <literal>flush</literal>
directive will send the output to the client.</phrase>)</para>
<para>To prevent misunderstandings coming from the above example:
<literal>attempt</literal>/<literal>recover</literal> is not (only)
for handling undefined variables (for that use <link
linkend="dgui_template_exp_missing">missing value handler
operators</link>). It can handle all kind of errors that occurs when
the block is executed (i.e. not syntactical errors, which are
detected earlier). It meant to enclose bigger template fragments,
where error can occur at various points. For example, you have a
part in your template that deals with printing advertisements, but
that's not the primary content of the page, so you don't want your
whole page be down just because some error occurs with the printing
of the advertisements (say, because of a database server outage). So
you put the whole advertisement printing into an
<literal><replaceable>attempt block</replaceable></literal>.</para>
<para>In some environments programmers configure FreeMarker so that
it doesn't abort template execution for certain errors, but
continues execution, possibly after printing some error indicator to
the output (<phrase role="forProgrammers">see more <link
linkend="pgui_config_errorhandling">here...</link></phrase>). The
<literal>attempt</literal> directive doesn't consider such
suppressed errors as errors.</para>
<para>Inside a <literal><replaceable>recover
block</replaceable></literal> the error message of the error is
available with the <literal>error</literal> <link
linkend="ref_specvar">special variable</link>. Don't forget that
references to special variable are started with dot (for example:
<literal>${.error}</literal>).</para>
<para><phrase role="forProgrammers">By default errors occurring
inside an <literal><replaceable>attempt
block</replaceable></literal> are <link
linkend="pgui_misc_logging">logged</link> with
<literal>ERROR</literal> level, despite that the template recovers
from them. This is because <literal>attempt</literal> is not meant
to be a general purpose error handler mechanism, like
<literal>try</literal> is in Java. It's for decreasing the impact of
unexpected errors on the visitors, by making it possible that only
part of the page is going down, instead of the whole page. But it's
still an error, something that needs the attention of the operators.
(The way this error is reported can be customized with the
<literal>attempt_exception_reporter</literal> configuration setting,
since FreeMarker 2.3.27.)</phrase></para>
</section>
</section>
<section xml:id="ref_directive_autoesc">
<title>autoesc</title>
<anchor xml:id="ref.directive.autoesc"/>
<indexterm>
<primary>autoesc directive</primary>
</indexterm>
<indexterm>
<primary>auto-escaping</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#autoesc&gt;
<replaceable>...</replaceable>
&lt;/#autoesc&gt;</literal>
</programlisting>
<para>Camel case name variant: <literal>autoEsc</literal></para>
</section>
<section>
<title>Description</title>
<para>Turns on <link
linkend="dgui_misc_autoescaping">auto-escaping</link> in the nested
section. Auto-escaping is usually enabled by default if the current
<link linkend="dgui_misc_autoescaping_outputformat">output
format</link> has auto-escaping by default, so you rarely need this.
Note that to escape just a single
<literal>${<replaceable>expression</replaceable>}</literal> where
auto-escaping is disabled you should use
<literal>${<replaceable>expression</replaceable>?esc}</literal>
instead.</para>
<para>This directive only has effect on the section that is
literally (as in the text editor) inside the nested bock, not on the
parts that are called/included from there.</para>
<para>Example:</para>
<programlisting role="template">&lt;#ftl output_format="XML" auto_esc=false&gt;
${"&amp;"}
&lt;#autoesc&gt;
${"&amp;"}
...
${"&amp;"}
&lt;/#autoesc&gt;
${"&amp;"}</programlisting>
<programlisting role="output">&amp;
&amp;amp;
...
&amp;amp;
&amp;</programlisting>
<para><literal>autoesc</literal> can't be used where the current
<link linkend="dgui_misc_autoescaping_outputformat">output
format</link> is a <link
linkend="dgui_misc_autoescaping_nonmarkupof">non-markup output
format</link> (and hence can't do escaping). Doing so is a <link
linkend="gloss.parseTimeError">parse-time error</link>.</para>
<para><literal>autoesc</literal> can also be used nested into <link
linkend="ref_directive_noautoesc"><literal>noautoesc</literal>
directive</link> to re-enable auto-escaping.</para>
<para><literal>autoesc</literal> can be used on places where
auto-escaping is already enabled, such as even inside another
<literal>autoesc</literal> block. Doing so is redundant but
allowed.</para>
</section>
</section>
<section xml:id="ref_directive_compress">
<title>compress</title>
<anchor xml:id="ref.directive.compress"/>
<indexterm>
<primary>compress directive</primary>
</indexterm>
<indexterm>
<primary>white-space removal</primary>
<secondary>compress</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#compress&gt;
<replaceable>...</replaceable>
&lt;/#compress&gt;</literal>
</programlisting>
</section>
<section>
<title>Description</title>
<para>The compress directive is useful for removing superfluous
<link linkend="gloss.whiteSpace">white-space</link> when you use a
white-space insensitive format (e.g. HTML or XML). It captures the
output generated inside its body (i.e. between its start-tag and
end-tag), and reduces all unbroken white-space sequences to a single
white-space character. The inserted character will be a <link
linkend="gloss.lineBreak">line break</link> if the replaced sequence
contains line breaks, or a space otherwise. The very first and very
last unbroken white-space sequences will be completely
removed.</para>
<programlisting role="template">&lt;#assign x = " moo \n\n "&gt;
(&lt;#compress&gt;
1 2 3 4 5
${moo}
test only
I said, test only
&lt;/#compress&gt;)</programlisting>
<para>will output:</para>
<programlisting role="output">(1 2 3 4 5
moo
test only
I said, test only)</programlisting>
</section>
</section>
<section xml:id="ref_directive_escape">
<title>escape, noescape (deprecated)</title>
<anchor xml:id="ref.directive.escape"/>
<anchor xml:id="ref.directive.noescape"/>
<indexterm>
<primary>escape directive</primary>
</indexterm>
<indexterm>
<primary>noescape directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#escape <replaceable>identifier</replaceable> as <replaceable>expression</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#noescape&gt;<replaceable>...</replaceable>&lt;/#noescape&gt;
<replaceable>...</replaceable>
&lt;/#escape&gt;</literal>
</programlisting>
<para>Camel case name variant: <literal>noEscape</literal></para>
</section>
<section>
<title>Description</title>
<note>
<para>These directives are <emphasis>deprecated</emphasis> by
<link linkend="dgui_misc_autoescaping">output-format-based
auto-escaping</link> since 2.3.24. Furthermore, on places that use
auto-escaping (with an output format that actually does escaping)
you aren't allowed to use the <literal>escape</literal> directive
(as you will find out from the parsing error message
anyway).</para>
</note>
<para>When you surround a part of the template with an escape
directive, interpolations
(<literal>${<replaceable>...</replaceable>}</literal>) that occur
inside the block are combined with the escaping expression
automatically. This is a convenience method for avoiding writing
similar expressions all over. It does not affect interpolations in
string literals (as in <literal>&lt;#assign x =
"Hello ${user}!"&gt;</literal>). Also, it does not affect numerical
interpolations
(<literal>#{<replaceable>...</replaceable>}</literal>).</para>
<para>Example:</para>
<programlisting role="template"><emphasis>&lt;#escape x as x?html&gt;</emphasis>
First name: ${firstName}
Last name: ${lastName}
Maiden name: ${maidenName}
<emphasis>&lt;/#escape&gt;</emphasis></programlisting>
<para>is actually equivalent to:</para>
<programlisting role="template"> First name: ${firstName<emphasis>?html</emphasis>}
Last name: ${lastName<emphasis>?html</emphasis>}
Maiden name: ${maidenName<emphasis>?html</emphasis>}</programlisting>
<para>Note that it is irrelevant what identifier you use in the
directive - it just serves as a formal parameter to the escaping
expression.</para>
<para>When you are calling macros or the <literal>include</literal>
directive, it is important to understand that escape has effect only
on interpolations that occur between the <literal>&lt;#escape
<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#escape&gt;</literal> <emphasis>in the template
text</emphasis>. That is, it will not escape anything that is before
<literal>&lt;#escape <replaceable>...</replaceable>&gt;</literal> in
the text, or after the <literal>&lt;/#escape&gt;</literal> in the
text, not even if that part is called from inside the
<literal>escape</literal>-d section.</para>
<programlisting role="template">&lt;#assign x = "&lt;test&gt;"&gt;
&lt;#macro m1&gt;
m1: ${x}
&lt;/#macro&gt;
&lt;#escape x as x?html&gt;
&lt;#macro m2&gt;m2: ${x}&lt;/#macro&gt;
${x}
&lt;@m1/&gt;
&lt;/#escape&gt;
${x}
&lt;@m2/&gt;</programlisting>
<para>the output will be:</para>
<programlisting role="output"> &amp;lt;test&amp;gt;
m1: &lt;test&gt;
&lt;test&gt;
m2: &amp;lt;test&amp;gt;</programlisting>
<para><phrase role="forProgrammers">More technically, the effects of
<literal>escape</literal> directive are applied at template parsing
time rather than at template processing time. This means that if you
call a macro or include another template from within an escape
block, it won't affect the interpolations in the macro/included
template, since macro calls and template includes are evaluated at
template processing time. On the other hand, if you surround one or
more macro declarations (which are evaluated at template parsing
time, as opposed to macro calls) with an escape block, the
interpolations in those macros will be combined with the escaping
expression.</phrase></para>
<para>Sometimes there is a need to temporarily turn off escaping for
one or two interpolations in an escape block. You can achieve this
by closing and later reopening the escape block, but then you have
to write the escaping expression twice. You can instead use the
noescape directive:</para>
<programlisting role="template">&lt;#escape x as x?html&gt;
From: ${mailMessage.From}
Subject: ${mailMessage.Subject}
<emphasis>&lt;#noescape&gt;</emphasis>Message: ${mailMessage.htmlFormattedBody}<emphasis>&lt;/#noescape&gt;</emphasis>
<replaceable>...</replaceable>
&lt;/#escape&gt;</programlisting>
<para>is equivalent to:</para>
<programlisting role="template"> From: ${mailMessage.From?html}
Subject: ${mailMessage.Subject?html}
Message: ${mailMessage.htmlFormattedBody}
...</programlisting>
<para>Escapes can be nested (although you will do it only in rare
circumstances). Therefore, you can write something like the below
code (the example is admittedly a bit stretched, as you'd probably
place item codes in a sequence and use <literal>list</literal> to
iterate over them, but we're now doing it this way just to
illustrate the point):</para>
<programlisting role="template"><emphasis>&lt;#escape x as x?html&gt;</emphasis>
Customer Name: ${customerName}
Items to ship:
<emphasis>&lt;#escape x as itemCodeToNameMap[x]&gt;</emphasis>
${itemCode1}
${itemCode2}
${itemCode3}
${itemCode4}
<emphasis>&lt;/#escape&gt;</emphasis>
<emphasis>&lt;/#escape&gt;</emphasis></programlisting>
<para>is actually equivalent to:</para>
<programlisting role="template"> Customer Name: ${customerName?html}
Items to ship:
${itemCodeToNameMap[itemCode1]?html}
${itemCodeToNameMap[itemCode2]?html}
${itemCodeToNameMap[itemCode3]?html}
${itemCodeToNameMap[itemCode4]?html}</programlisting>
<para>When you use the noescape directive in a nested escape block,
it undoes only a single level of escaping. Therefore, to completely
turn off escaping in a two-level deep escaped block, you need to use
two nested noescape directives as well.</para>
</section>
</section>
<section xml:id="ref_directive_flush">
<title>flush</title>
<anchor xml:id="ref.directive.flush"/>
<indexterm>
<primary>flush directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#flush&gt;</literal></programlisting>
</section>
<section>
<title>Description</title>
<para>When FreeMarker generates the output, it's usually not sent
immediately to the final receiving party (like a web browser or a
destination file), but is accumulated in a buffer, then it's sent
out in bigger chunks. The exact rules of the buffering is not
decided by FreeMarker, but by the embedding software. Sending out
the content accumulated in the buffer is called flushing. Although
flushing happens automatically, sometimes you want to force it on
certain points of the template processing, and this is what the
<literal>flush</literal> directive does. Whether it's needed at
certain points should be decided by a programmer, not a
designer.</para>
<para>Note that while <literal>flush</literal> tells the embedding
software that we want to flush, that might as well decides to ignore
this request. It's not in the hands of FreeMarker.</para>
<para><phrase role="forProgrammers">Flush simply calls the
<literal>flush()</literal> method of the currently used
<literal>java.io.Writer</literal> instance. The whole buffering and
flushing mechanism is implemented in the <literal>Writer</literal>
(that you have passed as the parameter of the
<literal>Template.process</literal> method); FreeMarker does not
deal with it.</phrase></para>
</section>
</section>
<section xml:id="ref_directive_ftl">
<title>ftl</title>
<anchor xml:id="ref.directive.ftl"/>
<indexterm>
<primary>ftl directive</primary>
</indexterm>
<indexterm>
<primary>header</primary>
</indexterm>
<indexterm>
<primary>charset</primary>
</indexterm>
<indexterm>
<primary>encoding</primary>
</indexterm>
<indexterm>
<primary>white-space removal</primary>
<secondary>stripping</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#ftl <replaceable>param1</replaceable>=<replaceable>value1</replaceable> <replaceable>param2</replaceable>=<replaceable>value2</replaceable> <replaceable>...</replaceable> <replaceable>paramN</replaceable>=<replaceable>valueN</replaceable>&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>param1</replaceable></literal>,
<literal><replaceable>param2</replaceable></literal>, ...etc.:
Name of the parameter. Not an expression. Allowed parameters
are: <literal>encoding</literal>,
<literal>strip_whitespace</literal>,
<literal>strip_text</literal>, ...etc. See below.</para>
</listitem>
<listitem>
<para><literal><replaceable>value1</replaceable></literal>,
<literal><replaceable>value2</replaceable></literal>, ...etc.:
The value of parameter. This must be a constant expression (as
<literal>true</literal>, or <literal>"ISO-8859-5"</literal>, or
<literal>{x:1, y:2}</literal>). It can't use variables.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>Tells information about the template for FreeMarker and for
other tools, also helps programs to automatically detect if a text
file is an FTL file. This directive, if present, must be the very
first thing in the template. Any <link
linkend="gloss.whiteSpace">white-space</link> before this directive
will be ignored. The old-syntax (<literal>#</literal>-less) format
of this directive is not supported.</para>
<para>The settings (encoding, white-space stripping, etc.) given
here has the highest precedence, that is, they will be used for the
template regardless of any FreeMarker configuration settings.</para>
<para>Possible parameters:</para>
<itemizedlist>
<listitem>
<para><literal>attributes</literal>: This is a hash that
associates arbitrary attributes (name-value pairs) to the
template. The values of the attributes can be of any type
(string, number, sequence... etc.). FreeMarker doesn't try to
understand the meaning of the attributes. It's up to the
application that encapsulates FreeMarker (as a Web application
framework). Thus, the set of allowed attributes and their
semantic is application (Web application framework) dependent.
<phrase role="forProgrammers">Programmers: you can get the
attributes associated with a <literal>Template</literal> object
with its <literal>getCustomAttributeNames</literal> and
<literal>getCustomAttribute</literal> methods (inherited from
<literal>freemarker.core.Configurable</literal>). As the
template attributes are associated with the
<literal>Template</literal> object when the template is parsed,
the attributes can be read anytime, the template need not be
executed. The methods mentioned return the attribute values
unwrapped, that is, with FreeMarker independent type as
<literal>java.util.List</literal>.</phrase></para>
</listitem>
<listitem>
<para><literal>auto_esc</literal>: A boolean constant to turn
<link linkend="dgui_misc_autoescaping">auto-escaping</link> on
or off. It depends on the
<literal>auto_escaping_policy</literal> of the FreeMarker
configuration, but usually auto-escaping will be by default on,
if the current <link
linkend="dgui_misc_autoescaping_outputformat">output
format</link> uses auto-escaping by default. So you mostly use
this to disable auto-escaping (<literal>false</literal> value).
An attempt to use <literal>true</literal> value when the current
output format is a <link
linkend="dgui_misc_autoescaping_nonmarkupof">non-markup output
format</link> (which hence can't escape) will cause <link
linkend="gloss.parseTimeError">parse-time error</link>. Note
that you can turn auto-escaping on/off for only a part of the
template with the <link
linkend="ref_directive_autoesc"><literal>autoesc</literal></link>
and <link
linkend="ref_directive_noautoesc"><literal>noautoesc</literal>
directives</link>.</para>
</listitem>
<listitem>
<para><literal>encoding</literal>: With this you can specify the
encoding (charset) of the template in the template file itself.
<phrase role="forProgrammers">(That is, this will be the
<literal>encoding</literal> setting of the newly created
<literal>Template</literal>, and not even the
<literal>encoding</literal> parameter to
<literal>Configuration.getTemplate</literal> can override
it)</phrase>. Note however, that FreeMarker will try to find and
interpret the <literal>ftl</literal> directive first with the
automatically guessed encoding (which depends on the FreeMarker
configuration set by the programmers), and only then realizes if
the <literal>ftl</literal> directive dictates something
different, and re-read the template with the new encoding. Thus,
the template must be valid FTL until the end of
<literal>ftl</literal> tag with the encoding tried first. The
valid values of this parameter are MIME-preferred charset names
from the IANA Charset Registry, like ISO-8859-5, UTF-8 or
Shift_JIS.</para>
</listitem>
<listitem>
<para><literal>ns_prefixes</literal>: This is a hash that
associates prefixes with node namespaces. For example:
<literal>{"e":"http://example.com/ebook",
"vg":"http://example.com/vektorGraphics"}</literal>. This is
mostly used with XML processing where the prefixes can be used
in XML queries, but it also influences the working of <link
linkend="ref_directive_visit">directives
<literal>visit</literal> and <literal>recurse</literal></link>.
Only one prefix can be registered for the same node namespace
(otherwise an error will occur), so there is one-to-one relation
between prefixes and node namespaces. Prefixes
<literal>D</literal> and <literal>N</literal> are reserved. If
you register prefix <literal>D</literal>, then other than you
associate the node namespace with prefix <literal>D</literal>,
you also set the default node namespace. Prefix
<literal>N</literal> can't be registered; it is used to denote
nodes with no node namespace in certain places, when (and only
when) prefix <literal>D</literal> is registered. (To see the
usage of default node namespace, <literal>N</literal>, and
prefixes in general, see the part about <link linkend="xgui">XML
processing</link> and <link
linkend="ref_directive_visit"><literal>visit</literal> and
<literal>recurse</literal></link> in the reference.) The effect
of <literal>ns_prefixes</literal> is limited to a single <link
linkend="dgui_misc_namespace">FTL namespace</link>, namely, to
the FTL namespace that was created for the template. This also
means that <literal>ns_prefixes</literal> has effect only when
an FTL namespace is created for the template that contains it,
otherwise the <literal>ns_prefixes</literal> parameter has no
effect. An FTL namespace is made for a template when: (a) the
template is the <quote>main</quote> template, that is, it is not
invoked as a result of an <literal>&lt;#include
...&gt;</literal>, but it is directly invoked (<phrase
role="forProgrammers">with the <literal>process</literal> Java
method of class <literal>Template</literal> or
<literal>Environment</literal></phrase>); (b) the template is
invoked directly with <literal>&lt;#import
...&gt;</literal>.</para>
</listitem>
<listitem>
<para><literal>output_format</literal>: Specifies the <link
linkend="dgui_misc_autoescaping_outputformat">output
format</link> of this template. This must be a string literal,
which refers to the name of the output format. See the <link
linkend="topic.predefinedOutputFormats">table of predefined
output formats here</link>. Other names can exist if the
programmers has added them via the
<literal>registered_custom_output_formats</literal>
configuration setting
(<literal>Configuration.setRegisteredCustomOutputFormats(<replaceable>...</replaceable>)</literal>).
The referred output format must be known by the
<literal>Configuration</literal>, or else a <link
linkend="gloss.parseTimeError">parse-time error </link>will
occur. The name can also refer to a so called combined output
format as
<literal>"<replaceable>outerFormatName</replaceable>{<replaceable>innerFormatName</replaceable>}"</literal>;
<link linkend="topic.combinedOutputFormats">see more about
combined output formats here</link>.</para>
</listitem>
<listitem>
<para><literal>strict_syntax</literal>: This turns on/off
<quote>strict syntax</quote>, which is the standard syntax after
FreeMarker 2.1. Valid values are the boolean constants
<literal>true</literal> and <literal>false</literal>. (And for
backward compatibility, strings <literal>"yes"</literal>,
<literal>"no"</literal>, <literal>"true"</literal>,
<literal>"false"</literal>). The default value (i.e., when you
don't use this parameter) depends on the FreeMarker
configuration set by the programmers, but it's most certainly
set to <literal>true</literal>. For more information read: <xref
linkend="ref_depr_oldsyntax"/></para>
</listitem>
<listitem>
<para><literal>strip_text</literal>: When enabled, all top-level
text in a template is removed when the template is parsed. This
does not affect text within macros, directives, or
interpolations. Valid values are the boolean constants
<literal>true</literal> and <literal>false</literal>. (And for
backward compatibility, strings <literal>"yes"</literal>,
<literal>"no"</literal>, <literal>"true"</literal>,
<literal>"false"</literal>). The default value (i.e. when you
don't use this parameter) is <literal>false</literal>.</para>
</listitem>
<listitem>
<para><literal>strip_whitespace</literal>: This enables/disables
<link linkend="dgui_misc_whitespace_stripping">white-space
stripping</link>. Valid values are the boolean constants
<literal>true</literal> and <literal>false</literal>. (And for
backward compatibility, strings <literal>"yes"</literal>,
<literal>"no"</literal>, <literal>"true"</literal>,
<literal>"false"</literal>). The default value (i.e. when you
don't use this parameter) depends on the FreeMarker
configuration set by the programmers, but it should be
<literal>true</literal> for new projects.</para>
</listitem>
</itemizedlist>
<note>
<para>As of FreeMarker 2.3.23, you can use camel case instead of
snake case for parameter names, like
<literal>outputFormat</literal> instead of
<literal>output_format</literal>. But know that then within the
same template, FreeMarker will enforce the usage of camel case for
all identifiers that are part of the template language (user
defined names are not affected).</para>
</note>
<para>This directive also determines if the template uses angle
bracket syntax (e.g. <literal>&lt;#include 'foo.ftl'&gt;</literal>)
or <link linkend="dgui_misc_alternativesyntax">square bracket
syntax</link> (e.g. <literal>[#include 'foo.ftl']</literal>).
Simply, the syntax used for this directive will be the syntax used
for the whole template, regardless of the FreeMarker configuration
settings.</para>
</section>
</section>
<section xml:id="ref_directive_function">
<title>function, return</title>
<anchor xml:id="ref.directive.function"/>
<anchor xml:id="ref.directive.function.return"/>
<indexterm>
<primary>function directive</primary>
</indexterm>
<indexterm>
<primary>return directive</primary>
</indexterm>
<indexterm>
<primary>method</primary>
<secondary>defining with FTL</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#function <replaceable>name</replaceable> <replaceable>param1</replaceable> <replaceable>param2</replaceable> <replaceable>... paramN</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#return <replaceable>returnValue</replaceable>&gt;
<replaceable>...</replaceable>
&lt;/#function&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: name
of method variable (not expression)</para>
</listitem>
<listitem>
<para><literal><replaceable>param1</replaceable></literal>,
<literal><replaceable>param2</replaceable></literal>, ...etc.:
the name of the <link linkend="dgui_misc_var">local
variables</link> store the parameter values (not expression),
optionally followed by <literal>=</literal> and the default
value (that's an expression).</para>
</listitem>
<listitem>
<para><literal><replaceable>paramN</replaceable></literal>, the
last parameter, may optionally include a trailing ellipsis
(<literal>...</literal>), which indicates the macro takes a
variable number of parameters. Local variable
<literal><replaceable>paramN</replaceable></literal> will be a
sequence of the extra parameters.</para>
</listitem>
<listitem>
<para><literal><replaceable>returnValue</replaceable></literal>:
the expression that calculates the value of the method
call.</para>
</listitem>
</itemizedlist>
<para>The <literal>return</literal> directive can be used anywhere
and for any times between the <literal>&lt;#function
<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#function&gt;</literal>.</para>
<para>Parameters without default value must precede parameters with
default value
(<literal><replaceable>paramName</replaceable>=<replaceable>defaultValue</replaceable></literal>).</para>
</section>
<section>
<title>Description</title>
<para>Creates a method variable (in the current namespace, if you
know namespace feature). This directive works in the same way as the
<link linkend="ref.directive.macro"><literal>macro</literal>
directive</link>, except that <literal>return</literal> directive
<emphasis>must</emphasis> have a parameter that specifies the return
value of the method, and that attempts to write to the output will
be ignored. If the <literal>&lt;/#function&gt;</literal> is reached
(i.e. there was no <literal>return
<replaceable>returnValue</replaceable></literal>), then the return
value of the method is an undefined variable.</para>
<para>Example 1: Creating a method that calculates the average of
two numbers:</para>
<programlisting role="template">&lt;#function avg x y&gt;
&lt;#return (x + y) / 2&gt;
&lt;/#function&gt;
${avg(10, 20)}</programlisting>
<para>will print:</para>
<programlisting role="output">15</programlisting>
<para>Example 2: Creating a method that calculates the average of
multiple numbers:</para>
<programlisting role="template">&lt;#function avg nums...&gt;
&lt;#local sum = 0&gt;
&lt;#list nums as num&gt;
&lt;#local sum += num&gt;
&lt;/#list&gt;
&lt;#if nums?size != 0&gt;
&lt;#return sum / nums?size&gt;
&lt;/#if&gt;
&lt;/#function&gt;
${avg(10, 20)}
${avg(10, 20, 30, 40)}
${avg()!"N/A"}</programlisting>
<para>will print:</para>
<programlisting role="output">15
25
N/A</programlisting>
</section>
</section>
<section xml:id="ref_directive_global">
<title>global</title>
<anchor xml:id="ref.directive.global"/>
<indexterm>
<primary>global directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#global <replaceable>name</replaceable>=<replaceable>value</replaceable>&gt;</literal>
or
<literal>&lt;#global <replaceable>name1</replaceable>=<replaceable>value1</replaceable> <replaceable>name2</replaceable>=<replaceable>value2</replaceable> <replaceable>... nameN</replaceable>=<replaceable>valueN</replaceable>&gt;</literal>
or
<literal>&lt;#global <replaceable>name</replaceable>&gt;
<replaceable>capture this</replaceable>
&lt;/#global&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: name
of the variable. It is not expression. However, it can be
written as a string literal, which is useful if the variable
name contains reserved characters, for example
<literal>&lt;#global "foo-bar" = 1&gt;</literal>. Note that this
string literal does not expand interpolations (as
<literal>"${foo}"</literal>).</para>
</listitem>
<listitem>
<para><literal>=</literal>: Assignment operator, which can also
be one of the shorthand assignment operators
(<literal>++</literal>, <literal>+=</literal>, etc.), just like
with <link linkend="ref_directive_assign">the
<literal>assign</literal> directive</link>,</para>
</listitem>
<listitem>
<para><literal><replaceable>value</replaceable></literal>: the
value to store. Expression.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>This directive is similar to <link
linkend="ref.directive.assign"><literal>assign</literal></link>, but
the variable created will be visible in all <link
linkend="dgui_misc_namespace">namespaces</link>, and will not be
inside any namespace. Exactly as if you would create (or replace) a
variable of the data-model. Hence, the variable is global. If a
variable with the same name already exists in the data-model, it
will be hidden by the variable created with this directive. If a
variable with the same name already exists in the current namespace,
that will hide the variable created with <literal>global</literal>
directive.</para>
<para>For example, with <literal>&lt;#global x = 1&gt;</literal> you
create a variable that is visible as <literal>x</literal> in all
namespaces, unless another variable called <literal>x</literal>
hides it (for example a variable what you have created as
<literal>&lt;#assign x = 2&gt;</literal>). In this case, you can use
<link linkend="dgui_template_exp_var_special">special
variable</link> <literal>globals</literal>, like
<literal>${.globals.x}</literal>. Note that with
<literal>globals</literal> you see all globally accessible
variables; not only the variables that were created with
<literal>global</literal> directive, but also the variables of the
data-model.</para>
<para>Note for custom JSP tag users: The set of variables created
with this directive corresponds to the JSP page-scope. This means,
that if a custom JSP tag wants to get a page-scope attribute
(page-scope bean), a variable with the same name in the current
namespace will not hide it from the viewpoint of the JSP tag.</para>
</section>
</section>
<section xml:id="ref_directive_if">
<title>if, else, elseif</title>
<anchor xml:id="ref.directive.if"/>
<anchor xml:id="ref.directive.else"/>
<anchor xml:id="ref.directive.elseif"/>
<indexterm>
<primary>if directive</primary>
</indexterm>
<indexterm>
<primary>else directive</primary>
</indexterm>
<indexterm>
<primary>elseif directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#if <replaceable>condition</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#elseif <replaceable>condition2</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#elseif <replaceable>condition3</replaceable>&gt;
<replaceable>...</replaceable>
<replaceable>...</replaceable>
&lt;#else&gt;
<replaceable>...</replaceable>
&lt;/#if&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>condition</replaceable></literal>,
<literal><replaceable>condition2</replaceable></literal>,
...etc.: Expression evaluates to a boolean value.</para>
</listitem>
</itemizedlist>
<para>The <literal>elseif</literal>-s and the
<literal>else</literal> are optional.</para>
<para>Camel case name variant: <literal>elseIf</literal></para>
</section>
<section>
<title>Description</title>
<para>You can use <literal>if</literal>, <literal>elseif</literal>
and <literal>else</literal> directives to conditionally skip a
section of the template. The
<literal><replaceable>condition</replaceable></literal>-s must
evaluate to a boolean value, or else an error will abort template
processing. The <literal>elseif</literal>-s and
<literal>else</literal>-s must occur inside <literal>if</literal>
(that is, between the <literal>if</literal> start-tag and end-tag).
The <literal>if</literal> can contain any number of
<literal>elseif</literal>-s (including 0) and at the end optionally
one <literal>else</literal>. Examples:</para>
<para><literal>if</literal> with 0 <literal>elseif</literal> and no
<literal>else</literal>:</para>
<programlisting role="template">&lt;#if x == 1&gt;
x is 1
&lt;/#if&gt;</programlisting>
<para><literal>if</literal> with 0 <literal>elseif</literal> and
<literal>else</literal>:</para>
<programlisting role="template">&lt;#if x == 1&gt;
x is 1
&lt;#else&gt;
x is not 1
&lt;/#if&gt;</programlisting>
<para><literal>if</literal> with 2 <literal>elseif</literal> and no
<literal>else</literal>:</para>
<programlisting role="template">&lt;#if x == 1&gt;
x is 1
&lt;#elseif x == 2&gt;
x is 2
&lt;#elseif x == 3&gt;
x is 3
&lt;/#if&gt;</programlisting>
<para><literal>if</literal> with 3 <literal>elseif</literal> and
<literal>else</literal>:</para>
<programlisting role="template">&lt;#if x == 1&gt;
x is 1
&lt;#elseif x == 2&gt;
x is 2
&lt;#elseif x == 3&gt;
x is 3
&lt;#elseif x == 4&gt;
x is 4
&lt;#else&gt;
x is not 1 nor 2 nor 3 nor 4
&lt;/#if&gt;</programlisting>
<para>To see more about boolean expressions, see: <xref
linkend="dgui_template_exp"/>.</para>
<para>You can nest <literal>if</literal> directives (of
course):</para>
<programlisting role="template">&lt;#if x == 1&gt;
x is 1
&lt;#if y == 1&gt;
and y is 1 too
&lt;#else&gt;
but y is not
&lt;/#if&gt;
&lt;#else&gt;
x is not 1
&lt;#if y &lt; 0&gt;
and y is less than 0
&lt;/#if&gt;
&lt;/#if&gt;</programlisting>
<note>
<para>When you want to test if <literal>x &gt; 0</literal> or
<literal>x &gt;= 0</literal>, writing <literal>&lt;#if x &gt;
0&gt;</literal> and <literal>&lt;#if x &gt;= 0&gt;</literal> is
WRONG, as the first <literal>&gt;</literal> will close the
<literal>#if</literal> tag. To work that around, write
<literal>&lt;#if x gt 0&gt;</literal> or <literal>&lt;#if gte
0&gt;</literal>. Also note that if the comparison occurs inside
parentheses, you will have no such problem, like <literal>&lt;#if
foo.bar(x &gt; 0)&gt;</literal> works as expected.</para>
</note>
</section>
</section>
<section xml:id="ref_directive_import">
<title>import</title>
<anchor xml:id="ref.directive.import"/>
<indexterm>
<primary>import directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#import <replaceable>path</replaceable> as <replaceable>hash</replaceable>&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>path</replaceable></literal>: The
path of a template. This is an expression that evaluates to a
string. (With other words, it doesn't have to be a fixed string,
it can also be something like, for example,
<literal>profile.baseDir + "/menu.ftl"</literal>.)</para>
</listitem>
<listitem>
<para><literal><replaceable>hash</replaceable></literal>: The
unquoted name of hash variable by which you can access the
namespace. Not an expression. (If you have to import into a
dynamically constructed name, you have to use <link
linkend="faq_assign_to_dynamic_variable_name">this
trick</link>.)</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>Used for making a collection of macros, functions, and other
variables available for the importing template, which were defined
in the imported template. For example, let's say you have written
macros to generate some commonly needed pieces output, and you have
put them into <literal>/libs/commons.ftl</literal>. Then, in the
template where you want to use them, do this (near the top of the
the template by convention, next to any other
<literal>import</literal>-s):</para>
<programlisting role="template">&lt;#import "/libs/commons.ftl" as com&gt;
</programlisting>
<para>Later in same template, let's say you want to use the
<literal>copyright</literal> macro defined in
<literal>/libs/commons.ftl</literal>. Then you can call that macro
like this:</para>
<programlisting role="template">&lt;@com.copyright date="1999-2002"/&gt;</programlisting>
<para>Note the <literal>com.</literal> before the macro name above.
All that was defined in <literal>/libs/commons.ftl</literal> will be
inside <literal>com</literal>.</para>
<para>Described more technically, <literal>import</literal> first
creates a new empty <link
linkend="dgui_misc_namespace">namespace</link>, and then executes
the template given with
<literal><replaceable>path</replaceable></literal> parameter inside
that namespace, so the template populates the namespace with
variables (macros, functions, ...etc.). Then the namespace is
assigned to the variable specified with the
<literal><replaceable>hash</replaceable></literal> parameter, and
you can access its contents through that. A namespace is <link
linkend="dgui_datamodel_container">a hash</link>, hence <link
linkend="dgui_template_exp_var_hash">the dot operator</link> worked
above. The assignment is like the <literal>assign</literal>
directive, that is, it sets the variable in the current namespace.
Except, if the import happens in the namespace of the main (topmost)
template, the hash variable is also created in the global
namespace.</para>
<para>If you call <literal>import</literal> with the same
<literal><replaceable>path</replaceable></literal> for multiple
times, it will create the namespace and run the template for the
first call of <literal>import</literal> only. The later calls will
just give back the namespace that was created and initialized when
the template was imported for the first time, and will not execute
the imported template.</para>
<para>Any output printed by the imported template will be ignored
(will not be inserted at the place of <literal>import</literal>
directive invocation). An imported template is executed to populate
its namespace with variables, and not to write to the output.</para>
<para>The <literal><replaceable>path</replaceable></literal>
parameter can be a relative path like <literal>"foo.ftl"</literal>
and <literal>"../foo.ftl"</literal>, or an absolute like
<literal>"/foo.ftl"</literal>. Relative paths are relative to the
directory of the template that uses the <literal>import</literal>
directive. Absolute paths are relative to a base (often referred as
the ''root directory of the templates'') that the programmer defines
when configuring FreeMarker.</para>
<para>Always use <literal>/</literal> (slash) to separate path
components, never <literal>\</literal> (backslash). If you are
loading templates from your local file system and it uses
backslashes (like under Windows), FreeMarker will do the necessary
conversions automatically.</para>
<para>Like with the <literal>include</literal> directive, <link
linkend="ref_directive_include_acquisition">acquisition</link> and
<link linkend="ref_directive_include_localized">localized
lookup</link> may be used for resolving the path.</para>
<para><phrase role="forProgrammers">Note that it's possible to
automatically do the commonly used imports for all templates, with
the "auto imports" setting of <literal>Configuration</literal>.
Because templates may not use all the automatically imported
namespaces, it's also possible to make imports lazy (on demand),
with the <quote>lazy auto imports</quote> setting of
<literal>Configuration</literal>.</phrase></para>
<para>If you are new to namespaces, you should read: <xref
linkend="dgui_misc_namespace"/></para>
<para>In case you are not sure if you should use the
<literal>import</literal>, or the somewhat similar
<literal>include</literal> directive, <link
linkend="topic.import_vs_include">then see this</link>.</para>
</section>
</section>
<section xml:id="ref_directive_include">
<title>include</title>
<anchor xml:id="ref.directive.include"/>
<indexterm>
<primary>include directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#include <replaceable>path</replaceable>&gt;</literal>
or
<literal>&lt;#include <replaceable>path</replaceable> <replaceable>options</replaceable>&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>path</replaceable></literal>: The
path of the file to include; an expression that evaluates to a
string. (With other words, it doesn't have to be a fixed string,
it can also be something like, for example,
<literal>profile.baseDir + "/menu.ftl"</literal>.)</para>
</listitem>
<listitem>
<para><literal><replaceable>options</replaceable></literal>: One
or more of these:
<literal>encoding=<replaceable>encoding</replaceable></literal>,
<literal>parse=<replaceable>parse</replaceable></literal></para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>encoding</replaceable></literal>:
Expression evaluates to string</para>
</listitem>
<listitem>
<para><literal><replaceable>parse</replaceable></literal>:
Expression evaluates to boolean (also accepts a few string
values for backward compatibility)</para>
</listitem>
<listitem>
<para><literal><replaceable>ignore_missing</replaceable></literal>:
Expression evaluates to boolean</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<note>
<para><emphasis>Using <literal>include</literal> directive is
almost always a bad practice</emphasis>, and you should consider
using <link linkend="ref.directive.import">the
<literal>import</literal> directive</link> instead! Even if using
<literal>import</literal> adds some verbosity, on the long run it
can pay off. See <link linkend="topic.import_vs_include">the
reasons here...</link></para>
</note>
<para>You can use it to insert another FreeMarker template file
(specified by the <literal><replaceable>path</replaceable></literal>
parameter) into your template. The output from the included template
is inserted at the point where the <literal>include</literal> tag
occurs. The included file shares the variables with the including
template, similarly like if it was copy-pasted into it. The
<literal>include</literal> directive is not really replaced by the
content of the included file, instead it processes the included file
each time when FreeMarker reaches the <literal>include</literal>
directive in the course of template processing. So for example if
the <literal>include</literal> is inside a <literal>list</literal>
loop, you can specify different file names in each cycle.</para>
<note>
<para>This directive is not be confused with the JSP (Servlet)
include, as it doesn't involve the Servlet container at all, just
processes another FreeMarker template, without "leaving"
FreeMarker. Regarding how to do a "JSP include" <link
linkend="faq_servlet_include">read this...</link></para>
</note>
<para>The <literal><replaceable>path</replaceable></literal>
parameter can be a relative path like <literal>"foo.ftl"</literal>
and <literal>"../foo.ftl"</literal>, or an absolute like
<literal>"/foo.ftl"</literal>. Relative paths are relative to the
directory of the template that contains the
<literal>import</literal> directive. Absolute paths are relative to
a base (often referred as the 'root directory of the templates')
that the programmer defines when he configures FreeMarker.</para>
<note>
<para>This is different than the way it worked prior FreeMarker
2.1, where the path was always absolute. To preserve the old
behavior, enable the classic compatible mode in the
<literal>Configuration</literal> object.</para>
</note>
<para>Always use <literal>/</literal> (slash) to separate path
components, never <literal>\</literal> (backslash). Even if you are
loading templates from your local file system and it uses
backslashes (like under. Windows), use <literal>/</literal>.</para>
<para>Example:</para>
<para>Assume /common/copyright.ftl contains:</para>
<programlisting role="template">Copyright 2001-2002 ${me}&lt;br&gt;
All rights reserved.</programlisting>
<para>Then this:</para>
<programlisting role="template">&lt;#assign me = "Juila Smith"&gt;
&lt;h1&gt;Some test&lt;/h1&gt;
&lt;p&gt;Yeah.
&lt;hr&gt;
<emphasis>&lt;#include "/common/copyright.ftl"&gt;</emphasis></programlisting>
<para>will output this:</para>
<programlisting role="output">&lt;h1&gt;Some test&lt;/h1&gt;
&lt;p&gt;Yeah.
&lt;hr&gt;
<emphasis>Copyright 2001-2002 Juila Smith
All rights reserved.</emphasis></programlisting>
<para>The supported
<literal><replaceable>options</replaceable></literal> are:</para>
<itemizedlist>
<listitem>
<para><literal>parse</literal>: If it is
<literal>true</literal>, then the included file will be parsed
as FTL, otherwise the whole file will be considered as simple
text (i.e, no FreeMarker constructs will be searched in it). If
you omit this option, then it defaults to
<literal>true</literal>.</para>
</listitem>
<listitem>
<para><literal>encoding</literal>: The encoding (charset) of the
included template. You shouldn't use this option anymore; if
different template use different encodings, then the programmers
should associated the encoding to the templates via
<literal>Configuration.setTemplateConfigurations(<replaceable>...</replaceable>)</literal>-s
(which also overrides that you specify here). If
<literal>Configuration.setTemplateConfigurations(<replaceable>...</replaceable>)</literal>
doesn't specify an encoding for the included template, then the
included file inherits the encoding (the charset) of the
top-level template, unless you specify an encoding with this
option. Examples of valid names: UTF-8, ISO-8859-1, ISO-8859-2,
Shift_JIS, Big5, EUC-KR, GB2312. <phrase
role="forProgrammers">Encoding names are the same as the ones
supported be java.io.InputStreamReader (as of Java API 1.3:
MIME-preferred charset names from the IANA Charset
Registry)</phrase></para>
</listitem>
<listitem>
<para><literal>ignore_missing</literal>: When
<literal>true</literal>, suppresses the error when the template
to include is missing, instead <literal>&lt;#include
...&gt;</literal> will print nothing. When
<literal>false</literal>, the template processing will stop with
error if the template is missing. If you omit this option, then
it defaults to <literal>false</literal>. A more flexible
approach to handle missing templates (such as if you need to do
something when the template is missing) is using the <link
linkend="ref_specvar_get_optional_template"><literal>get_optional_template</literal>
special variable</link>.</para>
<note>
<para>If <literal>ignore_missing</literal> is
<literal>true</literal>, yet the <literal>include</literal>
directive fails with <quote>Template inclusion failed</quote>
error when the template is missing, that's often because your
application uses a custom
<literal>freemarker.cache.TemplateLoader</literal>
implementation, which incorrectly (against the API
documentation) throws an <literal>IOException</literal> in the
<literal>findTemplateSource</literal> method instead of
returning <literal>null</literal> if a template is not found.
If it's so, the Java programmers need to fix that. Another
possibility is of course that it was indeed not possible to
tell if the template exists or not due to some technical
issues, in which case stopping with error is the correct
behavior. See the cause <literal>IOException</literal> in the
Java stack trace to figure out which case it is.</para>
</note>
</listitem>
</itemizedlist>
<para>Example:</para>
<programlisting role="template">&lt;#include "/common/navbar.html" parse=false encoding="Shift_JIS"&gt;</programlisting>
<para><phrase role="forProgrammers">Note, that it is possible to
automatically do the commonly used inclusions for all templates,
with the "auto includes" setting of
<literal>Configuration</literal>.</phrase></para>
<section xml:id="ref_directive_include_acquisition">
<title>Using acquisition</title>
<indexterm>
<primary>acquisition</primary>
</indexterm>
<para>There's a special path component represented by an asterisk
(<literal>*</literal>). It is interpreted as "this directory or
any of its parents". Therefore, if the template located in
<literal>/foo/bar/template.ftl</literal> has the following
line:</para>
<programlisting role="template">&lt;#include "*/footer.ftl"&gt;</programlisting>
<para>then the engine will look for the template in following
locations, in this order:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>/foo/bar/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/footer.ftl</literal></para>
</listitem>
</itemizedlist>
<para>This mechanism is called <emphasis
role="term">acquisition</emphasis> and allows the designers to
place commonly included files in a parent directory, and redefine
them on a per-subdirectory basis as needed. We say that the
including template acquires the template to include from the first
parent directory that has it. Note that you can specify not only a
template name to the right of the asterisk, but a subpath as well.
I.e. if the previous template instead read:</para>
<programlisting role="template">&lt;#include "*/commons/footer.ftl"&gt;</programlisting>
<para>then the engine would look for the template in following
locations, in this order:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>/foo/bar/commons/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/commons/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/commons/footer.ftl</literal></para>
</listitem>
</itemizedlist>
<para>Finally, the asterisk needn't be the first element of the
path:</para>
<programlisting role="template">&lt;#include "commons/*/footer.ftl"&gt;</programlisting>
<para>would cause the engine to look for the template in following
locations, in this order:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>/foo/bar/commons/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/bar/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/footer.ftl</literal></para>
</listitem>
</itemizedlist>
<para>However, there can be at most one asterisk in the path. If
you specifying more asterisks, the template won't be found.</para>
</section>
<section xml:id="ref_directive_include_localized">
<title>Localized lookup</title>
<indexterm>
<primary>localization</primary>
</indexterm>
<para>A locale is a language and an optional country or dialect
identifier (plus also maybe a further variant identifier, like
<quote>MAC</quote>). Whenever a template is requested, a desired
locale is always specified (explicitly or implicitly), and
FreeMarke will try to find a variant of the template that matches
that locale. When a template includes or imports another template,
internally that will also be requested for a locale, for the
locale that the <literal>locale</literal> setting is set to, and
that's usually for the locale of the top-level template.</para>
<para>Suppose your template was loaded with locale
<literal>en_US</literal>, which means U.S. English. When you
include another template:</para>
<programlisting role="template">&lt;#include "footer.ftl"&gt;</programlisting>
<para>the engine will in fact look for several templates, in this
order:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>footer_en_US.ftl</literal>,</para>
</listitem>
<listitem>
<para><literal>footer_en.ftl</literal></para>
</listitem>
<listitem>
<para><literal>footer.ftl</literal></para>
</listitem>
</itemizedlist>
<para>and it will use the first one that exists.</para>
<para>Note that if how (and if) FreeMarker searches the localized
variations is configurable by the programmers, so we are just
describing the default behavior here.<phrase
role="forProgrammers"> You can disable localized lookup with the
<literal>localized_lookup</literal> setting
(<literal>Configuration.setLocalizedLookup(boolean)</literal>).
Also, you can define your own sequence of deduced template names
with the <literal>template_lookup_strategy</literal> setting
(<literal>Configuration.setTemplateLookupStrategy(TemplateLookupStrategy)</literal>).</phrase></para>
<para>When you use both acquisition (i.e., <literal>*</literal>
step in the path) and localized template lookup, the template with
more specific locale in a parent directory takes precedence over
template with less specific locale in a child directory. Suppose
you use the following include from
<literal>/foo/bar/template.ftl</literal>:</para>
<programlisting role="template">&lt;#include "*/footer.ftl"&gt;</programlisting>
<para>the engine will look for these templates, in this
order:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>/foo/bar/footer_en_US.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/footer_en_US.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/footer_en_US.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/bar/footer_en.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/footer_en.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/footer_en.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/bar/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/foo/footer.ftl</literal></para>
</listitem>
<listitem>
<para><literal>/footer.ftl</literal></para>
</listitem>
</itemizedlist>
</section>
<section xml:id="topic.import_vs_include">
<title>Why <literal>import</literal> should be used instead of
<literal>include</literal></title>
<para>Generally, using <link linkend="ref.directive.import">the
<literal>import</literal> directive</link> is a better practice
than using <literal>include</literal>.</para>
<para>At first glance, import is only fitting if you have a
collection of commonly used macros, functions, and other
variables, which you put into a template for reuse. But, people
often use <literal>include</literal> to insert a common fragment
of output (e.g. page footer) into multiple templates. The
<literal>import</literal> directive has no output, so it's clearly
not a direct replacement. But, it's usually a better practice to
<link linkend="dgui_misc_userdefdir">put those output fragments
into macros</link>, as macros can have parameters, or even nested
content. If you do that, you have a collection of macros in a
template, that you can <literal>import</literal>.</para>
<para>So if you have collection of macros, functions and other
variables in a template, this is why <literal>import</literal> is
generally a better choice:</para>
<itemizedlist>
<listitem>
<para>Imported templates are processed only when first
requested. To compare with <literal>include</literal>, let's
say template <literal>top.ftl</literal> includes
<literal>commons.ftl</literal>, and
<literal>tables.ftl</literal>. If
<literal>tables.ftl</literal> also includes
<literal>commons.ftl</literal>, then now
<literal>commons.ftl</literal> will be processed twice. On the
other hand, importing <literal>commons.ftl</literal> for the
second time just gives back the namespace that was already
initialized during the first import.</para>
</listitem>
<listitem>
<para>With imports, each imported template has its own
namespace. As they don't just drop everything into a common
shared namespace, it's easier to see in templates where a
referred variable, or macro/function is coming from.
Accidental name clashes are also avoided.</para>
</listitem>
<listitem>
<para>If you have several collections of useful
macros/functions/constants (say,
<literal>commons.ftl</literal>, <literal>form.ftl</literal>,
<literal>report.ftl</literal>, etc.), and you decide to
auto-import them, but a top-level template usually only uses
some of them, you can configure auto-imports to be lazy (i.e.,
they on happen when something in their namespace is actually
accessed). This is not possible with auto-includes.</para>
</listitem>
<listitem>
<para><literal>import</literal> never prints to the output,
while <literal>include</literal> might prints unwanted output,
like some whitespace that wasn't removed by the automatic
whitespace removal.</para>
</listitem>
</itemizedlist>
</section>
</section>
</section>
<section xml:id="ref_directive_list">
<title>list, else, items, sep, break, continue</title>
<anchor xml:id="ref.directive.list"/>
<indexterm>
<primary>list directive</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>iterate</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<para>The simplest form for listing a sequence (or collection)
is:</para>
<programlisting role="metaTemplate"><literal>&lt;#list <replaceable>sequence</replaceable> as <replaceable>item</replaceable>&gt;
<replaceable>Part repeated for each item</replaceable>
&lt;/#list&gt;</literal></programlisting>
<para>and to list the key-value pairs of a hash (since
2.3.25):</para>
<programlisting role="metaTemplate"><literal>&lt;#list <replaceable>hash</replaceable> as <replaceable>key</replaceable>, <replaceable>value</replaceable>&gt;
<replaceable>Part repeated for each key-value pair</replaceable>
&lt;/#list&gt;</literal></programlisting>
<para>But these are just special cases of the generic forms, which
are shown below. Note that for simplicity we only show the generic
forms for sequence listing; simply replace <quote><literal>as
<replaceable>item</replaceable></literal></quote> with
<quote><literal>as <replaceable>key</replaceable>,
<replaceable>value</replaceable></literal></quote> to get the
generic form for hash listing.</para>
<para>Generic form 1:</para>
<programlisting role="metaTemplate"><literal>&lt;#list <replaceable>sequence</replaceable> as <replaceable>item</replaceable>&gt;
<replaceable>Part repeated for each item</replaceable>
&lt;#else&gt;
<replaceable>Part executed when there are 0 items</replaceable>
&lt;/#list&gt;</literal></programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para>The <literal>else</literal> part is optional, and is only
supported since FreeMarker 2.3.23.</para>
</listitem>
<listitem>
<para><literal><replaceable>sequence</replaceable></literal>:
Expressions evaluates to a sequence or collection of the items
we want to iterate through</para>
</listitem>
<listitem>
<para><literal><replaceable>item</replaceable></literal>: Name
of the <link linkend="dgui_misc_var">loop variable</link> (not
an expression)</para>
</listitem>
<listitem>
<para>The various <quote>parts</quote> between the tags can
contain arbitrary FTL (including nested
<literal>list</literal>-s)</para>
</listitem>
</itemizedlist>
<para>Generic form 2 (since FreeMarker 2.3.23):</para>
<programlisting role="metaTemplate"><literal>&lt;#list <replaceable>sequence</replaceable>&gt;
<replaceable>Part executed once if we have more than 0 items</replaceable>
&lt;#items as <replaceable>item</replaceable>&gt;
<replaceable> Part repeated for each item</replaceable>
&lt;/#items&gt;
<replaceable>Part executed once if we have more than 0 items</replaceable>
&lt;#else&gt;
<replaceable>Part executed when there are 0 items</replaceable>
&lt;/#list&gt;</literal></programlisting>
<para>Where: see the <quote>Where</quote> section of Form 1 above
(and thus the <literal>else</literal> part is optional here
too).</para>
</section>
<section>
<title>Description</title>
<section xml:id="ref_list_simple">
<title>Simplest form</title>
<para>Assuming <literal>users</literal> contains the
<literal>['Joe', 'Kate', 'Fred']</literal> sequence:</para>
<programlisting role="template">&lt;#list users as user&gt;
&lt;p&gt;${user}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;p&gt;Joe
&lt;p&gt;Kate
&lt;p&gt;Fred</programlisting>
<para>The <literal>list</literal> directive executes the code
between the <literal>list</literal> start-tag and
<literal>list</literal> end-tag (the body of
<literal>list</literal> from now on) for each value in the
sequence (or collection) specified as its first parameter. For
each such iteration the loop variable (<literal>user</literal> in
this example) will store the value of the current item.</para>
<para>The loop variable (<literal>user</literal>) only exists
inside the <literal>list</literal> body. Also, macros/functions
called from within the loop won't see it (as if it were a local
variable).</para>
<para>Listing hashes is very similar, but you need to provide two
variable names after the <literal>as</literal>; one for the hash
key, and another for the associated value. Assuming
<literal>products</literal> is <literal>{ "apple": 5, "banana":
10, "kiwi": 15 }</literal>:</para>
<programlisting role="template">&lt;#list products as name, price&gt;
&lt;p&gt;${name}: ${price}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;p&gt;apple: 5
&lt;p&gt;banan: 10
&lt;p&gt;kiwi: 15</programlisting>
<para>Note that not all hash variables can be listed, because some
of them isn't able to enumerate its keys. It's practically safe to
assume though that hashes that stand for Java
<literal>Map</literal> objects can be listed.</para>
</section>
<section xml:id="ref_list_else">
<title>else directive</title>
<anchor xml:id="ref.directive.list.else"/>
<indexterm>
<primary>else directive inside list</primary>
</indexterm>
<note>
<para><literal>else</literal> inside <literal>list</literal> is
only supported since FreeMarker 2.3.23</para>
</note>
<para>The <literal>else</literal> directive is used if when there
are 0 items, you have to print something special instead of just
printing nothing:</para>
<programlisting role="template">&lt;#list users as user&gt;
&lt;p&gt;${user}
&lt;#else&gt;
&lt;p&gt;No users
&lt;/#list&gt;</programlisting>
<para>This outputs the same as the earlier example, except when
<literal>users</literal> contains 0 items:</para>
<programlisting role="output"> &lt;p&gt;No users</programlisting>
<para>Note that the loop variable (<literal>user</literal>)
doesn't exist between the <literal>else</literal> tag and the
<literal>list</literal> end-tag, since that part is not part of
the loop.</para>
<para><literal>else</literal> must be literally (means, in the
source code) inside the body of the <literal>list</literal>
directive. That is, you can't moved it out into a macro or
included template.</para>
</section>
<section xml:id="ref_list_items">
<title>items directive</title>
<anchor xml:id="ref.directive.items"/>
<indexterm>
<primary>items directive</primary>
</indexterm>
<note>
<para><literal>items</literal> exists since FreeMarker
2.3.23</para>
</note>
<para>The <literal>items</literal> directive is used if you have
to print (or do) something before the first list item, and after
the last list item, as far as there's at least 1 item. A typical
example:</para>
<programlisting role="template">&lt;#list users&gt;
&lt;ul&gt;
&lt;#items as user&gt;
&lt;li&gt;${user}&lt;/li&gt;
&lt;/#items&gt;
&lt;/ul&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;ul&gt;
&lt;li&gt;Joe&lt;/li&gt;
&lt;li&gt;Kate&lt;/li&gt;
&lt;li&gt;Fred&lt;/li&gt;
&lt;/ul&gt;</programlisting>
<para>If there are 0 items, the above won't print anything, thus
you don't end up with an empty
<literal>&lt;ul&gt;&lt;/ul&gt;</literal>.</para>
<para>That is, when the <literal>list</literal> directive has no
<literal>as <replaceable>item</replaceable></literal> parameter,
the body of its is executed exactly once if there's at least one
item, or not at all otherwise. It's the body of the mandatory
nested <literal>items</literal> directive that will be run for
each item, and hence it's also the <literal>items</literal>
directive that defines the loop variable with <literal>as
<replaceable>item</replaceable></literal>, not
<literal>list</literal>.</para>
<para>A <literal>list</literal> directive with
<literal>items</literal> also can have an <literal>else</literal>
directive:</para>
<programlisting role="template">&lt;#list users&gt;
&lt;ul&gt;
&lt;#items as user&gt;
&lt;li&gt;${user}&lt;/li&gt;
&lt;/#items&gt;
&lt;/ul&gt;
&lt;#else&gt;
&lt;p&gt;No users
&lt;/#list&gt;</programlisting>
<para>Some further details:</para>
<itemizedlist>
<listitem>
<para>The parser will check that a <literal>list</literal>
without <literal>as <replaceable>item</replaceable></literal>
parameter always has a nested <literal>items</literal>
directive, and that an <literal>items</literal> directive
always has an enclosing <literal>list</literal> which has no
<literal>as <replaceable>item</replaceable></literal>
parameter. This is checked when the template is parsed, not
when the template is executed. Thus, these rules apply on the
FTL source code itself, so you can't move
<literal>items</literal> out into a macro or included
template.</para>
</listitem>
<listitem>
<para>A <literal>list</literal> can have multiple
<literal>items</literal> directives, but only one of them will
be allowed to run (as far as you don't leave and re-enter the
enclosing <literal>list</literal> directive); and further
attempts to call <literal>items</literal> will cause error. So
multiple <literal>items</literal> can be utilized on different
<literal>if</literal>-<literal>else</literal> branches for
example, but not for iterating twice.</para>
</listitem>
<listitem>
<para><literal>items</literal> directive can't have its own
nested <literal>else</literal> directive, only the enclosing
<literal>list</literal> can have</para>
</listitem>
<listitem>
<para>The loop variable (<literal>user</literal>) only exists
inside the body of the <literal>items</literal>
directive.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_list_sep">
<title>sep directive</title>
<anchor xml:id="ref.directive.sep"/>
<indexterm>
<primary>sep directive</primary>
</indexterm>
<note>
<para><literal>sep</literal> exists since FreeMarker
2.3.23</para>
</note>
<para><literal>sep</literal> is used when you have to display
something between each item (but not before the first item or
after the last item). For example:</para>
<programlisting role="template">&lt;#list users as user&gt;${user}<emphasis>&lt;#sep&gt;, </emphasis>&lt;/#list&gt;</programlisting>
<programlisting role="output">Joe, Kate, Fred</programlisting>
<para>Above, <literal>&lt;#sep&gt;, &lt;/#list&gt;</literal> is a
shorthand for <literal>&lt;#sep&gt;,
&lt;/#sep&gt;&lt;/#list&gt;</literal>; the <literal>sep</literal>
end-tag can be omitted if you would put it where the enclosing
directive is closed anyway. In the next example, you couldn't use
such abbreviation (HTML tags close nothing, as they are just raw
text to output for FreeMarker):</para>
<programlisting role="template">&lt;#list users as user&gt;
&lt;div&gt;
${user}<emphasis>&lt;#sep&gt;, &lt;/#sep&gt;</emphasis>
&lt;/div&gt;
&lt;/#list&gt;</programlisting>
<para><literal>sep</literal> is just a shorthand for
<literal>&lt;#if
<replaceable>item</replaceable>?has_next&gt;...&lt;/#if&gt;</literal>.
Thus, it can be used anywhere where there's a
<literal>list</literal> or <literal>items</literal> loop variable
available, it can occur for multiple times, and it can have
arbitrary nested content.</para>
<para>The parser ensures that <literal>sep</literal> is only used
on a place where there's a visible loop variable. This happens
earlier than the actual execution of the template. Thus, you can't
move <literal>sep</literal> from inside the associated
<literal>list</literal> or <literal>items</literal> directive into
a macro or included template (the parser can't know where those
will be called from).</para>
</section>
<section xml:id="ref_list_break">
<title>break directive</title>
<anchor xml:id="ref.directive.list.break"/>
<indexterm>
<primary>break directive</primary>
</indexterm>
<note>
<para><literal>break</literal> is deprecated for most use cases,
as it doesn't work well with <literal>&lt;#sep&gt;</literal> and
<literal><replaceable>item</replaceable>?has_next</literal>.
Instead, use <link
linkend="ref_builtin_take_while"><literal><replaceable>sequence</replaceable>?take_while(<replaceable>predicate</replaceable>)</literal></link>
to cut the sequence before you list it. See also examples <link
linkend="ref_list_skipping">here.</link></para>
</note>
<para>You can exit the iteration at any point with the
<literal>break</literal> directive. For example:</para>
<programlisting role="template">&lt;#list 1..10 as x&gt;
${x}
&lt;#if x == 3&gt;
<emphasis>&lt;#break&gt;</emphasis>
&lt;/#if&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> 1
2
3</programlisting>
<para>The <literal>break</literal> directives can be placed
anywhere inside <literal>list</literal> as far as it has
<literal>as <replaceable>item</replaceable></literal> parameter,
otherwise it can be placed anywhere inside the
<literal>items</literal> directive. However, it's strongly
recommended to place it either before or after all the other
things that you do inside the iteration. Otherwise it's easy to
end up with unclosed elements in the output, or otherwise make the
template harder to understand. Especially, avoid breaking out from
the nested content of custom directives (like <literal>&lt;#list
...&gt;...&lt;@foo&gt;...&lt;#break&gt;...&lt;/@foo&gt;...&lt;/#list&gt;</literal>),
as the author of the directive may not expect that the closing tag
(<literal>&lt;/@foo&gt;</literal>) is never executed.</para>
<para>If the <literal>break</literal> is inside
<literal>items</literal>, it will only exit from
<literal>items</literal>, not from <literal>list</literal>. In
general, <literal>break</literal> will only exit from the
directive whose body is called for each item, and can only be
placed inside such directive. So for example can't use
<literal>break</literal> inside <literal>list</literal>'s
<literal>else</literal> section, unless there's the
<literal>list</literal> is nested into another
<literal>break</literal>-able directive.</para>
<para>Using <literal>break</literal> together with
<literal>sep</literal> or <literal>?has_next</literal> is
generally a bad idea, as these can't know if you will skip the
rest of items with a <literal>break</literal>. To solve such
situations see <link linkend="ref_list_skipping">these
examples</link>.</para>
<para>Just like <literal>else</literal> and
<literal>items</literal>, <literal>break</literal> must be
literally inside body of the directive to break out from, and
can't be moved out into a macro or included template.</para>
</section>
<section xml:id="ref_list_continue">
<title>continue directive</title>
<anchor xml:id="ref.directive.list.continue"/>
<indexterm>
<primary>continue directive</primary>
</indexterm>
<note>
<para><literal>continue</literal> is deprecated for most use
cases, as it doesn't work well with
<literal>&lt;#sep&gt;</literal>,
<literal><replaceable>item</replaceable>?has_next</literal>,
<literal><replaceable>item</replaceable>?counter</literal>,
<literal><replaceable>item</replaceable>?index</literal>,
<literal><replaceable>item</replaceable>?item_parity</literal>,
etc. Instead, use <link
linkend="ref_builtin_filter"><literal><replaceable>sequence</replaceable>?filter(<replaceable>predicate</replaceable>)</literal></link>
to remove unwanted elements. See also examples <link
linkend="ref_list_skipping">here.</link></para>
</note>
<note>
<para>The <literal>continue</literal> directive exists since
FreeMarker 2.3.27.</para>
</note>
<para>You can skip the rest of the iteration body (the section
until the <literal>&lt;/#list&gt;</literal> or
<literal>&lt;/#items&gt;</literal> tag) with the
<literal>continue</literal> directive, then FreeMarker will
continue with the next item. For example:</para>
<programlisting role="template">&lt;#list 1..5 as x&gt;
&lt;#if x == 3&gt;
&lt;#continue&gt;
&lt;/#if&gt;
${x}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> 1
2
4
5</programlisting>
<para>The <literal>continue</literal> directives can be placed
anywhere inside <literal>list</literal> as far as it has
<literal>as <replaceable>item</replaceable></literal> parameter,
otherwise it can be placed anywhere inside the
<literal>items</literal> directive. However, it's strongly
recommended to place it before all the other things you do inside
the iteration. Otherwise it's easy to end up with unclosed
elements in the output, or otherwise make the template harder to
understand. Especially, avoid breaking out from the nested content
of custom directives (like <literal>&lt;#list
...&gt;...&lt;@foo&gt;...&lt;#continue&gt;...&lt;/@foo&gt;...&lt;/#list&gt;</literal>),
as the author of the directive may not expect that the closing tag
(<literal>&lt;/@foo&gt;</literal>) is never executed.</para>
<para>When you call <literal>continue</literal>, the
<literal>sep</literal> directive will not be executed for that
iteration. Using <literal>continue</literal> together with
<literal>sep</literal> is generally a bad idea anyway, also
<literal>?has_next</literal>, <literal>?counter</literal>,
<literal>?index</literal>, <literal>?item_parity</literal>, etc.
will not work as you certainly wanted if you completely skip
items. To solve such situations see <link
linkend="ref_list_skipping">these examples</link>.</para>
<para>Just like <literal>break</literal>,
<literal>continue</literal> must be literally inside body of the
directive whose iteration need to be <quote>continued</quote>, and
can't be moved out into a macro or included template.</para>
</section>
<section xml:id="ref_list_accessing_state">
<title>Accessing iteration state</title>
<indexterm>
<primary>iteration state</primary>
</indexterm>
<indexterm>
<primary>listing state</primary>
</indexterm>
<para>Starting from 2.3.23, <link
linkend="ref_builtins_loop_var">loop variable built-ins</link> is
the preferred way of accessing current state of the iteration. For
example, here we use the <literal>counter</literal> and
<literal>item_parity</literal> loop variable built-ins (see all of
them <link linkend="ref_builtins_loop_var">in the
Reference</link>):</para>
<programlisting role="template">&lt;#list users&gt;
&lt;table&gt;
&lt;#items as user&gt;
&lt;tr class="${user<emphasis>?item_parity</emphasis>}Row"&gt;
&lt;td&gt;${user<emphasis>?counter</emphasis>}
&lt;td&gt;${user}
&lt;/#items&gt;
&lt;/table&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> &lt;table&gt;
&lt;tr class="<emphasis>odd</emphasis>Row"&gt;
&lt;td&gt;<emphasis>1</emphasis>
&lt;td&gt;Joe
&lt;tr class="<emphasis>even</emphasis>Row"&gt;
&lt;td&gt;<emphasis>2</emphasis>
&lt;td&gt;Kate
&lt;tr class="<emphasis>odd</emphasis>Row"&gt;
&lt;td&gt;<emphasis>3</emphasis>
&lt;td&gt;Fred
&lt;/table&gt;</programlisting>
<para>In 2.3.22 and earlier, there were two extra loop variables
to retrieve the iteration state instead (and they still exist for
backward compatibility):</para>
<itemizedlist>
<listitem>
<para><literal><replaceable>item</replaceable>_index</literal>
(<emphasis>deprecated</emphasis> by
<literal><replaceable>item</replaceable>?index</literal>): The
index (0-based number) of the current item in the loop.</para>
</listitem>
<listitem>
<para><literal><replaceable>item</replaceable>_has_next</literal>
(<emphasis>deprecated</emphasis> by
<literal><replaceable>item</replaceable>?has_next</literal>):
Boolean value that tells if the current item is the last in
the sequence or not.</para>
</listitem>
</itemizedlist>
<para>so in the above example, you could replace
<literal>${user?counter}</literal> with <literal>${user_index +
1}</literal>.</para>
</section>
<section xml:id="ref_list_skipping">
<title>Skipping items conditionally</title>
<para>If you need to skip certain element in a list, it's
generally a bad idea to use <link
linkend="ref.directive.if"><literal>if</literal> directive</link>
for that, because then <literal>&lt;#sep&gt;</literal>,
<literal><replaceable>item</replaceable>?has_next</literal>,
<literal><replaceable>item</replaceable>?counter</literal>,
<literal><replaceable>item</replaceable>?index</literal>,
<literal><replaceable>item</replaceable>?item_parity</literal>,
etc., will not be usable, as FreeMarker doesn't know what items
were and will be actually displayed. Instead, you should try to
remove the unwanted items from the sequence that you will list,
and then list it (since 2.3.29). Here are some typical examples
with and without <literal>if</literal>.</para>
<simplesect>
<title>Filtering</title>
<para>In this example, you want to show the recommended products
from <literal>products</literal>. Here's the wrong solution with
<literal>if</literal>:</para>
<programlisting role="template">&lt;#-- WRONG solution! The row parity classes will be possibly messed up: --&gt;
&lt;#list products as product&gt;
&lt;#<emphasis>if product.recommended</emphasis>&gt;
&lt;div class="${product<emphasis>?item_parity</emphasis>}Row"&gt;${product.name}&lt;/div&gt;
&lt;/#if&gt;
&lt;/#list&gt;</programlisting>
<para>Here's the good solution that uses the <link
linkend="ref_builtin_filter"><literal>filter</literal>
built-in</link>:</para>
<programlisting role="template">&lt;#-- Good solution: --&gt;
&lt;#list products<emphasis>?filter(p -&gt; p.recommended)</emphasis> as product&gt;
&lt;div class="${product?item_parity}Row"&gt;${product.name}&lt;/div&gt;
&lt;/#list&gt;</programlisting>
</simplesect>
<simplesect>
<title>Stop listing when a certain element is found</title>
<para>Let's say you have a list of lines in
<literal>lines</literal>, and you need to stop at the first
empty line (if there's any). Furthermore you need to
<literal>&lt;br&gt;</literal> between the elements. Here's the
wrong solution with <literal>if</literal> and
<literal>break</literal>:</para>
<programlisting role="template">&lt;#-- WRONG solution! &lt;br&gt; might be added after the last printed line: --&gt;
&lt;#list lines as line&gt;
&lt;#if line == ''&gt;
&lt;#break&gt;
&lt;/#if&gt;
${line}&lt;#sep&gt;&lt;br&gt;
&lt;/#list&gt;</programlisting>
<para>Here's the good solution that uses the <link
linkend="ref_builtin_take_while"><literal>take_while</literal>
built-in</link> (note that the condition is inverted compared to
the <literal>if</literal>+<literal>break</literal>
solution):</para>
<programlisting role="template">&lt;#-- Good solution: --&gt;
&lt;#list lines?take_while(line -&gt; line != '') as line&gt;
${line}&lt;#sep&gt;&lt;br&gt;
&lt;/#list&gt;</programlisting>
</simplesect>
</section>
<section xml:id="ref_list_nesting">
<title>Nesting loops into each other</title>
<para>Naturally, <literal>list</literal> or
<literal>items</literal> can contain further
<literal>list</literal>-s:</para>
<programlisting role="template">&lt;#list 1..2 as i&gt;
&lt;#list 1..3 as j&gt;
i = ${i}, j = ${j}
&lt;/#list&gt;
&lt;/#list&gt;</programlisting>
<programlisting role="output"> i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 2, j = 1
i = 2, j = 2
i = 2, j = 3</programlisting>
<para>It's also allowed to use clashing loop variable names
like:</para>
<programlisting role="template">&lt;#list 1..2 as i&gt;
Outer: ${i}
&lt;#list 10..12 as i&gt;
Inner: ${i}
&lt;/#list&gt;
Outer again: ${i}
&lt;/#list&gt;</programlisting>
<programlisting role="output"> Outer: 1
Inner: 10
Inner: 11
Inner: 12
Outer again: 1
Outer: 2
Inner: 10
Inner: 11
Inner: 12
Outer again: 2</programlisting>
</section>
<section xml:id="ref_list_missing_element">
<title>Treatment of missing (null) elements</title>
<para>As you know by now, the <literal>list</literal> directive
will repeat its nested content for each element of the listed
value. However, it's technically possible that you have holes
(missing values, Java <literal>null</literal>-s) in the list of
elements. The nested content will executed for these
<quote>holes</quote> as well, but then the loop variable (the
variable whose name you specify after the <literal>as</literal>
keyword) will be missing. When FreeMarker finds that there's no
variable with the given name in the loop variable scope, it will
just fall back to a higher scopes to find it. However, this
fallback behavior can be problematic in this case.
Consider:</para>
<programlisting role="template">&lt;#list xs as x&gt;
${x!'Missing'}
&lt;/#list&gt;</programlisting>
<para>Here, the intent of the author is to print
<quote>Missing</quote> for the missing elements (hopes) of
<literal>xs</literal>. But if accidentally there's an
<literal>x</literal> variable in a higher scope, like in the
data-model, then <literal>x</literal> will evaluate to that in
case the currently listed element is missing, and so it won't
default to <quote>Missing</quote>. To solve that, the programmers
should set the <literal>fallback_on_null_loop_variable</literal>
configuration setting to <literal>false</literal>. (Unfortunately,
the default must be <literal>true</literal> for backward
compatibility.) In that case no fallback will occur if a loop
variable is missing.</para>
</section>
<section xml:id="ref_list_java_notes">
<title>Notes for Java programmers</title>
<para><phrase role="forProgrammers">If classic compatible mode
<literal>list</literal> accepts a scalar too and treats it as a
single-element sequence.</phrase></para>
<para><phrase role="forProgrammers">If you pass a collection that
wraps an <literal>java.util.Iterator</literal> to the
<literal>list</literal>, you can iterate over its elements only
once, since <literal>Iterator</literal>s are by their nature
one-off objects. When you try to list a such collection variable
for the second time, an error will abort template
processing.</phrase></para>
</section>
</section>
</section>
<section xml:id="ref_directive_local">
<title>local</title>
<anchor xml:id="ref.directive.local"/>
<indexterm>
<primary>local directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#local <replaceable>name</replaceable>=<replaceable>value</replaceable>&gt;</literal>
or
<literal>&lt;#local <replaceable>name1</replaceable>=<replaceable>value1</replaceable> <replaceable>name2</replaceable>=<replaceable>value2</replaceable> <replaceable>... nameN</replaceable>=<replaceable>valueN</replaceable>&gt;</literal>
or
<literal>&lt;#local <replaceable>name</replaceable>&gt;
<replaceable>capture this</replaceable>
&lt;/#local&gt;
</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: the
name of the local object in the root. It is not an expression.
However, it can be written as a string literal, which is useful
if the variable name contains reserved characters, for example
<literal>&lt;#local "foo-bar" = 1&gt;</literal>. Note that this
string literal does not expand interpolations (as
<literal>"${foo}"</literal>).</para>
</listitem>
<listitem>
<para><literal>=</literal>: Assignment operator, which can also
be one of the shorthand assignment operators
(<literal>++</literal>, <literal>+=</literal>, etc.), just like
with <link linkend="ref_directive_assign">the
<literal>assign</literal> directive</link>,</para>
</listitem>
<listitem>
<para><literal><replaceable>value</replaceable></literal>: the
value to store. Expression.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>It is similar to <link linkend="ref.directive.assign">assign
directive</link>, but it creates or replaces local variables. This
only works inside macro definitions and function definitions.</para>
<para>For more information about variables, read this: <xref
linkend="dgui_misc_var"/></para>
<note>
<para>A frequent mistake is trying to use
<literal>assign</literal> to change a local variable like:
<literal>&lt;#macro m&gt;&lt;#local x = 1&gt;${x}&lt;#assign x =
2&gt;${x}&lt;/#macro&gt;</literal>. This prints
<literal>11</literal>, not <literal>12</literal>, because
<literal>assign</literal> creates/replaces the
<literal>x</literal> of the namespace that the template belongs
to, and doesn't change the <literal>x</literal> local variable.
Local variables should be always set with the <link
linkend="ref.directive.local"><literal>local</literal>
directive</link>, not just for the fist time.</para>
</note>
</section>
</section>
<section xml:id="ref_directive_macro">
<title>macro, nested, return</title>
<anchor xml:id="ref.directive.macro"/>
<indexterm>
<primary>macro directive</primary>
</indexterm>
<indexterm>
<primary>nested directive</primary>
</indexterm>
<indexterm>
<primary>return directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#macro <replaceable>name</replaceable> <replaceable>param1</replaceable> <replaceable>param2</replaceable> <replaceable>... paramN</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#nested <replaceable>loopvar1</replaceable>, <replaceable>loopvar2</replaceable>, <replaceable>...</replaceable>, <replaceable>loopvarN</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#return&gt;
<replaceable>...</replaceable>
&lt;/#macro&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: name
of macro variable. It's not an expression. It follows the same
syntax as <link linkend="dgui_template_exp_var_toplevel">like
top-level variable references</link>, like
<literal>myMacro</literal> or <literal>my\-macro</literal>.
However, it can also be written as a string literal, which is
useful if the macro name contains characters that can't be
specified in an identifier, for example <literal>&lt;#macro
"foo~bar"&gt;<replaceable>...</replaceable></literal>. Note that
this string literal does not expand interpolations (as
<literal>"${foo}"</literal>).</para>
</listitem>
<listitem>
<para><literal><replaceable>param1</replaceable></literal>,
<literal><replaceable>param2</replaceable></literal>, ...etc.:
the name of the <link linkend="dgui_misc_var">local
variables</link> store the parameter values (not expression),
optionally followed by <literal>=</literal> and the default
value (that's an expression). The default value can even be
another parameter, for example <literal>&lt;#macro section title
label=title&gt;</literal>. The parameter name uses the same
syntax as <link linkend="dgui_template_exp_var_toplevel">like
top-level variable references</link>, so the same features and
restrictions apply.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>catch-all parameter</primary>
</indexterm><indexterm>
<primary>variable number of parameters</primary>
</indexterm><literal><replaceable>paramN</replaceable></literal>,
the last parameter may optionally has 3 trailing dots
(<literal>...</literal>), which indicates that the macro takes a
variable number of parameters and the parameters that doesn't
match any other parameters will be collected in this last
parameter (also called the catch-all parameter). When the macro
is called with named parameters,
<literal><replaceable>paramN</replaceable></literal> will be a
hash containing all of the undeclared key/value pairs passed to
the macro. When the macro is called using positional parameters,
<literal><replaceable>paramN</replaceable></literal> will be the
sequence of the extra parameter values. (Inside the macro, to
find out which was the case, you can use
<literal><replaceable>myCatchAllParam</replaceable>?is_sequence</literal>.)</para>
</listitem>
<listitem>
<para><literal><replaceable>loopvar1</replaceable></literal>,
<literal><replaceable>loopvar2</replaceable></literal>, ...etc.:
Optional. The values of <link linkend="dgui_misc_var">loop
variables</link> that the <literal>nested</literal> directive
wants to create for the nested content. These are
expressions.</para>
</listitem>
</itemizedlist>
<para>The <literal>return</literal> and <literal>nested</literal>
directives are optional and can be used anywhere and for any times
between the <literal>&lt;#macro
<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#macro&gt;</literal>.</para>
<para>Parameters without default value must precede parameters with
default value
(<literal><replaceable>paramName</replaceable>=<replaceable>defaultValue</replaceable></literal>).</para>
</section>
<section>
<title>Description</title>
<para>Creates a macro variable (in the current namespace, if you
know namespace feature). If you are new to macros and user-defined
directives you should read the <link
linkend="dgui_misc_userdefdir">the tutorial about user-defined
directives</link>.</para>
<para>Macro variable stores a template fragment (called macro
definition body) that can be used as <link
linkend="ref.directive.userDefined">user-defined directive</link>.
The variable also stores the name of allowed parameters to the
user-defined directive. You must give value for all of those
parameters when you use the variable as directive, except for
parameters that has a default value. The default value will be used
if and only if you don't give value for the parameter when you call
the macro.</para>
<para>The variable will be created at the beginning of the template;
it does not mater where the <literal>macro</literal> directive is
placed in the template. Thus, this will work:</para>
<programlisting role="template">&lt;#-- call the macro; the macro variable is already created: --&gt;
&lt;@test/&gt;
...
&lt;#-- create the macro variable: --&gt;
&lt;#macro test&gt;
Test text
&lt;/#macro&gt;</programlisting>
<para>However, if the macro definitions are inserted with
<literal>include</literal> directive, they will not be available
until FreeMarker has executed the <literal>include</literal>
directive.</para>
<para>Example: Macro without parameters:</para>
<programlisting role="template">&lt;#macro test&gt;
Test text
&lt;/#macro&gt;
&lt;#-- call the macro: --&gt;
&lt;@test/&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> Test text
</programlisting>
<para>Example: Macro with parameters:</para>
<programlisting role="template">&lt;#macro test foo bar baaz&gt;
Test text, and the params: ${foo}, ${bar}, ${baaz}
&lt;/#macro&gt;
&lt;#-- call the macro: --&gt;
&lt;@test foo="a" bar="b" baaz=5*5-2/&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> Test text, and the params: a, b, 23
</programlisting>
<para>Example: Macro with parameters and default parameter
values:</para>
<programlisting role="template">&lt;#macro test foo bar="Bar" baaz=-1&gt;
Test text, and the params: ${foo}, ${bar}, ${baaz}
&lt;/#macro&gt;
&lt;@test foo="a" bar="b" baaz=5*5-2/&gt;
&lt;@test foo="a" bar="b"/&gt;
&lt;@test foo="a" baaz=5*5-2/&gt;
&lt;@test foo="a"/&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> Test text, and the params: a, b, 23
Test text, and the params: a, b, -1
Test text, and the params: a, Bar, 23
Test text, and the params: a, Bar, -1
</programlisting>
<para>Example: A more complex macro.</para>
<programlisting role="template">&lt;#macro list title items&gt;
&lt;p&gt;${title?cap_first}:
&lt;ul&gt;
&lt;#list items as x&gt;
&lt;li&gt;${x?cap_first}
&lt;/#list&gt;
&lt;/ul&gt;
&lt;/#macro&gt;
&lt;@list items=["mouse", "elephant", "python"] title="Animals"/&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> &lt;p&gt;Animals:
&lt;ul&gt;
&lt;li&gt;Mouse
&lt;li&gt;Elephant
&lt;li&gt;Python
&lt;/ul&gt;
</programlisting>
<para>Example: A macro with support for a variable number of named
parameters:</para>
<programlisting role="template">&lt;#macro img src extra...&gt;
&lt;img src="/myapp${src?ensure_starts_with('/')}"
&lt;#list extra as attrName, attrVal&gt;
${attrName}="${attrVal}"
&lt;/#list&gt;
&gt;
&lt;/#macro&gt;
&lt;@img src="/images/test.png" width=100 height=50 alt="Test"/&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> &lt;img src="/context/images/test.png"
alt="Test"
height="50"
width="100"
&gt;</programlisting>
<para>Example: A macro that supports a variable number of positional
parameters, regardless if it uses named or positional parameter
passing:</para>
<programlisting role="template">&lt;#macro m a b ext...&gt;
a = ${a}
b = ${b}
&lt;#if ext?is_sequence&gt;
&lt;#list ext as e&gt;
${e?index} = ${e}
&lt;/#list&gt;
&lt;#else&gt;
&lt;#list ext as k, v&gt;
${k} = ${v}
&lt;/#list&gt;
&lt;/#if&gt;
&lt;/#macro&gt;
&lt;@m 1 2 3 4 5 /&gt;
&lt;@m a=1 b=2 c=3 d=4 e=5 data\-foo=6 myns\:bar=7 /&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> a = 1
b = 2
0 = 3
1 = 4
2 = 5
a = 1
b = 2
c = 3
d = 4
e = 5
data-foo=6
myns:bar=7</programlisting>
<warning>
<para>Before FreeMarker 2.3.30, named catch-all parameters are
unordered, that is, you don't know what order will they be
enumerated. Only starting from 2.3.30 are they returned in the
same order as they were passed in.</para>
</warning>
<section>
<title>nested</title>
<anchor xml:id="ref.directive.nested"/>
<para>The <literal>nested</literal> directive executes the
template fragment between the start-tag and end-tags of the
user-defined directive. The nested part can contain anything what
is valid in templates; interpolations, directives, ...etc. It is
executed in the context where the macro was called from, rather
than in the context of the macro definition body. Thus, for
example, you don't see the local variables of the macro in the
nested part. If you don't call the <literal>nested</literal>
directive, the part between the start-tag and end-tags of the
user-defined directive will be ignored.</para>
<para>Example:</para>
<programlisting role="template">&lt;#macro do_twice&gt;
1. &lt;#nested&gt;
2. &lt;#nested&gt;
&lt;/#macro&gt;
&lt;@do_twice&gt;something&lt;/@do_twice&gt;</programlisting>
<programlisting role="output"> 1. something
2. something
</programlisting>
<para>The nested directive can create loop variables for the
nested content. For example:</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;
${<emphasis>x</emphasis>} Anything.
&lt;/@do_thrice&gt;</programlisting>
<programlisting role="output"> 1 Anything.
2 Anything.
3 Anything.
</programlisting>
<para>A more complex example:</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>
<programlisting role="output"> 1. 0.5
2. 1
3. 1.5
4. 2 Last!
</programlisting>
</section>
<section>
<title>return</title>
<anchor xml:id="ref.directive.macro.return"/>
<para>With the <literal>return</literal> directive, you can leave
a macro or function definition body anywhere. Example:</para>
<programlisting role="template">&lt;#macro test&gt;
Test text
&lt;#return&gt;
Will not be printed.
&lt;/#macro&gt;
&lt;@test/&gt;</programlisting>
<programlisting role="output"> Test text
</programlisting>
</section>
</section>
</section>
<section xml:id="ref_directive_noautoesc">
<title>noautoesc</title>
<anchor xml:id="ref.directive.noautoesc"/>
<indexterm>
<primary>noautoesc directive</primary>
</indexterm>
<indexterm>
<primary>auto-escaping</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#noautoesc&gt;
<replaceable>...</replaceable>
&lt;/#noautoesc&gt;</literal>
</programlisting>
<para>Camel case name variant: <literal>noAutoEsc</literal></para>
</section>
<section>
<title>Description</title>
<para>Disables <link
linkend="dgui_misc_autoescaping">auto-escaping</link> in the nested
section. Note that to prevent escaping for just a single
<literal>${<replaceable>expression</replaceable>}</literal> you
should use
<literal>${<replaceable>expression</replaceable>?no_esc}</literal>
instead.</para>
<para>This directive only has effect on the section that is
literally (as in the text editor) inside the nested bock, not on the
parts that are called/included from there.</para>
<para>Example:</para>
<programlisting role="template">&lt;#ftl output_format="XML"&gt;
${"&amp;"}
&lt;#noautoesc&gt;
${"&amp;"}
...
${"&amp;"}
&lt;/#noautoesc&gt;
${"&amp;"}</programlisting>
<programlisting role="output">&amp;amp;
&amp;
...
&amp;
&amp;amp;</programlisting>
<para><literal>noautoesc</literal> can be used regardless of what
the current <link
linkend="dgui_misc_autoescaping_outputformat">output format</link>
is (unlike the <link
linkend="ref_directive_autoesc"><literal>autoesc</literal>
directive</link>).</para>
<para><literal>noautoesc</literal> can also be used nested into
<link linkend="ref_directive_autoesc"><literal>autoesc</literal>
directive</link> to re-enable escaping.</para>
<para><literal>noautoesc</literal> can be used on places where
auto-escaping is already disabled, such as even inside another
<literal>noautoesc</literal> block. Doing so is redundant but
allowed.</para>
</section>
</section>
<section xml:id="ref_directive_noparse">
<title>noparse</title>
<anchor xml:id="ref.directive.noparse"/>
<indexterm>
<primary>noparse directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#noparse&gt;
<replaceable>...</replaceable>
&lt;/#noparse&gt;</literal>
</programlisting>
<para>Camel case name variant: <literal>noParse</literal></para>
</section>
<section>
<title>Description</title>
<para>FreeMarker will not search FTL tags and interpolations and
other special character sequences in the body of this directive,
except the noparse end-tag.</para>
<para>Example:</para>
<programlisting role="template">Example:
--------
<emphasis>&lt;#noparse&gt;</emphasis>
&lt;#list animals as animal&gt;
&lt;tr&gt;&lt;td&gt;${animal.name}&lt;td&gt;${animal.price} Euros
&lt;/#list&gt;
<emphasis>&lt;/#noparse&gt;</emphasis></programlisting>
<programlisting role="output">Example:
--------
&lt;#list animals as animal&gt;
&lt;tr&gt;&lt;td&gt;${animal.name}&lt;td&gt;${animal.price} Euros
&lt;/#list&gt;
</programlisting>
</section>
</section>
<section xml:id="ref_directive_nt">
<title>nt</title>
<anchor xml:id="ref.directive.nt"/>
<indexterm>
<primary>nt directive</primary>
</indexterm>
<indexterm>
<primary>trimmer directives</primary>
</indexterm>
<indexterm>
<primary>white-space removal</primary>
<secondary>trimming</secondary>
</indexterm>
<indexterm>
<primary>white-space removal</primary>
<secondary>stripping</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#nt&gt;</literal>
</programlisting>
</section>
<section>
<title>Description</title>
<para><quote>No Trim</quote>. This directive disables <link
linkend="dgui_misc_whitespace_stripping">white-space
stripping</link> in the line where it occurs. It also disables the
effect of other trim directives occurring in the same line (the
effect of <literal>t</literal>, <literal>rt</literal>,
<literal>lt</literal>).</para>
</section>
</section>
<section xml:id="ref_directive_outputformat">
<title>outputformat</title>
<anchor xml:id="ref.directive.outputformat"/>
<indexterm>
<primary>outputformat directive</primary>
</indexterm>
<indexterm>
<primary>auto-escaping</primary>
</indexterm>
<indexterm>
<primary>escaping</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#outputformat <replaceable>formatName</replaceable>&gt;
<replaceable>...</replaceable>
&lt;/#outputFormat&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>formatName</replaceable></literal>:
A string constant; can't contain runtime expressions! This is
the name of the output format, like <literal>"HTML"</literal>,
<literal>"XML"</literal>, etc.; see the <link
linkend="topic.predefinedOutputFormats">table of the predefined
output formats here</link>. The referred output format must be
known by the <literal>Configuration</literal>, or else a <link
linkend="gloss.parseTimeError">parse-time error</link> will
occur. The name can also be like
<literal>"<replaceable>outerFormatName</replaceable>{<replaceable>innerFormatName</replaceable>}"</literal>,
or
<literal>"{<replaceable>innerFormatName</replaceable>}"</literal>;
<link linkend="topic.combinedOutputFormats">see combined output
formats later</link>.</para>
</listitem>
</itemizedlist>
<para>Camel case name variant: <literal>outputFormat</literal><note>
<para><literal>outputformat</literal> exists since FreeMarker
2.3.24.</para>
</note></para>
</section>
<section>
<title>Description</title>
<para>Sets the <link
linkend="dgui_misc_autoescaping_outputformat">output format</link>
to the specified one, inside the nested block. At the end of the
block, the earlier output format is restored.</para>
<para>This directive only has effect on the section that is
literally (as in the text editor) inside the nested bock, not on the
parts that are called/included from there.</para>
<para>Example:</para>
<programlisting role="template">&lt;#ftl output_format="XML"&gt;
XML escaping: ${"&amp;{}"}
&lt;#outputformat "RTF"&gt;
RTF escaping: ${"&amp;{}"}
&lt;/#outputformat&gt;
&lt;#outputformat "plainText"&gt;
No escsaping: ${"&amp;{}"}
&lt;/#outputformat&gt;
XML escsaping: ${"&amp;{}"}</programlisting>
<programlisting role="output">XML escsaping: &amp;amp;{}
RTF escaping: &amp;\{\}
No escsaping: &amp;{}
XML escsaping: &amp;amp;{}</programlisting>
<simplesect xml:id="topic.combinedOutputFormats">
<title>Combined (nested) output formats</title>
<para>When <literal>outputformat</literal>-s are nested into each
other, normally, only the innermost output format will count. For
example:</para>
<programlisting role="template">&lt;#ftl output_format="XML"&gt;
${"'{}"}
&lt;#outputformat "HTML"&gt;
${"'{}"}
&lt;#outputformat "RTF"&gt;
${"'{}"}
&lt;/#outputformat&gt;
&lt;/#outputformat&gt;</programlisting>
<programlisting role="output">&amp;apos;{}
&amp;#39;{}
'\{\}</programlisting>
<para>But sometimes you want all enclosing output format escaping
to be applied at once. In that case the 2nd
<literal>${<replaceable>...</replaceable>}</literal> above should
be escaped with <literal>"HTML"</literal> and then with
<literal>"XML"</literal>, and the 3rd
<literal>${<replaceable>...</replaceable>}</literal> should be
escaped with <literal>"RTF"</literal> and then with
<literal>"HTML"</literal> and then with <literal>"XML"</literal>.
These are called combined output formats, and can be referred by
names like <literal>"XML{HTML}"</literal> and
<literal>"XML{HTML{RTF}}"</literal>, respectively. We could use
these names in the earlier two <literal>outputformat</literal>
calls, however, there's a shorthand where you inherit the part
outside the <literal>{<replaceable>...</replaceable>}</literal>
from the enclosing output format:</para>
<programlisting role="template">&lt;#ftl outputFormat="XML"&gt;
${"'{}"}
&lt;#outputFormat "{HTML}"&gt;&lt;#-- Same as "XML{HTML}" --&gt;
${"'{}"}
&lt;#outputFormat '{RTF}'&gt;&lt;#-- Same as "XML{HTML{RTF}}" --&gt;
${"'{}"}
&lt;/#outputFormat&gt;
&lt;/#outputFormat&gt;
</programlisting>
<programlisting role="output">&amp;apos;{}
&amp;amp;#39;{}
&amp;amp;#39;\{\}</programlisting>
</simplesect>
</section>
</section>
<section xml:id="ref_directive_setting">
<title>setting</title>
<anchor xml:id="ref.directive.setting"/>
<indexterm>
<primary>setting directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#setting <replaceable>name</replaceable>=<replaceable>value</replaceable>&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: name
of the setting. It is not expression!</para>
</listitem>
<listitem>
<para><literal><replaceable>value</replaceable></literal>: New
value of the setting. Expression</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>Sets a setting for the further part of processing. Settings
are values that influence the behavior of FreeMarker. The new value
will be present only in the template processing where it was set,
and does not touch the template itself. The initial value of
settings is set by the programmer <phrase
role="forProgrammers">(see: <xref
linkend="pgui_config_settings"/>)</phrase>.</para>
<para>The supported settings are:</para>
<itemizedlist>
<listitem>
<para><indexterm>
<primary>locale</primary>
</indexterm><literal>locale</literal>: The locale (language)
of the output. It can influence the presentation format of
numbers, dates, etc. The value is a string which consist of a
language code (lowercase two-letter ISO-639 code) plus optional
county code (uppercase two-letter ISO-3166 code) separated from
the language code with underscore, and if we have specified the
country then an optional variant code (not standardized)
separated from the country with underscore. Examples of valid
values: <literal>en</literal>, <literal>en_US</literal>,
<literal>en_US_MAC</literal>. FreeMarker will try to use the
most specific available locale, so if you specify
<literal>en_US_MAC</literal> but that is not known, then it will
try <literal>en_US</literal>, and then <literal>en</literal>,
and then the default locale of the computer (which is may set by
the programmer).</para>
</listitem>
<listitem>
<para xml:id="ref.setting.number_format"><indexterm>
<primary>number_format</primary>
</indexterm><indexterm>
<primary>format</primary>
<secondary>number</secondary>
</indexterm><literal>number_format</literal>: The number
format that is used to convert numbers to strings when no
explicit format is specified. Can be one of the
following:</para>
<itemizedlist>
<listitem>
<para>Predefined values defined by the Java platform:
<literal>number</literal> (the default),
<literal>currency</literal>, or
<literal>percent</literal></para>
</listitem>
<listitem>
<para><literal>computer</literal>, which formats like <link
linkend="ref_builtin_c">the <literal>c</literal>
built-in</link></para>
</listitem>
<listitem>
<para>Format pattern written in <link
xlink:href="http://java.sun.com/j2se/1.4/docs/api/java/text/DecimalFormat.html">Java
decimal number format syntax</link>, for example
<literal>0.###</literal>. FreeMarker <link
linkend="topic.extendedJavaDecimalFormat">extends this
format</link> to allow specifying rounding mode, symbols
used, etc.</para>
</listitem>
<listitem>
<para>Values starting with <literal>@</literal> that's also
followed by a letter, refer to a <link
linkend="pgui_config_custom_formats">custom format</link>.
For example, <literal>"@price"</literal> refers to the
custom format registered with the <literal>"price"</literal>
name. The custom format name is possibly followed by space
or <literal>_</literal> and then format parameters, whose
interpretation depends on the custom format. For backward
compatibility, the initial <literal>@</literal> only has
this new meaning if either <link
linkend="pgui_config_incompatible_improvements_how_to_set">the
<literal>incompatible_improvements</literal> setting</link>
is at least 2.3.24, or there's any custom formats defined.
When the initial <literal>@</literal> isn't followed by a
letter (any UNICODE letter), it's never treated as a
reference to a custom format.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><indexterm>
<primary>boolean_format</primary>
</indexterm><indexterm>
<primary>format</primary>
<secondary>boolean</secondary>
</indexterm><literal>boolean_format</literal>: The
comma-separated pair of strings for representing true and false
values respectively that is used to convert booleans to strings
when no explicit format is specified (like in
<literal>${<replaceable>booleanValue</replaceable>}</literal>).
Note that currently white space isn't removed from this string,
so don't put space after the comma. Default value is
<literal>"true,false"</literal>, but FreeMarker will deny using
that particular value for
<literal>${<replaceable>booleanValue</replaceable>}</literal>,
and requires using
<literal>${<replaceable>booleanValue</replaceable>?c}</literal>
instead (this works since 2.3.21). For any other value, like
<literal>"Y,N"</literal>,
<literal>${<replaceable>booleanValue</replaceable>}</literal>
will work. See also:<link
linkend="ref_builtin_string_for_boolean"><literal>string</literal>
built-in</link>.</para>
</listitem>
<listitem xml:id="topic.dateTimeFormatSettings">
<para xml:id="topic_date_format_settings"><indexterm>
<primary>date_format</primary>
</indexterm><indexterm>
<primary>time_format</primary>
</indexterm><indexterm>
<primary>datetime_format</primary>
</indexterm><indexterm>
<primary>format</primary>
<secondary>date</secondary>
</indexterm><indexterm>
<primary>XML Schema date rendering</primary>
</indexterm><indexterm>
<primary>XML Schema time rendering</primary>
</indexterm><indexterm>
<primary>XML Schema dateTime rendering</primary>
</indexterm><indexterm>
<primary>ISO 8601</primary>
</indexterm> <literal>date_format</literal>,
<literal>time_format</literal>,
<literal>datetime_format</literal>: The format used to convert
date/time/date-time values (Java
<literal>java.util.Date</literal>-s and its subclasses) to
strings when no explicit format is specified via the <link
linkend="ref_builtin_string_for_date"><literal>string</literal>
built-in</link> (or otherwise), as in the case of
<literal>${someDate}</literal>. The
<literal>date_format</literal> setting only effects the
formatting of date values that store no time part,
<literal>time_format</literal> only effects the formatting of
times that store no date part, and
<literal>datetime_format</literal> only effects formatting of
date-time values. These settings also effects what format do
<link
linkend="ref_builtin_string_date"><literal>?time</literal>,
<literal>?date</literal>, and
<literal>?datetime</literal></link> expect when it's applied on
a string value.</para>
<para><remark>The following part is copy-pasted from the JavaDoc
of Configurable.setDateTimeFormat(String); keep them in sync.
</remark>The possible setting values are (the quotation marks
aren't part of the value itself):</para>
<itemizedlist>
<listitem>
<para>Patterns <link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html">accepted
by Java's <literal>SimpleDateFormat</literal></link>, for
example <literal>"dd.MM.yyyy HH:mm:ss"</literal> (where
<literal>"HH"</literal> means 0-23 hours) or
<literal>"MM/dd/yyyy hh:mm:ss a"</literal> (where
<literal>"a"</literal> prints AM or PM, if the current
language is English).</para>
<warning>
<para>Be careful <emphasis>not</emphasis> to use
<literal>YYYY</literal> (upper case, means <quote>week
year</quote>) instead of <literal>yyyy</literal> (lower
case, means year)! It's an easy mistake to do, and hard to
notice during testing, as <quote>week year</quote> only
differs from <quote>year</quote> near the edge of
years.</para>
</warning>
</listitem>
<listitem>
<para><literal>"xs"</literal> for XML Schema format, or
<literal>"iso"</literal> for ISO 8601:2004 format. These
formats allow various additional options, separated with
space, like in <literal>"iso m nz"</literal> (or with
<literal>_</literal>, like in <literal>"iso_m_nz"</literal>;
this is useful in a case like
<literal>lastModified?string.iso_m_nz</literal>). The
options and their meanings are:</para>
<itemizedlist>
<listitem>
<para>Accuracy options:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>ms</literal>: Milliseconds, always
shown with all 3 digits, even if it's all 0-s.
Example: <literal>13:45:05.800</literal></para>
</listitem>
<listitem>
<para><literal>s</literal>: Seconds (fraction
seconds are dropped even if non-0), like
<literal>13:45:05</literal></para>
</listitem>
<listitem>
<para><literal>m</literal>: Minutes, like
<literal>13:45</literal>. This isn't allowed for
<literal>"xs"</literal>.</para>
</listitem>
<listitem>
<para><literal>h</literal>: Hours, like
<literal>13</literal>. This isn't allowed for
<literal>"xs"</literal>.</para>
</listitem>
<listitem>
<para>Neither: Up to millisecond accuracy, but
trailing millisecond 0-s are removed, also the whole
milliseconds part if it would be 0 otherwise.
Example: <literal>13:45:05.8</literal></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Time zone offset visibility options:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>fz</literal>: <quote>Force
Zone</quote>, always show time zone offset (even for
for <literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal> values). But,
because ISO 8601 doesn't allow for dates (means date
without time of the day) to show the zone offset,
this option will have no effect in the case of
<literal>"iso"</literal> with dates.</para>
</listitem>
<listitem>
<para><literal>nz</literal>: <quote>No Zone</quote>,
never show time zone offset</para>
</listitem>
<listitem>
<para>Neither: Always show time zone offset, except
for <literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal>, and for
<literal>"iso"</literal> date values.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Time zone options:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>u</literal>: Use UTC instead of what
the <literal>time_zone</literal> setting suggests.
However, <literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal> aren't affected by
this (see
<literal>sql_date_and_time_time_zone</literal> to
understand why)</para>
</listitem>
<listitem>
<para><literal>fu</literal>: <quote>Force
UTC</quote>, that is, use UTC instead of what the
<literal>time_zone</literal> or the
<literal>sql_date_and_time_time_zone</literal>
setting suggests. This also effects
<literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal> values</para>
</listitem>
<listitem>
<para>Neither: Use the time zone suggested by the
<literal>time_zone</literal> or the
<literal>sql_date_and_time_time_zone</literal>
configuration setting</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>Options from the same category are mutually exclusive,
like using <literal>m</literal> and <literal>s</literal>
together is an error.</para>
<para>The options can be specified in any order.</para>
<para>The accuracy and time zone offset visibility options
don't influence parsing, only formatting. For example, even
if you use <literal>"iso m nz"</literal>,
<literal>"2012-01-01T15:30:05.125+01"</literal> will be
parsed successfully and with milliseconds accuracy. The time
zone options (like <literal>"u"</literal>) influence what
time zone is chosen only when parsing a string that doesn't
contain time zone offset.</para>
<para>Parsing with <literal>"iso"</literal> understands both
<quote>extend format</quote> and <quote>basic
format</quote>, like <literal>20141225T235018</literal>. It
doesn't, however, support the parsing of all kind of ISO
8601 strings: if there's a date part, it must use year,
month and day of the month values (not week of the year),
and the day can't be omitted.</para>
<para>The output of <literal>"iso"</literal> is deliberately
so that it's also a good representation of the value with
XML Schema format, except for 0 and negative years, where
it's impossible. Also note that the time zone offset is
omitted for date values in the <literal>"iso"</literal>
format, while it's preserved for the <literal>"xs"</literal>
format.</para>
</listitem>
<listitem>
<para><literal>"short"</literal>,
<literal>"medium"</literal>, <literal>"long"</literal>, or
<literal>"full"</literal>, which has locale-dependent
meaning defined by the Java platform (see in the <link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html">documentation
of <literal>java.text.DateFormat</literal></link>). For
date-time values, you can specify the length of the date and
time part independently, be separating them with
<literal>_</literal>, like
<literal>"short_medium"</literal>.
(<literal>"medium"</literal> means
<literal>"medium_medium"</literal> for date-time
values.)</para>
</listitem>
<listitem>
<para>Values starting with <literal>@</literal> that's also
followed by a letter, refer to a <link
linkend="pgui_config_custom_formats">custom format</link>,
like <literal>"@worklog"</literal> refers to the custom
format registered with the <literal>"worklog"</literal>
name. The format name is possibly followed by space or
<literal>_</literal> and then format parameters, whose
interpretation depends on the custom format. For backward
compatibility, the initial <literal>@</literal> only has
this new meaning if either <link
linkend="pgui_config_incompatible_improvements_how_to_set">the
<literal>incompatible_improvements</literal> setting</link>
is at least 2.3.24, or there's any custom formats defined.
When the initial <literal>@</literal> isn't followed by a
letter (any UNICODE letter), it's never treated as a
reference to a custom format.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><indexterm>
<primary>time_zone</primary>
</indexterm><literal>time_zone</literal>: The name of the time
zone used to format times for display. As with all settings, the
default is chosen by the programmers when they set up FreeMarker
(<phrase role="forProgrammers">via the
<literal>Configuration</literal> class</phrase>), but it's most
often the default time zone of the JVM. Can be any value that is
accepted by <link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html">Java
TimeZone API</link>, or <literal>"JVM default"</literal> (since
FreeMarker 2.3.21) to use the JVM default time zone. Examples:
<literal>"GMT"</literal>, <literal>"GMT+2"</literal>,
<literal>"GMT-1:30"</literal>, <literal>"CET"</literal>,
<literal>"PST"</literal>,
<literal>"America/Los_Angeles"</literal>.</para>
<warning>
<para>If you change this setting from its default value, you
should certainly also set
<literal>sql_date_and_time_time_zone</literal> to "JVM
default". <phrase role="forProgrammers">See more in the Java
API documentation of
<literal>Configurable.setSQLDateAndTimeTimeZone(TimeZone)</literal>.</phrase></para>
</warning>
</listitem>
<listitem>
<para><indexterm>
<primary>time_zone</primary>
</indexterm><indexterm>
<primary>JDBC time zone</primary>
</indexterm><literal>sql_date_and_time_time_zone</literal>
(since FreeMarker 2.3.21): This handles a highly technical
issue, so it should usually be set from the Java code by the
programmers. <phrase role="forProgrammers">For programmers: If
this is set to non-<literal>null</literal>, for date-only and
time-only values coming from SQL database (more precisely, for
<literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal> objects) FreeMarker will use
this time zone instead of the time zone specified by the
<literal>time_zone</literal> FreeMarker setting. See more in the
Java API documentation of
<literal>Configurable.setSQLDateAndTimeTimeZone(TimeZone)</literal>.</phrase></para>
</listitem>
<listitem>
<para><indexterm>
<primary>url_escaping_charset</primary>
</indexterm><literal>url_escaping_charset</literal>: The
charset used for URL escaping (e.g. for
<literal>${foo?url}</literal>) to calculate the escaped
(<literal>%<replaceable>XX</replaceable></literal>) parts.
Usually the framework that encloses FreeMarker should set it, so
you hardly ever should set this setting in templates. <phrase
role="forProgrammers">(Programmers can read more about this
<link
linkend="pgui_misc_charset">here...</link>)</phrase></para>
</listitem>
<listitem>
<para><indexterm>
<primary>output_encoding</primary>
</indexterm><literal>output_encoding</literal>: Tells
FreeMarker what the charset of the output is. As FreeMarker
outputs a stream of UNICODE characters (<phrase
role="forProgrammers">it writes into a
<literal>java.io.Writer</literal></phrase>), it's not affected
by the output encoding, but some macros/functions and built-ins
may want to use this information.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>classic_compatible</primary>
</indexterm><literal>classic_compatible</literal>: Used for
better compatibility with very old FreeMarker versions (mostly
1.7.x). See the documentation of
<literal>freemarker.template.Configurable.isClassicCompatible()</literal>
for more information.</para>
</listitem>
</itemizedlist>
<para>Example: Assume that the initial locale of template is
<literal>de_DE</literal> (German). Then this:</para>
<programlisting role="template">${1.2}
&lt;#setting locale="en_US"&gt;
${1.2}</programlisting>
<para>will output this:</para>
<programlisting role="output">1,2
1.2</programlisting>
<para>because German people use the comma as their decimal
separator, while US people use the dot.</para>
</section>
</section>
<section xml:id="ref_directive_stop">
<title>stop</title>
<anchor xml:id="ref.directive.stop"/>
<indexterm>
<primary>stop directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#stop&gt;</literal>
or
<literal>&lt;#stop <replaceable>reason</replaceable>&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>reason</replaceable></literal>:
Informative message that describes the reason of the terminating
error. Expression, must evaluate to a string.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>Aborts template processing with the given (optional) error
message. <emphasis>This must not be used for ending template
processing in normal situations!</emphasis> The caller of the
FreeMarker template will see this as a failed template rendering,
not as a normally finished one.</para>
<para><phrase role="forProgrammers">This directive throws a
<literal>StopException</literal>, and the
<literal>StopException</literal> will hold the value of the reason
parameter.</phrase></para>
</section>
</section>
<section xml:id="ref_directive_switch">
<title>switch, case, default, break</title>
<anchor xml:id="ref.directive.switch"/>
<anchor xml:id="ref.directive.case"/>
<anchor xml:id="ref.directive.default"/>
<anchor xml:id="ref.directive.switch.break"/>
<indexterm>
<primary>switch directive</primary>
</indexterm>
<indexterm>
<primary>case directive</primary>
</indexterm>
<indexterm>
<primary>default directive</primary>
</indexterm>
<indexterm>
<primary>break directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#switch <replaceable>value</replaceable>&gt;
&lt;#case <replaceable>refValue1</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#break&gt;
&lt;#case <replaceable>refValue2</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#break&gt;
<replaceable>...</replaceable>
&lt;#case <replaceable>refValueN</replaceable>&gt;
<replaceable>...</replaceable>
&lt;#break&gt;
&lt;#default&gt;
<replaceable>...</replaceable>
&lt;/#switch&gt;
</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>value</replaceable></literal>,
<literal><replaceable>refValue1</replaceable></literal>, etc.:
Expressions evaluates to scalars of the same type.</para>
</listitem>
</itemizedlist>
<para>The <literal>break</literal>-s and <literal>default</literal>
are optional.</para>
</section>
<section>
<title>Description</title>
<para>The usage of this directive is not recommended, as it's
error-prone because of the fall-through behavior. Use <link
linkend="ref.directive.elseif"><literal>elseif</literal></link>-s
instead unless you want to exploit the fall-through behavior.</para>
<para>Switch is used to choose a fragment of template depending on
the value of an expression:</para>
<programlisting role="template">&lt;#switch animal.size&gt;
&lt;#case "small"&gt;
This will be processed if it is small
&lt;#break&gt;
&lt;#case "medium"&gt;
This will be processed if it is medium
&lt;#break&gt;
&lt;#case "large"&gt;
This will be processed if it is large
&lt;#break&gt;
&lt;#default&gt;
This will be processed if it is neither
&lt;/#switch&gt;</programlisting>
<para>Inside the <literal>switch</literal> must be one or more
<literal>&lt;#case <replaceable>value</replaceable>&gt;</literal>,
and after all such <literal>case</literal> tags optionally one
<literal>&lt;#default&gt;</literal>. When FM reaches the
<literal>switch</literal> directive, it chooses a
<literal>case</literal> directive where
<literal><replaceable>refValue</replaceable></literal> equals with
<literal><replaceable>value</replaceable></literal> and continues
the processing of the template there. If there is no
<literal>case</literal> directive with appropriate value then it
continues processing at the <literal>default</literal> directive if
that exists, otherwise it continues the processing after the end-tag
of <literal>switch</literal>. And now comes the confusing thing:
when it has chosen a <literal>case</literal> directive, it will
continue the processing there, and will go ahead until it reaches a
<literal>break</literal> directive. That is, it will not
automatically leave the <literal>switch</literal> directive when it
reaches another <literal>case</literal> directive or the
<literal>&lt;#default&gt;</literal> tag. Example:</para>
<programlisting role="template">&lt;#switch x&gt;
&lt;#case 1&gt;
1
&lt;#case 2&gt;
2
&lt;#default&gt;
d
&lt;/#switch&gt;</programlisting>
<para>If <literal>x</literal> is 1, then it will print 1 2 d; if
<literal>x</literal> is 2 then it will print 2 d; if
<literal>x</literal> is 3 then it will print d. This is the
mentioned fall-through behavior. The <literal>break</literal> tag
instructs FM to immediately skip past the <literal>switch</literal>
end-tag.</para>
</section>
</section>
<section xml:id="ref_directive_t">
<title>t, lt, rt</title>
<anchor xml:id="ref.directive.t"/>
<anchor xml:id="ref.directive.lt"/>
<anchor xml:id="ref.directive.rt"/>
<indexterm>
<primary>t directive</primary>
</indexterm>
<indexterm>
<primary>lt directive</primary>
</indexterm>
<indexterm>
<primary>rt directive</primary>
</indexterm>
<indexterm>
<primary>trimmer directives</primary>
</indexterm>
<indexterm>
<primary>white-space removal</primary>
<secondary>trimming</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;#t&gt;</literal>
<literal>&lt;#lt&gt;</literal>
<literal>&lt;#rt&gt;</literal></programlisting>
</section>
<section>
<title>Description</title>
<para>These directives, instruct FreeMarker to ignore certain
white-space in the line of the tag:</para>
<itemizedlist>
<listitem>
<para><literal>t</literal> (for trim): Ignore all leading and
trailing white-space in this line.</para>
</listitem>
<listitem>
<para><literal>lt</literal> (for left trim): Ignore all leading
white-space in this line.</para>
</listitem>
<listitem>
<para><literal>rt</literal> (for right trim): Ignore all
trailing white-space in this line.</para>
</listitem>
</itemizedlist>
<para>where:</para>
<itemizedlist>
<listitem>
<para><quote>leading white-space</quote> means all space and tab
(and other character that are white-space according to <link
linkend="gloss.unicode">UNICODE</link>, except <link
linkend="gloss.lineBreak">line breaks</link>) before the first
non-white-space character of the line.</para>
</listitem>
<listitem>
<para><quote>trailing white-space</quote> means all space and
tab (and other character that are white-space according to <link
linkend="gloss.unicode">UNICODE</link>, except line breaks)
after the last non-white-space character of the line,
<emphasis>and</emphasis> the line break at the end of the
line.</para>
</listitem>
</itemizedlist>
<para>It is important to understand that these directives examine
the template itself, and <emphasis>not</emphasis> the output what
the template generates when you merge it with the data-model.
<phrase role="forProgrammers">(That is, the white-space removal
happens on parse time.)</phrase></para>
<para>For example this:</para>
<programlisting role="template">--
1 &lt;#t&gt;
2&lt;#t&gt;
3&lt;#lt&gt;
4
5&lt;#rt&gt;
6
--
</programlisting>
<para>will output this:</para>
<programlisting role="output">--
1 23
4
5 6
--</programlisting>
<para>The placement of these directives inside the line has no
importance. That is, the effect will be the same regardless if you
put the directive at the beginning of the line, or at the end of the
line, or in the middle of the line.</para>
</section>
</section>
<section xml:id="ref_directive_userDefined">
<title>User-defined directive (&lt;@...&gt;)</title>
<anchor xml:id="ref.directive.userDefined"/>
<indexterm>
<primary>user-defined directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;@<replaceable>user_def_dir_exp</replaceable> <replaceable>param1</replaceable>=<replaceable>val1</replaceable> <replaceable>param2</replaceable>=<replaceable>val2</replaceable> <replaceable>...</replaceable> <replaceable>paramN</replaceable>=<replaceable>valN</replaceable>/&gt;</literal>
(Note the XML-style <literal>/</literal> before the <literal>&gt;</literal>)
or if you need loop variables (<link
linkend="ref_directive_userDefined_loopVar">more details...</link>)
<literal>&lt;@<replaceable>user_def_dir_exp</replaceable> <replaceable>param1</replaceable>=<replaceable>val1</replaceable> <replaceable>param2</replaceable>=<replaceable>val2</replaceable> <replaceable>...</replaceable> <replaceable>paramN</replaceable>=<replaceable>valN</replaceable> ; <replaceable>lv1</replaceable>, <replaceable>lv2</replaceable>, <replaceable>...</replaceable>, <replaceable>lvN</replaceable>/&gt;</literal>
Or the same as the above two but with end-tag (<link
linkend="ref_directive_userDefined_entTag">more details...</link>):
<literal>&lt;@<replaceable>user_def_dir_exp</replaceable> <replaceable>...</replaceable>&gt;
...
&lt;/@<replaceable>user_def_dir_exp</replaceable>&gt;</literal>
or
<literal>&lt;@<replaceable>user_def_dir_exp</replaceable> <replaceable>...</replaceable>&gt;
...
&lt;/@&gt;</literal>
Or all above but with positional parameter passing (<link
linkend="ref_directive_userDefined_positionalParam">more details...</link>):
<literal>&lt;@<replaceable>user</replaceable> <replaceable>val1</replaceable>, <replaceable>val2</replaceable>, <replaceable>...</replaceable>, <replaceable>valN</replaceable>/&gt;</literal>
...etc.
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>user_def_dir_exp</replaceable></literal>:
Expression evaluates to an user-defined directive (for example a
macro), that will be called.</para>
</listitem>
<listitem>
<para><literal><replaceable>param1</replaceable></literal>,
<literal><replaceable>param2</replaceable></literal>, ...etc.:
The name of parameters. They are <emphasis>not</emphasis>
expressions.</para>
</listitem>
<listitem>
<para><literal><replaceable>val1</replaceable></literal>,
<literal><replaceable>val2</replaceable></literal>, ...etc.: The
value of parameters. They <emphasis>are</emphasis>
expressions.</para>
</listitem>
<listitem>
<para><literal><replaceable>lv1</replaceable></literal>,
<literal><replaceable>lv2</replaceable></literal>, ...etc.: The
name of <link linkend="dgui_misc_var">loop variables</link>.
They are <emphasis>not</emphasis> expressions.</para>
</listitem>
</itemizedlist>
<para>The number of parameters can be 0 (i.e. no parameters).</para>
<para>The order of parameters is not significant (unless you use
positional parameter passing). The name of parameters must be
unique. Lower- and uppercase letters are considered as different
letters in parameter names (i.e. <literal>Color</literal> and
<literal>color</literal> is not the same).</para>
</section>
<section>
<title>Description</title>
<para>This will call an user-defined directive, for example a macro.
The meaning of parameters, and the set of supported and required
parameters depend on the concrete user-defined directive.</para>
<para>You may read <link linkend="dgui_misc_userdefdir">the tutorial
about user-defined directives</link>.</para>
<para>Example 1: Calls the directive that is stored in the variable
<literal>html_escape</literal>:</para>
<programlisting role="template">&lt;@html_escape&gt;
a &lt; b
Romeo &amp; Juliet
&lt;/@html_escape&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> a &amp;lt; b
Romeo &amp;amp; Juliet</programlisting>
<para>Example 2: Calls a macro with parameters:</para>
<programlisting role="template">&lt;@list items=["mouse", "elephant", "python"] title="Animals"/&gt;
<replaceable>...</replaceable>
&lt;#macro list title items&gt;
&lt;p&gt;${title?cap_first}:
&lt;ul&gt;
&lt;#list items as x&gt;
&lt;li&gt;${x?cap_first}
&lt;/#list&gt;
&lt;/ul&gt;
&lt;/#macro&gt;</programlisting>
<para>Output:</para>
<programlisting role="output"> &lt;p&gt;Animals:
&lt;ul&gt;
&lt;li&gt;Mouse
&lt;li&gt;Elephant
&lt;li&gt;Python
&lt;/ul&gt;
<replaceable>...</replaceable></programlisting>
<section xml:id="ref_directive_userDefined_entTag">
<title>End-tag</title>
<para>You can omit the
<literal><replaceable>user_def_dir_exp</replaceable></literal> in
the <link linkend="gloss.endTag">end-tag</link>. That is, you can
always write <literal>&lt;/@&gt;</literal> instead of
<literal>&lt;/@<replaceable>anything</replaceable>&gt;</literal>.
This rule is mostly useful when the
<literal><replaceable>user_def_dir_exp</replaceable></literal>
expression is too complex, because you don't have to repeat the
expression in the end-tag. Furthermore, if the expression contains
other than simple variable names and dots, you are not allowed to
repeat the expression. For example,
<literal>&lt;@a_hash[a_method()]&gt;<replaceable>...</replaceable>&lt;/@a_hash[a_method()]&gt;</literal>
is an error; you must write
<literal>&lt;@a_hash[a_method()]&gt;<replaceable>...</replaceable>&lt;/@&gt;</literal>.
But
<literal>&lt;@a_hash.foo&gt;<replaceable>...</replaceable>&lt;/@a_hash.foo&gt;</literal>
is OK.</para>
<para>There's also a special rule that says that if the
<literal><replaceable>user_def_dir_exp</replaceable></literal>
ends with <literal><link
linkend="ref_builtin_with_args">?with_args(<replaceable>...</replaceable>)</link></literal>,
then that's ignored when the end-tag is matched, so you can write
something like
<literal>&lt;@myMacro?with_args(args)&gt;<replaceable>...</replaceable>&lt;/@myMacro&gt;</literal>.</para>
</section>
<section xml:id="ref_directive_userDefined_loopVar">
<title>Loop variables</title>
<para>Some user-defined directives create loop variables
(similarly to <literal>list</literal> directive). 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 variable is set by the
directive itself. In the case of user-defined directives the
syntax is that the name of loop variables is given after a
semicolon. For example:</para>
<programlisting role="template">&lt;@myRepeatMacro count=4 ; <emphasis>x, last</emphasis>&gt;
${<emphasis>x</emphasis>}. Something... &lt;#if <emphasis>last</emphasis>&gt; This was the last!&lt;/#if&gt;
&lt;/@myRepeatMacro&gt;</programlisting>
<para>Note that the number of loop variable created by the
user-defined directive and the number of loop variables specified
after the semicolon need not match. Say, if you are not interested
if the repetition is the last, you can simply write:</para>
<programlisting role="template">&lt;@myRepeatMacro count=4 ; <emphasis>x</emphasis>&gt;
${<emphasis>x</emphasis>}. Something...
&lt;/@myRepeatMacro&gt;</programlisting>
<para>or you can even:</para>
<programlisting role="template">&lt;@myRepeatMacro count=4&gt;
Something...
&lt;/@myRepeatMacro&gt;</programlisting>
<para>Furthermore, it does not cause error if you specify more
loop variables after the semicolon than the user-defined directive
creates, just the last few loop variables will not be created
(i.e. those will be undefined in the nested content). Trying to
use the undefined loop variables, however, will cause error
(unless you use built-ins like <literal>?default</literal>), since
you try to access a non-existing variable.</para>
<para>See the <link linkend="dgui_misc_userdefdir">the tutorial
about user-defined directives</link> for more explanation.</para>
</section>
<section xml:id="ref_directive_userDefined_positionalParam">
<title>Positional parameter passing</title>
<indexterm>
<primary>positional parameter passing</primary>
</indexterm>
<para>Positional parameter passing (as <literal>&lt;@heading
"Preface", 1/&gt;</literal>) is a shorthand form of normal named
parameter passing (as <literal>&lt;@heading title="Preface"
level=1/&gt;</literal>), where you omit the parameter name. This
shorthand form should be used if a user-defined directive has only
one parameter, or if it is easy to remember the order of
parameters for a frequently used user-defined directive. To use
this form, you have to know the order in which the named
parameters are declared (trivial if the directive has only one
parameter). Say, if <literal>heading</literal> was created as
<literal>&lt;#macro heading title
level&gt;<replaceable>...</replaceable></literal>, then
<literal>&lt;@heading "Preface", 1/&gt;</literal> is equivalent
with <literal>&lt;@heading title="Preface" level=1/&gt;</literal>
(or <literal>&lt;@heading level=1 title="Preface"/&gt;</literal>;
if you use parameter names, the order is not important). Note that
positional parameter passing is currently only supported for
macros.</para>
</section>
</section>
</section>
<section xml:id="ref_directive_visit">
<title>visit, recurse, fallback</title>
<anchor xml:id="ref.directive.visit"/>
<indexterm>
<primary>visit directive</primary>
</indexterm>
<indexterm>
<primary>recurse directive</primary>
</indexterm>
<indexterm>
<primary>fallback directive</primary>
</indexterm>
<indexterm>
<primary>recursion</primary>
<secondary>iterate</secondary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#visit <replaceable>node</replaceable> using <replaceable>namespace</replaceable>&gt;</literal>
or
<literal>&lt;#visit <replaceable>node</replaceable>&gt;</literal></programlisting>
<programlisting role="metaTemplate"><literal>&lt;#recurse <replaceable>node</replaceable> using <replaceable>namespace</replaceable>&gt;</literal>
or
<literal>&lt;#recurse <replaceable>node</replaceable>&gt;</literal>
or
<literal>&lt;#recurse using <replaceable>namespace</replaceable>&gt;</literal>
or
<literal>&lt;#recurse&gt;</literal></programlisting>
<programlisting role="metaTemplate"><literal>&lt;#fallback&gt;</literal></programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>node</replaceable></literal>:
Expression evaluates to a <link linkend="xgui_expose_dom">node
variable</link>.</para>
</listitem>
<listitem>
<para><literal><replaceable>namespace</replaceable></literal>: A
<link linkend="dgui_misc_namespace">namespace</link>, or a
sequence of namespaces. A namespace can be given with the
namespace hash (a.k.a. gate hash), or with a string literal that
store the path of template that could be imported. Instead of
namespace hashes, you can use plain hashes as well.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>The <literal>visit</literal> and <literal>recurse</literal>
directives are used for the recursive processing of trees. In
practice, this will mostly be used for <link
linkend="xgui">processing XML.</link></para>
<section>
<title>Visit</title>
<para>When you call <literal>&lt;#visit
<replaceable>node</replaceable>&gt;</literal>, it looks for a
user-defined directive (like a macro) to invoke that has the name
deducted from the node's name
(<literal><replaceable>node</replaceable>?node_name</literal>) and
namespace
(<literal><replaceable>node</replaceable>?node_namespace</literal>).
The rules of name deduction:</para>
<itemizedlist>
<listitem>
<para>If the node doesn't support node namespaces (as text
nodes in XML), then the directive name is simply the name of
the node
(<literal><replaceable>node</replaceable>?node_name</literal>).
<phrase role="forProgrammers">A node does not support node
namespaces if the <literal>getNodeNamespace</literal> method
returns <literal>null</literal>.</phrase></para>
</listitem>
<listitem>
<para>If the node does support node namespaces (as element
nodes in XML), then a prefix deduced from the node namespace
maybe appended before the node name with a colon used as
separator (e.g. <literal>e:book</literal>). The prefix, and if
there is a prefix used at all, depends on what prefixes has
been registered with the <literal>ns_prefixes</literal>
parameter of the <literal>ftl</literal> directive in the <link
linkend="dgui_misc_namespace">FTL namespace</link> where
<literal>visit</literal> looks for the handler directive
(which is not necessary the same as the FTL namespace where
<literal>visit</literal> was called from, as you will see
later). Concretely, if there was no default namespace
registered with <literal>ns_prefixes</literal> then for nodes
that does not belong to any namespace (<phrase
role="forProgrammers">when <literal>getNodeNamespace</literal>
returns <literal>""</literal></phrase>) no prefix is used. If
there was a default namespace registered with
<literal>ns_prefixes</literal> then for nodes that does not
belong to any namespace prefix <literal>N</literal> is used,
and for nodes that belong to the default node namespace no
prefix is used. Otherwise, in both case, the prefix associated
to the node namespace with the <literal>ns_prefixes</literal>
is used. If there is not prefix associated to the node
namespace of the node, then <literal>visit</literal> simply
behave as if there was no directive found with the proper
name.</para>
</listitem>
</itemizedlist>
<para>The node for which the user-defined directive was invoked is
available for it as special variable <literal>.node</literal>.
Example:</para>
<programlisting role="template">&lt;#-- Assume that nodeWithNameX?node_name is "x" --&gt;
&lt;#visit nodeWithNameX&gt;
Done.
&lt;#macro x&gt;
Now I'm handling a node that has the name "x".
Just to show how to access this node: this node has ${.node?children?size} children.
&lt;/#macro&gt;</programlisting>
<para>The output will be something like:</para>
<programlisting role="output"> Now I'm handling a node that has the name "x".
Just to show how to access this node: this node has 3 children.
Done.</programlisting>
<para>If one or more namespaces is specified using the optional
<literal>using</literal> clause, then <literal>visit</literal>
will look for the directives in those namespaces only, with the
earlier specified namespaces in the list getting priority. If no
<literal>using</literal> clause is specified, the namespace or
sequence of namespaces specified with the <literal>using</literal>
clause of the last uncompleted <literal>visit</literal> call is
reused. If there is no such pending <literal>visit</literal> call,
then the current namespace is used. For example, if you execute
this template:</para>
<programlisting role="template">&lt;#import "n1.ftl" as n1&gt;
&lt;#import "n2.ftl" as n2&gt;
&lt;#-- This will call n2.x (because there is no n1.x): --&gt;
&lt;#visit nodeWithNameX using [n1, n2]&gt;
&lt;#-- This will call the x of the current namespace: --&gt;
&lt;#visit nodeWithNameX&gt;
&lt;#macro x&gt;
Simply x
&lt;/#macro&gt;</programlisting>
<para>and this is <literal>n1.ftl</literal>:</para>
<programlisting role="template">&lt;#macro y&gt;
n1.y
&lt;/#macro&gt;</programlisting>
<para>and this is <literal>n2.ftl</literal>:</para>
<programlisting role="template">&lt;#macro x&gt;
n2.x
&lt;#-- This callc n1.y as it inherits the "using [n1, n2]" from the pending visit call: --&gt;
&lt;#visit nodeWithNameY&gt;
&lt;#-- This will call n2.y: --&gt;
&lt;#visit nodeWithNameY using .namespace&gt;
&lt;/#macro&gt;
&lt;#macro y&gt;
n2.y
&lt;/#macro&gt;</programlisting>
<para>then this will print:</para>
<programlisting role="output">
n2.x
n1.y
n2.y
Simply x
</programlisting>
<para>If <literal>visit</literal> doesn't find a user-defined
directive in either FTL namespaces with the name identical to the
name deduced with the rules described earlier, then it tries to
find an user-defined directive with name
<literal>@<replaceable>node_type</replaceable></literal>, or if
the node does not support node type property (i.e.
<literal><replaceable>node</replaceable>?node_type</literal>
returns undefined variable), then with name
<literal>@default</literal>. For the lookup, it uses the same
mechanism as was explained earlier. If it still doesn't find an
user-defined directive to handle the node, then
<literal>visit</literal> stops template processing with error.
Some XML specific node types have special handling in this regard;
see: <xref linkend="xgui_declarative_details"/>. Example:</para>
<programlisting role="template">&lt;#-- Assume that nodeWithNameX?node_name is "x" --&gt;
&lt;#visit nodeWithNameX&gt;
&lt;#-- Assume that nodeWithNameY?node_type is "foo" --&gt;
&lt;#visit nodeWithNameY&gt;
&lt;#macro x&gt;
Handling node x
&lt;/#macro&gt;
&lt;#macro @foo&gt;
There was no specific handler for node ${node?node_name}
&lt;/#macro&gt;</programlisting>
<para>This would print:</para>
<programlisting role="output">Handling node x
There was no specific handler for node y
</programlisting>
</section>
<section>
<title>Recurse</title>
<anchor xml:id="ref.directive.recurse"/>
<para>The <literal>&lt;#recurse&gt;</literal> directive is really
syntactic sugar. It visits all children nodes of the node (and not
the node itself). So, to write:</para>
<programlisting role="template">&lt;#recurse <replaceable>someNode</replaceable> using <replaceable>someLib</replaceable>&gt;</programlisting>
<para>is equivalent to writing:</para>
<programlisting role="template">&lt;#list <replaceable>someNode</replaceable>?children as <replaceable>child</replaceable>&gt;&lt;#visit <replaceable>child</replaceable> using <replaceable>someLib</replaceable>&gt;&lt;/#list&gt;</programlisting>
<para>However, target node is optional in the
<literal>recurse</literal> directive. If the target node is
unspecified, it simply uses the <literal>.node</literal>. Thus,
the terse instruction <literal>&lt;#recurse&gt;</literal> is
equivalent to:</para>
<programlisting role="template">&lt;#list .node?children as child&gt;&lt;#visit child&gt;&lt;/#list&gt;</programlisting>
<para>As a side comment for those who are familiar with XSLT,
<literal>&lt;#recurse&gt;</literal> is pretty much exactly
analogous to the <literal>&lt;xsl:apply-templates/&gt;</literal>
instruction in XSLT.</para>
</section>
<section>
<title>Fallback</title>
<anchor xml:id="ref.directive.fallback"/>
<para>As you could learn earlier, in the documentation of the
<literal>visit</literal> directive, the user-defined directive
that handles the node is maybe searched in multiple FTL
name-spaces. The <literal>fallback</literal> directive can be used
in a user-defined directive that was invoked to handle a node. It
directs FreeMarker to continue the searching for the user-defined
directive in the further name-spaces (that is, in the name-spaces
that are after the name-space of the currently invoked
user-defined directive in the list of name-spaces). If a handler
for the node is found then it is invoked, otherwise
<literal>fallback</literal> does nothing.</para>
<para>A typical usage of this to write customization layer over a
handler library, that sometimes passes the handling to the
customized library:</para>
<programlisting role="template">&lt;#import "/lib/docbook.ftl" as docbook&gt;
&lt;#--
We use the docbook library, but we override some handlers
in this namespace.
--&gt;
&lt;#visit document using [.namespace, docbook]&gt;
&lt;#--
Override the "programlisting" handler, but only in the case if
its "role" attribute is "java"
--&gt;
&lt;#macro programlisting&gt;
&lt;#if .node.@role[0]!"" == "java"&gt;
&lt;#-- Do something special here... --&gt;
...
&lt;#else&gt;
&lt;#-- Just use the original (overidden) handler --&gt;
&lt;#fallback&gt;
&lt;/#if&gt;
&lt;/#macro&gt;</programlisting>
</section>
</section>
</section>
</chapter>
<chapter xml:id="ref_specvar">
<title>Special Variable Reference</title>
<indexterm>
<primary>special variable</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. For
example, you can't write simply <literal>version</literal>; you have to
write <literal>.version</literal>.</para>
<note>
<para>As of FreeMarker 2.3.23, you can use camel case instead of snake
case for special variable names, like <literal>dataModel</literal>
instead of <literal>data_model</literal>. But know that then within
the same template, FreeMarker will enforce the usage of camel case for
all identifiers that are part of the template language (user defined
names are not affected).</para>
</note>
<para>The supported special variables are:</para>
<itemizedlist spacing="compact">
<listitem xml:id="specvar.args">
<para><indexterm>
<primary>args</primary>
</indexterm><literal>args</literal> (since 2.3.30): Used inside
the <link
linkend="ref.directive.macro"><literal>macro</literal></link> and
<link
linkend="ref.directive.function"><literal>function</literal></link>
directives, it returns all arguments of the current invocation of
the macro or function. This allows processing all the arguments in
an uniform way (like pass them to the <link
linkend="ref_builtin_with_args"><literal>with_args</literal>
built-in</link>). Further details:</para>
<itemizedlist>
<listitem>
<para>When used inside a macro, <literal>.args</literal> is
always a hash that maps the parameter names to the parameter
values. That's so even if the macro was called with positional
arguments, as the parameter names are declared by the
<literal>macro</literal> directive. But when used inside a
function, <literal>.args</literal> is always a sequence of the
argument values. That's because functions can only be called
with positional arguments, so the parameter names declared
inside the <literal>function</literal> directive aren't
relevant.</para>
</listitem>
<listitem>
<para>For arguments that have a default value (as
<literal>b</literal> in <literal>&lt;#macro m1 a
b=0&gt;</literal>), if the caller of the macro or function has
omitted that argument (as in <literal>&lt;@m1 a=1
/&gt;</literal>), <literal>.args</literal> will contain the
default value for that argument (<literal>{'a': 1, 'b':
0}</literal>).</para>
</listitem>
<listitem>
<para>If there's a catch-all argument, like
<literal>others</literal> in <literal>&lt;#macro m2 a, b,
others...&gt;</literal>, then <literal>.args</literal> will
contain the elements in the the catch-all parameter directly,
and won't contain the declared catch-all parameter
(<literal>others</literal>) itself. So for <literal>&lt;@m2 a=1
b=2 c=3 d=4 /&gt;</literal> it will be <literal>{'a': 1, 'b': 2,
'c': 3, 'd': 4}</literal>, and <emphasis>not</emphasis>
<literal>{'a': 1, 'b': 2, 'others': {'c':3, 'd':
4}}</literal>.</para>
</listitem>
<listitem>
<para>If a macro has a catch-all parameter, and the actual
catch-all argument is not empty, and the macro uses
<literal>.args</literal> somewhere, it can only be called with
named arguments (like <literal>&lt;@m a=1 b=2 /&gt;</literal>),
and not with positional arguments (like <literal>&lt;@m 1 2
/&gt;</literal>). That's because for macros
<literal>.args</literal> is always a hash, but if the arguments
are positional, the catch-all arguments won't have names, so
it's impossible to put them into the hash.</para>
</listitem>
<listitem>
<para><literal>.args</literal> is initialized immediately when
the macro or function is called, and so it doesn't reflect
changes made later on the local variables that correspond to the
arguments. (However, if the argument value is a mutable object,
and the objects itself is mutated, <literal>.args</literal> will
contain the mutated object. Setting an argument variable with
the <link linkend="ref.directive.local"><literal>local</literal>
directive</link> doesn't mutate the object.)</para>
</listitem>
<listitem>
<para><literal>.args</literal> must occur inside a
<literal>macro</literal> or <literal>function</literal>
directive on the source code level, or else it's a template
parsing error. So you can't use it in a template fragment that
you insert dynamically into a macro or function (like via the
<link linkend="ref.directive.include"><literal>include</literal>
directive</link>, <link
linkend="ref_builtin_eval"><literal>eval</literal>
built-in</link>, or <link
linkend="ref_builtin_interpret"><literal>interpret</literal>
built-in</link>). That's because the <literal>macro</literal> or
<literal>function</literal> has to know if it contains
<literal>.args</literal> earlier than it's called.</para>
</listitem>
<listitem>
<para>For macros, the order of elements in the
<literal>.args</literal> hash is the same as the order in which
the parameters were declared in the <literal>macro</literal>
directive, and not the order the caller has used. Except,
catch-all arguments will use the order that the caller used.
(For functions and methods, as it only support positional
arguments, the parameter order of on the caller side is the same
as the parameter order in the <literal>function</literal>
directive or Java method, so there's no doubt there.)</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><indexterm>
<primary>auto_esc</primary>
</indexterm><literal>auto_esc</literal> (since 2.3.24): Boolean
value that tells if auto-escaping (based on output format) is on or
off at the place where this variable is referred (resolved
statically). This is <emphasis>not</emphasis> affected by the
deprecated <literal>escape</literal> directive. This only deals with
automatic escaping based on the output format mechanism.</para>
</listitem>
<listitem>
<para xml:id="ref_specvar_caller_template_name"><indexterm>
<primary>caller_template_name</primary>
</indexterm><literal>caller_template_name</literal> (available
since FreeMarker 2.3.28): Returns the name (path) of the template
from which the current <link
linkend="ref.directive.macro">macro</link> or <link
linkend="ref.directive.function">function</link> was called. It's
mostly useful if you want to resolve paths relative to the caller
template (<link linkend="ref_builtin_absolute_template_name">see an
example here</link>). To serve that purpose better, if the caller
template is nameless, this will be an empty string (not a missing
value). Reading this variable will cause error if you aren't inside
a macro or function call. In particular, directives and
<quote>methods</quote> implemented in Java will not influence the
value of this variable; it's only for macros and functions
implemented in templates. (<phrase
role="forProgrammers"><literal>TemplateDirectiveModel</literal>
implementations can get similar information via the
<literal>freemarker.core.DirectiveCallPlace</literal>
object.</phrase>)</para>
</listitem>
<listitem>
<para><indexterm>
<primary>current_template_name</primary>
</indexterm><literal>current_template_name</literal>: The name of
the template where we are now (available since FreeMarker 2.3.23).
This can be missing (<literal>null</literal>) if the template was
created on-the-fly in Java <phrase role="forProgrammers">(via
<literal>new Template(null,
<replaceable>...</replaceable>)</literal>)</phrase>, rather than
loaded from a backing store by name <phrase
role="forProgrammers">(via
<literal><replaceable>cfg</replaceable>.getTemplate(name,
<replaceable>...</replaceable>)</literal>)</phrase>. Migration
notice: If you replace the deprecated
<literal>template_name</literal> with this, note that the later is a
0-length string instead of missing (<literal>null</literal>) if the
template has no name, so you might want to write
<literal>current_template_name!''</literal> in legacy
templates.</para>
</listitem>
<listitem>
<para><literal>data_model</literal>: A hash that you can use to
access the data-model directly. That is, variables you did with
<literal>global</literal> directive are not visible here.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>error</primary>
</indexterm><literal>error</literal> (available since FreeMarker
2.3.1): This variable accessible in the body of the <link
linkend="ref.directive.attempt"><literal>recover</literal>
directive</link>, where it stores the error message of the error we
recover from.</para>
</listitem>
<listitem>
<para><literal>globals</literal>: A hash that you can use to access
the globally accessible variables: the data-model and the variables
created with <literal>global</literal> directive. Note that
variables created with <literal>assign</literal> or
<literal>macro</literal> are not globals, thus they never hide the
variables when you use <literal>globals</literal>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>incomplatible_improvements</primary>
</indexterm><literal>incompatible_improvements</literal> (since
FreeMarker 2.3.24): The <link
linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
setting</link> of the current FreeMarker configuration, as a
string.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>language</primary>
</indexterm><indexterm>
<primary>lang</primary>
</indexterm><literal>lang</literal>: Returns the language part of
the current value of the locale setting. For example if
<literal>.locale</literal> is <literal>en_US</literal>, then
<literal>.lang</literal> is <literal>en</literal>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>locale</primary>
</indexterm><literal>locale</literal>: Returns the current value
of the locale setting. This is a string, for example
<literal>en_US</literal>. For more information about locale strings
<link linkend="ref.directive.setting">see the
<literal>setting</literal> directive</link>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>locale_object</primary>
</indexterm><literal>locale_object</literal> (available since
FreeMarker 2.3.21): Returns the current value of the locale setting
as a <literal>java.util.Locale</literal> object, rather than as a
string. This meant to be used instead of <literal>.locale</literal>
when you want to pass it as a <literal>java.util.Locale</literal>
object to a Java method. (The <literal>Locale</literal> object will
be wrapped according the <literal>object_wrapper</literal> setting
value. Whether you can actually pass this value to a Java method as
a <literal>Locale</literal> object depends on the object wrapper,
but an object wrapper that let you call Java methods directly is
very unlikely to not support that.)</para>
</listitem>
<listitem>
<para><literal>locals</literal>: A hash that you can use to access
the local variables (the variables created with the
<literal>local</literal> directive, and the parameters of
macro).</para>
</listitem>
<listitem>
<para><literal>main</literal>: A hash that you can use to access the
main <link linkend="dgui_misc_namespace">namespace</link>. Note that
global variables like the variables of data-model are
<emphasis>not</emphasis> visible through this hash.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>main_template_name</primary>
</indexterm><literal>main_template_name</literal>: The name of the
top level template (available since FreeMarker 2.3.23). <phrase
role="forProgrammers">(In Java, this is the template for which
<literal>Template.process</literal> was called.) </phrase>This can
be missing (<literal>null</literal>) if the template was created
on-the-fly in Java <phrase role="forProgrammers">(via <literal>new
Template(null, <replaceable>...</replaceable>)</literal>)</phrase>,
rather than loaded from a backing store by name <phrase
role="forProgrammers">(via
<literal><replaceable>cfg</replaceable>.getTemplate(name,
<replaceable>...</replaceable>)</literal>)</phrase>. Migration
notice: If you replace the deprecated
<literal>template_name</literal> with this, note that the later is a
0-length string instead of missing (<literal>null</literal>) if the
template has no name, so you might want to write
<literal>main_template_name!''</literal> in legacy templates.</para>
</listitem>
<listitem>
<para><literal>namespace</literal>: A hash that you can use to
access the current <link
linkend="dgui_misc_namespace">namespace</link>. Note that global
variables like the variables of data-model are
<emphasis>not</emphasis> visible through this hash.</para>
</listitem>
<listitem>
<para><literal>node</literal> (alias <literal>current_node</literal>
for historical reasons): The node you are currently processing with
the visitor pattern (i.e. with the <link
linkend="ref_directive_visit"><literal>visit</literal>,
<literal>recurse</literal>, ...etc. directives</link>). Also, it
initially stores the root node when you use the <link
linkend="pgui_misc_ant">FreeMarker XML Ant task</link>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>now</primary>
</indexterm><indexterm>
<primary>current date-time</primary>
</indexterm><literal>now</literal>: Returns the current date-time.
Usage examples: "<literal>Page generated: ${.now}</literal>",
"<literal>Today is ${.now?date}</literal>", "<literal>The current
time is ${.now?time}</literal>".</para>
</listitem>
<listitem>
<para><indexterm>
<primary>output format</primary>
</indexterm> Returns the name of the current <link
linkend="dgui_misc_autoescaping_outputformat">output format</link>.
This value is never missing/null. It's maybe the string
<literal>"undefined"</literal>, which is just the name of the
default output format.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>output encoding</primary>
</indexterm><indexterm>
<primary>output charset</primary>
</indexterm><literal>output_encoding</literal> (available since
FreeMarker 2.3.1): Returns the name of the current output charset.
This special variable is not existent if the framework that
encapsulates FreeMarker doesn't specify the output charset for
FreeMarker. <phrase role="forProgrammers">(Programmers can read more
about charset issues <link
linkend="pgui_misc_charset">here...</link>)</phrase></para>
</listitem>
<listitem>
<para><literal>get_optional_template</literal>: This is a method
that's used when you need to include or import a template that's
possibly missing, and you need to handle that case on some special
way. <link linkend="ref_specvar_get_optional_template">More
details...</link></para>
</listitem>
<listitem>
<para><literal>pass</literal>: This is a macro that does nothing. It
has no parameters. Mostly used as no-op node handler in XML
processing.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>template_name</primary>
</indexterm><literal>template_name</literal>: <emphasis>Don't use
it, because its behavior is strange when macros are used; use
<literal>current_template_name</literal> or
<literal>main_template_name</literal> instead (see migration notices
there).</emphasis> Gives the name of the main template, or if we are
running an included or imported template, the name of that template.
When calling macros, it becomes rather confusing: the macro call
won't change the value of this special variable, but when
<literal>nested</literal> is called, it changes it to the name of
the template that belongs to the current namespace. (Available since
FreeMarker 2.3.14.)</para>
</listitem>
<listitem>
<para><indexterm>
<primary>URL escaping charset</primary>
</indexterm><indexterm>
<primary>URL escaping charset</primary>
</indexterm><literal>url_escaping_charset</literal> (available
since FreeMarker 2.3.1): If exists, it stores the name of the
charset that should be used for URL escaping. If this variable
doesn't exist that means that nobody has specified what charset
should be used for URL encoding yet. In this case the <link
linkend="ref_builtin_url"><literal>url</literal> built-in</link>
uses the charset specified by the <literal>output_encoding</literal>
special variable for URL encoding; custom mechanism may follow the
same logic. <phrase role="forProgrammers">(Programmers can read more
about charset issues <link
linkend="pgui_misc_charset">here...</link>)</phrase></para>
</listitem>
<listitem>
<para><indexterm>
<primary>output_format</primary>
</indexterm><literal>output_format</literal> (since 2.3.24): The
name of output format at the place where this variable is referred
(resolved statically), such as <literal>"HTML"</literal>,
<literal>"XML"</literal>, <literal>"RTF"</literal>,
<literal>"plainText"</literal>, <literal>"undefined"</literal>, etc.
<phrase role="forProgrammers">(The available names can be extended
by the programmers, by the
<literal>registered_custom_output_formats</literal>
setting.)</phrase></para>
</listitem>
<listitem>
<para><indexterm>
<primary>vars</primary>
</indexterm><literal>vars</literal>: Expression
<literal>.vars.foo</literal> returns the same variable as expression
<literal>foo</literal>. It's useful if for some reasons you have to
use square bracket syntax, since that works only for hash sub
variables, so you need an artificial parent hash. For example, to
read a top-level variable that has a strange name that would confuse
FreeMarker, you can write
<literal>.vars["A strange name!"]</literal>. Or, to access a
top-level variable with dynamic name given with variable
<literal>varName</literal> you can write
<literal>.vars[varName]</literal>. Note that the hash returned by
<literal>.vars</literal> does not support <literal>?keys</literal>
and <literal>?values</literal>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>version</primary>
</indexterm><literal>version</literal>: Returns the FreeMarker
version number as string, for example <literal>2.2.8</literal>. This
can be used to check which FreeMarker version does your application
use, but note that this special variable does not exist prior to the
2.3.0 or 2.2.8 versions. The version number of non-final releases
contains dash and further info after the numbers, like in
2.3.21-nightly_20140726T151800Z.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>time zone</primary>
</indexterm><indexterm>
<primary>time_zone</primary>
</indexterm><literal>time_zone</literal> (exists since FreeMarker
2.3.31): The current value of the <literal>time_zone</literal>
setting, as a string. This is the ID of the time zone, like
<literal>GMT+01:00</literal>, or
<literal>America/Los_Angeles</literal>.</para>
</listitem>
</itemizedlist>
<simplesect xml:id="ref_specvar_get_optional_template">
<title>Using get_optional_template</title>
<indexterm>
<primary>get_optional_template</primary>
</indexterm>
<indexterm>
<primary>include optional</primary>
</indexterm>
<indexterm>
<primary>import optional</primary>
</indexterm>
<para>This special variable is used when you need to include or import
a template that's possibly missing, and you need to handle that case
on some special way. It a method (so you meant to call it) that has
the following parameters:</para>
<orderedlist>
<listitem>
<para>The name of the template (can be relative or absolute), like
<literal>"/commonds/footer.ftl"</literal>; similar to the first
parameter of the <link
linkend="ref.directive.include"><literal>include</literal>
directive</link>. Required, string.</para>
</listitem>
<listitem>
<para>An optional hash of options, like <literal>{ 'parse': false,
'encoding': 'UTF-16BE' }</literal>. The valid keys are
<literal>encoding</literal> and <literal>parse</literal>. The
meaning of these are the same as of the similarly named <link
linkend="ref.directive.include"><literal>include</literal>
directive</link> parameters.</para>
</listitem>
</orderedlist>
<para>This method returns a hash that contains the following
entries:</para>
<itemizedlist>
<listitem>
<para><literal>exists</literal>: A boolean that tells if the
template was found.</para>
</listitem>
<listitem>
<para><literal>include</literal>: A directive that, when called,
includes the template. Calling this directive is similar to
calling the <link
linkend="ref.directive.include"><literal>include</literal>
directive</link>, but of course with this you spare looking up the
template again. This directive has no parameters, nor nested
content. If <literal>exists</literal> is <literal>false</literal>,
this key will be missing; see later how can this be utilized with
<link linkend="dgui_template_exp_missing_default">the
<literal><replaceable>exp</replaceable>!<replaceable>default</replaceable></literal>
operator</link>.</para>
</listitem>
<listitem>
<para><literal>import</literal>: A method that, when called,
imports the template, and returns the namespace of the imported
template. Calling this method is similar to calling the
<literal>import</literal> directive, but of course with this you
spare looking up the template again, also, it doesn't assign the
namespace to anything, just returns it. The method has no
parameters. If <literal>exists</literal> is
<literal>false</literal>, this key will be missing; see later how
can this be utilized with <link
linkend="dgui_template_exp_missing_default">the
<literal><replaceable>exp</replaceable>!<replaceable>default</replaceable></literal>
operator</link>.</para>
</listitem>
</itemizedlist>
<para>When this method is called (like
<literal>.get_optional_template('some.ftl')</literal>), it immediately
loads the template if it exists, but doesn't yet process it, so it
doesn't have any visible effect yet. The template will be processed
only when <literal>include</literal> or <literal>import</literal>
members of the returned structure is called. (Of course, when we say
that it loads the template, it actually looks it up in the template
cache, just like the <link
linkend="ref.directive.include"><literal>include</literal>
directive</link> does.)</para>
<para>While it's not an error if the template is missing, it's an
error if it does exist but still can't be loaded due to syntactical
errors in it, or due to some I/O error.</para>
<note>
<para>If the template fails with <quote>I/O error when trying to
load optional template</quote> when the template is missing, that's
often because your application uses a custom
<literal>freemarker.cache.TemplateLoader</literal> implementation,
which incorrectly (against the API documentation) throws an
<literal>IOException</literal> in the
<literal>findTemplateSource</literal> method instead of returning
<literal>null</literal> if a template is not found. If it's so, the
Java programmers need to fix that. Another possibility is of course
that it was indeed not possible to tell if the template exists or
not due to some technical issues, in which case stopping with error
is the correct behavior. See the cause
<literal>IOException</literal> in the Java stack trace to figure out
which case it is.</para>
</note>
<para>Example, in which depending on if <literal>some.ftl</literal>
exists, we either print <quote>Template was found:</quote> and the
include the template as <literal>&lt;#include 'some.ftl'&gt;</literal>
would, otherwise it we print <quote>Template was
missing.</quote>:</para>
<programlisting role="template">&lt;#assign optTemp = .get_optional_template('some.ftl')&gt;
&lt;#if optTemp.exists&gt;
Template was found:
&lt;@optTemp.include /&gt;
&lt;#else&gt;
Template was missing.
&lt;/#if&gt;</programlisting>
<para>Example, in which we try to include <literal>some.ftl</literal>,
but if that's missing then we try to include
<literal>some-fallback.ftl</literal>, and if that's missing too then
we call the <literal>ultimateFallback</literal> macro instead of
including anything (note the <literal>!</literal>-s after the
<literal>include</literal>-s; they belong to <link
linkend="dgui_template_exp_missing_default">the
<literal><replaceable>exp</replaceable>!<replaceable>default</replaceable></literal>
operator</link>):</para>
<programlisting role="template">&lt;#macro ultimateFallback&gt;
Something
&lt;/#macro&gt;
&lt;@(
.get_optional_template('some.ftl').include!
.get_optional_template('some-fallback.ftl').include!
ultimateFallback
) /&gt;</programlisting>
<para>Example, which behaves like <literal>&lt;#import 'tags.ftl' as
tags&gt;</literal>, except that if <literal>tags.ftl</literal> is
missing, then it creates an empty <literal>tags</literal> hash:</para>
<programlisting role="template">&lt;#assign tags = (.get_optional_template('tags.ftl').import())!{}&gt;</programlisting>
</simplesect>
</chapter>
<chapter xml:id="ref_reservednames">
<title>Reserved names in FTL</title>
<indexterm>
<primary>reserved name</primary>
</indexterm>
<para>The following names cannot be used for top-level variables without
square-bracket syntax (as <literal>.vars["in"]</literal>), since they
are keywords in FTL:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>true</literal>: boolean value
<quote>true</quote></para>
</listitem>
<listitem>
<para><literal>false</literal>: boolean value
<quote>false</quote></para>
</listitem>
<listitem>
<para><literal>gt</literal>: comparison operator <quote>greater
than</quote></para>
</listitem>
<listitem>
<para><literal>gte</literal>: comparison operator <quote>greater
than or equivalent</quote></para>
</listitem>
<listitem>
<para><literal>lt</literal>: comparison operator <quote>less
than</quote></para>
</listitem>
<listitem>
<para><literal>lte</literal>: comparison operator <quote>less than
or equivalent</quote></para>
</listitem>
<listitem>
<para><literal>as</literal>: used by a few directives</para>
</listitem>
<listitem>
<para><literal>in</literal>: used by a few directives</para>
</listitem>
<listitem>
<para><literal>using</literal>: used by a few directives</para>
</listitem>
</itemizedlist>
</chapter>
<chapter xml:id="ref_deprecated">
<title>Deprecated FTL constructs</title>
<indexterm>
<primary>deprecated</primary>
</indexterm>
<section xml:id="ref_depr_directive">
<title>List of deprecated directives</title>
<para>The following directives are deprecated, but still
working:</para>
<itemizedlist>
<listitem>
<para><link
linkend="ref.directive.call"><literal>call</literal></link>: use
<link linkend="ref.directive.userDefined">user-defined directive
call</link> instead</para>
</listitem>
<listitem>
<para><literal>comment</literal>: This is the old format of
<literal>&lt;#--<replaceable>...</replaceable>--&gt;</literal>.
Anything between the <literal>&lt;#comment&gt;</literal> and
<literal>&lt;/#comment&gt;</literal> will be ignored.</para>
</listitem>
<listitem>
<para><literal>foreach</literal>: it is a synonym of the
<literal>list</literal> directive with slightly different
parameter syntax. The syntax is <literal>&lt;#foreach
<replaceable>item</replaceable> in
<replaceable>sequence</replaceable>&gt;</literal> that is
equivalent with <literal>&lt;#list
<replaceable>sequence</replaceable> as
<replaceable>item</replaceable>&gt;</literal>.</para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.transform"><literal>transform</literal></link>:
use <link linkend="ref.directive.userDefined">user-defined
directive call</link> instead</para>
</listitem>
</itemizedlist>
<para>The following directives are not working anymore:</para>
<itemizedlist>
<listitem>
<para>Legacy <literal>function</literal>: Originally
<literal>function</literal> was used to define macros, and was
deprecated in favor of the <literal>macro</literal> directive. As
of FreeMarker 2.3, this directive is reintroduced with different
meaning: it is used to define methods.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_depr_builtin">
<title>List of deprecated built-ins</title>
<para>The following built-ins are deprecated, but still
working:</para>
<itemizedlist>
<listitem>
<para><indexterm>
<primary>default built-in</primary>
</indexterm> <literal>default</literal>: This was deprecated
with the introduction of the <link
linkend="dgui_template_exp_missing_default">default value
operator</link>.
<literal><replaceable>exp1</replaceable>?default(<replaceable>exp2</replaceable>)</literal>
is near equivalent with
<literal><replaceable>exp1</replaceable>!<replaceable>exp2</replaceable></literal>,
and
<literal>(<replaceable>exp1</replaceable>)?default(<replaceable>exp2</replaceable>)</literal>
is near equivalent with with
<literal>(<replaceable>exp1</replaceable>)!<replaceable>exp2</replaceable></literal>.
The only difference is that prior to FreeMarker 2.4, the
<literal>default</literal> built-in has always evaluated
<literal><replaceable>exp2</replaceable></literal>, while the
default value operator only evaluates it when the default value is
really needed. Starting from FreeMarker 2.4, however, the
<literal>default</literal> built-in was improved, and behaves
exactly like the default value operator.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>exists built-in</primary>
</indexterm><literal>exists</literal>: This was deprecated with
the introduction of the <link
linkend="dgui_template_exp_missing_test">missing value test
operator</link>.
<literal><replaceable>exp1</replaceable>?exists</literal> is
equivalent with
<literal><replaceable>exp1</replaceable>??</literal>, also
<literal>(<replaceable>exp1</replaceable>)?exists</literal> is
equivalent with with
<literal>(<replaceable>exp1</replaceable>)??</literal>.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>if_exists built-in</primary>
</indexterm><literal>if_exists</literal>: This was deprecated
with the introduction of the <link
linkend="dgui_template_exp_missing_default">default value
operator</link>.
<literal><replaceable>exp1</replaceable>?if_exists</literal> is
similar to <literal><replaceable>exp1</replaceable>!</literal>,
and <literal>(<replaceable>exp1</replaceable>)?if_exists</literal>
is similar to
<literal>(<replaceable>exp1</replaceable>)!</literal>. The
difference is that the default value with
<literal>if_exists</literal> is not only empty string, empty
sequence and empty hashs at the same time, but also boolean
<literal>false</literal> and a transform that does nothing and
ignores all parameters.</para>
</listitem>
<listitem>
<para><indexterm>
<primary>web_safe built-in</primary>
</indexterm><literal>web_safe</literal>: the same as <link
linkend="ref_builtin_html"><literal>html</literal></link></para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_depr_oldmacro">
<title>Old-style macro and call directives</title>
<anchor xml:id="ref.directive.oldmacro"/>
<anchor xml:id="ref.directive.call"/>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>&lt;#macro <replaceable>name</replaceable>(<replaceable>argName1</replaceable>, <replaceable>argName2</replaceable>, <replaceable>... argNameN</replaceable>)&gt;
...
&lt;/#macro&gt;</literal>
<literal>&lt;#call <replaceable>name</replaceable>(<replaceable>argValue1</replaceable>, <replaceable>argValue2</replaceable>, <replaceable>... argValueN</replaceable>)&gt;</literal></programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>name</replaceable></literal>: name
of the macro (not expression)</para>
</listitem>
<listitem>
<para><literal><replaceable>argName1</replaceable></literal>,
<literal><replaceable>argName2</replaceable></literal>, ...etc.:
the name of the <link linkend="dgui_misc_var">local
variables</link> store the parameter values (not
expression)</para>
</listitem>
<listitem>
<para><literal><replaceable>argValue1</replaceable></literal>,
<literal><replaceable>argValue2</replaceable></literal>,
...etc.: expressions, the value of the parameters</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<note>
<para>This is the documentation of FreeMarker 2.1 macro and macro
related directives. These are still working, but deprecated. You
may want to read the FreeMarker 2.2+ references: <link
linkend="ref.directive.macro">macro, return</link>, <link
linkend="ref.directive.userDefined">user-defined directive
call</link></para>
</note>
<para>A macro is a template fragment with an associated name. You
can use that named fragment on multiple places in your template, so
it helps in repetitive tasks. A macro can have parameters that
influence the output generated when you use the macro.</para>
<para>You define a macro with the <literal>macro</literal>
directive, and then you can use the defined macro in the whole
template. The <literal>macro</literal> directive itself does not
write anything to the output, it just defines the macro. For example
this will define a macro called <literal>warning</literal>:</para>
<programlisting role="template"><emphasis>&lt;#macro warning(message)&gt;</emphasis>
&lt;div align=center&gt;
&lt;table border=1 bgcolor=yellow width="80%"&gt;&lt;tr&gt;&lt;td align=center&gt;
&lt;b&gt;Warning!&lt;/b&gt;
&lt;p&gt;${message}
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
<emphasis>&lt;/#macro&gt;</emphasis></programlisting>
<para>The macro definition body (the section between the macro
start-tag and end-tag) will be processed whenever you use the
<literal>call</literal> directive with the name of the macro. For
example this calls the macro called
<literal>warning</literal>:</para>
<programlisting role="template">&lt;#call warning("Unplug the machine before opening the cover!")&gt;</programlisting>
<para>and will write this to the output:</para>
<programlisting role="output"> &lt;div align=center&gt;
&lt;table border=1 bgcolor=yellow width="80%"&gt;&lt;tr&gt;&lt;td align=center&gt;
&lt;b&gt;Warning!&lt;/b&gt;
&lt;p&gt;Unplug the machine before opening the cover!
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
</programlisting>
<para>The parameters passed in as parameters to the
<literal>call</literal> directive will be accessible in the macro
definition body as <link linkend="dgui_misc_var">local
variables</link>.</para>
<para>When you call a macro, you must specify the same number of
parameters as were specified in the macro definition. For example if
this is the macro definition:</para>
<programlisting role="template">&lt;#macro test(a, b, c)&gt;Nothing...&lt;/#macro&gt;</programlisting>
<para>then these are valid macro calls:</para>
<programlisting role="template">&lt;#call test(1, 2, 3)&gt;
&lt;#call test("one", 2 + x, [1234, 2341, 3412, 4123])&gt;</programlisting>
<para>If a macro has no parameters, then you can omit the
parentheses:</para>
<programlisting role="template">&lt;#macro test&gt;mooo&lt;/#macro&gt;
&lt;#call test&gt;</programlisting>
<para>When you define a macro it will be available in the template,
where you have defined it only. But probably you want to use the
same macros in more templates. In this case you can store your macro
definitions in a common file, and then include that file in all
templates where you need those macros.</para>
<para>It's fine to call a macro that's defined further down in the
template <phrase role="forProgrammers">(since macros are defined at
parse time, not in process time)</phrase>. However, if the macro
definitions are inserted with <literal>include</literal> directive,
they will not be available until FreeMarker has executed the
<literal>include</literal> directive.</para>
<para>You can leave a macro definition body before the
<literal>&lt;/#macro&gt;</literal> tag with the
<literal>return</literal> directive.</para>
</section>
</section>
<section xml:id="ref_depr_transform">
<title>Transform directive</title>
<anchor xml:id="ref.directive.transform"/>
<indexterm>
<primary>transform directive</primary>
</indexterm>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate">
<literal>&lt;transform <replaceable>transVar</replaceable>&gt;
<replaceable>...</replaceable>
&lt;/transform&gt;</literal>
or
<literal>&lt;transform <replaceable>transVar</replaceable> <replaceable>name1</replaceable>=<replaceable>value1</replaceable> <replaceable>name2</replaceable>=<replaceable>value2</replaceable> <replaceable>...</replaceable> <replaceable>nameN</replaceable>=<replaceable>valueN</replaceable>&gt;
<replaceable>...</replaceable>
&lt;/transform&gt;</literal>
</programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>transVar</replaceable></literal>:
Expression evaluates to a transform</para>
</listitem>
<listitem>
<para><literal><replaceable>name1</replaceable></literal>,
<literal><replaceable>name2</replaceable></literal>, ...
<literal><replaceable>nameN</replaceable></literal>: Name of
parameters. Literal value, not expression.</para>
</listitem>
<listitem>
<para><literal><replaceable>value1</replaceable></literal>,
<literal><replaceable>value2</replaceable></literal>, ...
<literal><replaceable>valueN</replaceable></literal>:
Expressions evaluate to the values of parameters</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<note>
<para>This directive is still working, but deprecated. You may
want to read about <link
linkend="ref.directive.userDefined">user-defined directive
calls</link> to see the replacement.</para>
</note>
<para>Captures the output generated inside its body (i.e. between
its start-tag and end-tag), and let the given transform modify it
before it is written to the final output.</para>
<para>Example:</para>
<programlisting role="template">&lt;p&gt;A very simple HTML file:
&lt;pre&gt;
<emphasis>&lt;transform html_escape&gt;</emphasis>
&lt;html&gt;
&lt;body&gt;
&lt;p&gt;Hello word!
&lt;/body&gt;
&lt;/html&gt;
<emphasis>&lt;/transform&gt;</emphasis>
&lt;/pre&gt;</programlisting>
<para>the output will be:</para>
<programlisting role="output">&lt;p&gt;A very simple HTML file:
&lt;pre&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;p&amp;gt;Hello word!
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;</programlisting>
<para>Some transforms may take parameters. The name and meaning of
parameters depends on the transform in question. For example here we
give a parameter called <quote>var</quote>:</para>
<programlisting role="template">&lt;#-- This transform stores the output in the variable x,
rather than sending it to the output --&gt;
&lt;transform capture_output<emphasis> var="x"</emphasis>&gt;
some test
&lt;/transform&gt;</programlisting>
<para>It is the task of the programmers to put the necessary
transforms into the data-model. For the name and usage of accessible
transforms ask the programmers. <phrase
role="forProgrammers">Initially there is a <link
linkend="pgui_config_sharedvariables">shared variable</link> for
most transforms in the
<literal>freemarker.template.utility</literal> package. For more
information see: <xref
linkend="pgui_config_sharedvariables"/></phrase></para>
</section>
</section>
<section xml:id="ref_depr_oldsyntax">
<title>Old FTL syntax</title>
<indexterm>
<primary>strict syntax</primary>
</indexterm>
<indexterm>
<primary>old FTL syntax</primary>
</indexterm>
<indexterm>
<primary>new FTL syntax</primary>
</indexterm>
<para>With the old FTL syntax the <literal>#</literal> was not
required (prior 2.1 not even allowed) in the FTL tags. For example,
you could write this:</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;We have there animals:
&lt;ul&gt;
<emphasis>&lt;list animals as animal&gt;</emphasis>
&lt;li&gt;${animal.name} for ${animal.price} Euros
<emphasis>&lt;/list&gt;</emphasis>
&lt;/ul&gt;
<emphasis>&lt;include "common_footer.html"&gt;</emphasis>
&lt;/body&gt;
&lt;/html&gt;</programlisting>
<para>While the <literal>#</literal>-less syntax was more natural for
HTML authors, it had too many drawbacks, so finally we have decided to
deprecate it. With the newer syntax (a.k.a <quote>strict
syntax</quote>), the <literal>#</literal> is strictly required. That
is, things like <literal>&lt;include
"common_footer.html"&gt;</literal> will go to the output as is, since
they are not considered as FTL tags. Note that user-defined directives
use <literal>@</literal> <emphasis>instead of</emphasis>
<literal>#</literal>.</para>
<para>However, to give users time to prepare for this change, in
FreeMarker 2.1 and 2.2 the usage of <literal>#</literal> is optional,
unless the programmer enables strict syntax mode in the FreeMarker
configuration by calling <literal>setStrictSyntaxMode(true)</literal>
on <literal>Configuration</literal>. In fact, we strongly recommend
this to programmers. Starting from some later release this setting
will be initially set to <literal>true</literal>. Also, you can
specify if you want to use strict syntax or old syntax in the template
files with the <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link>.</para>
<para>The advantages of <quote>strict syntax</quote> over the legacy
FTL syntax are:</para>
<itemizedlist>
<listitem>
<para>Since all
<literal>&lt;#<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#<replaceable>...</replaceable>&gt;</literal> are
reserved for FTL:</para>
<itemizedlist>
<listitem>
<para>We can introduce new directives without breaking
backward compatibility.</para>
</listitem>
<listitem>
<para>We can detect if you made a typo, i.e.
<literal>&lt;#inculde
<replaceable>...</replaceable>&gt;</literal> is treated as
parse-time error, rather than silently treated as simple
text.</para>
</listitem>
<listitem>
<para>It is easier for third-party tools to handle templates
(e.g. do syntax highlighting), especially since they don't
have to know about the new directives introduced with new
releases.</para>
</listitem>
<listitem>
<para>Templates are more readable, since it is easier to spot
<literal>&lt;#...&gt;</literal> tags embedded into HTML or
other markup.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><literal>&lt;#</literal> and <literal>&lt;/#</literal> is
illegal XML (except in CDATA sections), and illegal in almost all
other SGML applications, so they can't interfere with the tags
used in the static text parts (e.g. if you have
<literal>include</literal> element in the generated XML).</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="ref_depr_numerical_interpolation">
<title>#{...}: Numerical interpolation</title>
<indexterm>
<primary>#{...}</primary>
</indexterm>
<para>Deprecated: Use the <link
linkend="ref.setting.number_format"><literal>number_format</literal>
setting</link> and <link linkend="ref_builtin_string_for_number">the
<literal>string</literal> built-in</link> instead. For formatting for
computer audience (i.e., no localized formatting) use the <link
linkend="ref_builtin_c"><literal>c</literal> built-in</link> (like
<literal><replaceable>number</replaceable>?c</literal>).</para>
<para>While by default
<literal>#{<replaceable>...</replaceable>}</literal> is interpreted,
that can be disabled by setting the
<literal>interpolation_syntax</literal> configuration setting
(<literal>Configuration.setInterpolationSyntax</literal> in the Java
API) to <literal>dollar</literal>. Then
<literal>#{<replaceable>...</replaceable>}</literal> will be just
static text, and only
<literal>${<replaceable>...</replaceable>}</literal> will operate as
interpolation.</para>
<section>
<title>Synopsis</title>
<programlisting role="metaTemplate"><literal>#{<replaceable>expression</replaceable>}</literal>
or
<literal>#{<replaceable>expression</replaceable>; <replaceable>format</replaceable>}</literal></programlisting>
<para>Where:</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal><replaceable>expression</replaceable></literal>:
expression that can be evaluated as a number.</para>
</listitem>
<listitem>
<para><literal><replaceable>format</replaceable></literal>:
optional format specifier.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Description</title>
<para>The numerical interpolation is used to output a number value.
If the expression doesn't evaluate to a number, the evaluation ends
with an error.</para>
<para>The optional format specifier specifies the minimum and the
maximum number of displayed fractional digits using syntax
<literal>m<replaceable>min</replaceable>M<replaceable>max</replaceable></literal>.
For example, <literal>m2M5</literal> means "at least two, at most
five fractional digits". The minimum or the maximum specifier part
can be omitted. If only the minimum is specified, the maximum is
equal to the minimum. If only maximum is specified, the minimum is
0.</para>
<para>The decimal separator character of the output is
internationalized (according the current locale setting), which
means that it is not necessarily a dot.</para>
<para>Unlike <literal>${...}</literal>, <literal>#{...}</literal>
ignores the <link
linkend="ref.setting.number_format"><literal>number_format</literal>
setting</link>. This is actually a backward compatibility quirk, but
it can be useful when you print numbers in situations like
<literal>&lt;a href="queryDatabase?id=#{id}"&gt;</literal>, where
you surely don't want grouping separators or something fancy like
that. However, starting from FreeMarker 2.3.3 rather use the <link
linkend="ref_builtin_c"><literal>?c</literal> built-in</link> for
this purpose, like <literal>&lt;a
href="queryDatabase?id=${id?c}"&gt;</literal>.</para>
<para>Examples. Assume that <literal>x</literal> is
<literal>2.582</literal> and <literal>y</literal> is
<literal>4</literal>:</para>
<programlisting role="template"> &lt;#-- If the language is US English the output is: --&gt;
#{x} &lt;#-- 2.582 --&gt;
#{y} &lt;#-- 4 --&gt;
#{x; M2} &lt;#-- 2.58 --&gt;
#{y; M2} &lt;#-- 4 --&gt;
#{x; m1} &lt;#-- 2.6 --&gt;
#{y; m1} &lt;#-- 4.0 --&gt;
#{x; m1M2} &lt;#-- 2.58 --&gt;
#{y; m1M2} &lt;#-- 4.0 --&gt;</programlisting>
</section>
</section>
</chapter>
</part>
<part xml:id="xgui">
<title>XML Processing Guide</title>
<preface xml:id="xgui_preface">
<title>Preface</title>
<para>Although FreeMarker was originally designed as a web page template
engine, as of version 2.3 it also targets another application domain:
transforming XML into arbitrary textual output (e.g. HTML files). Thus,
in many cases, FreeMarker is an XSLT alternative.</para>
<para>Technically, there is nothing special in transforming XML
documents. It's just like when you do anything else with FreeMarker: you
drop the XML document into the data-model (and possibly other
variables), and then you merge the data-model with the FTL template(s)
that generate the output text. The extra features introduced for better
XML processing are the node FTL variable type (symbolizes a node in
generic tree structures, usable not only for XML) and the built-ins and
directives dealing with them, and the XML wrapper you get out-of-the-box
that exposes XML documents as FTL variables for the templates.</para>
<para>What's the difference between using FreeMarker or XSLT? The FTL
language has the usual imperative/procedural logic. On the other hand,
XSLT is a language with declarative style, designed by "too clever"
people, so it's not easy to adopt its logic, nor to use it in many
cases. Also its syntax is terribly verbose. However, XSLT's
"apply-templates" method can be very handy when you process XML
documents, thus FreeMarker supports something similar called the
<quote>visitor pattern</quote>. So in many applications, it is much
easier to write FTL stylesheets than XSLT style-sheets. Another
fundamental difference is that FTL "transforms" the node tree to text,
while XSLT transforms the tree to another tree. So you cannot always use
FreeMarker where you can use XSLT.</para>
</preface>
<chapter xml:id="xgui_expose">
<title>Exposing XML documents</title>
<indexterm>
<primary>XML</primary>
<secondary>exposing</secondary>
</indexterm>
<section xml:id="xgui_expose_dom">
<title>The DOM tree</title>
<para>We will use this XML document for the examples:</para>
<anchor xml:id="misc.example.bookXml"/>
<programlisting role="unspecified">&lt;book&gt;
&lt;title&gt;Test Book&lt;/title&gt;
&lt;chapter&gt;
&lt;title&gt;Ch1&lt;/title&gt;
&lt;para&gt;p1.1&lt;/para&gt;
&lt;para&gt;p1.2&lt;/para&gt;
&lt;para&gt;p1.3&lt;/para&gt;
&lt;/chapter&gt;
&lt;chapter&gt;
&lt;title&gt;Ch2&lt;/title&gt;
&lt;para&gt;p2.1&lt;/para&gt;
&lt;para&gt;p2.2&lt;/para&gt;
&lt;/chapter&gt;
&lt;/book&gt;</programlisting>
<para>W3C DOM models an XML document as a tree of nodes. The node tree
of the above XML can be visualized as:</para>
<programlisting role="unspecified">document
|
+- element book
|
+- text "\n "
|
+- element title
| |
| +- text "Test Book"
|
+- text "\n "
|
+- element chapter
| |
| +- text "\n "
| |
| +- element title
| | |
| | +- text "Ch1"
| |
| +- text "\n "
| |
| +- element para
| | |
| | +- text "p1.1"
| |
| +- text "\n "
| |
| +- element para
| | |
| | +- text "p1.2"
| |
| +- text "\n "
| |
| +- element para
| |
| +- text "p1.3"
|
+- element
|
+- text "\n "
|
+- element title
| |
| +- text "Ch2"
|
+- text "\n "
|
+- element para
| |
| +- text "p2.1"
|
+- text "\n "
|
+- element para
|
+- text "p2.2"</programlisting>
<para>Note that the disturbing <literal>"\n  "</literal>-s are the
line-breaks (indicated here with <literal>\n</literal>, an escape
sequence used in FTL string literals) and the indentation spaces
between the tags.</para>
<para>Notes on the DOM related terminology:</para>
<itemizedlist>
<listitem>
<para>The topmost node of a tree is called the <emphasis
role="term">root</emphasis>. In the case of XML documents, it is
always the <quote>document</quote> node, and not the top-most
element (<literal>book</literal> in this example).</para>
</listitem>
<listitem>
<para>We say that node B is the <emphasis
role="term">child</emphasis> of node A, if B is the
<emphasis>immediate</emphasis> descendant of A. For example, the
two <literal>chapter</literal> element nodes are the children of
the <literal>book</literal> element node, but the
<literal>para</literal> element nodes are not.</para>
</listitem>
<listitem>
<para>We say that node A is the <emphasis
role="term">parent</emphasis> of node B, if A is the
<emphasis>immediate</emphasis> ascendant of node B, that is, if B
is the children of A. For example, the <literal>book</literal>
element node is the parent of the two <literal>chapter</literal>
element nodes, but it is not the parent of the
<literal>para</literal> element nodes.</para>
</listitem>
<listitem>
<para>There are several kind of components that can occur in XML
documents, such as elements, text, comments, processing
instructions, etc. All such components are nodes in the DOM tree,
so there are element nodes, text nodes, comment nodes, etc. In
principle, the attributes of elements are also nodes in the tree
-- they are the children of the element --, but still, usually we
(and other XML related technologies) exclude them of element
children. So basically they don't count as children nodes.</para>
</listitem>
</itemizedlist>
<para>The programmer drops the document node of the DOM tree into the
FreeMarker data-model, and then the template author can walk the DOM
tree using that variable as the starting-point.</para>
<para>The DOM nodes in FTL correspond to <emphasis role="term">node
variables</emphasis>. This is a variable type, similarly to type
string, number, hash, etc. Node variable type makes it possible for
FreeMarker to get the parent node and the child nodes of a node. This
is technically required to allow the template author to navigate
between the nodes, say, to use the <link
linkend="ref_builtins_node">node built-ins</link> or the <link
linkend="ref.directive.visit"><literal>visit</literal></link> and
<link
linkend="ref.directive.recurse"><literal>recurse</literal></link>
directives; we will show the usage of these in the further
chapters.</para>
</section>
<section xml:id="xgui_expose_put">
<title>Putting the XML into the data-model</title>
<note>
<para>This section is for programmers.</para>
</note>
<para>It's easy to create a simple program to try the examples. Just
replace the <quote>Create a data-model</quote> part of <link
linkend="pgui_quickstart_all">the example of Programmer's Guide
Quickstart</link> with this:</para>
<programlisting role="unspecified">/* Create a data-model */
Map root = new HashMap();
root.put(
"doc",
freemarker.ext.dom.NodeModel.parse(new File("<replaceable>the/path/of/the.xml</replaceable>")));</programlisting>
<para>and then you have a program that outputs the result of the XML
transformation to the standard output (usually the terminal
screen).</para>
<para>Notes:</para>
<itemizedlist>
<listitem>
<para>The <literal>parse</literal> method removes comment and
processing instruction nodes by default. See the API for more
details.</para>
</listitem>
<listitem>
<para><literal>NodeModel</literal> also allows you to wrap
<literal>org.w3c.dom.Node</literal>-s directly. You may want to
clean up the DOM tree first with the static utility methods, such
as <literal>NodeModel.simplify</literal> or your own custom
cleanup routines.</para>
</listitem>
</itemizedlist>
<para>Note that there are tools available that you can use to generate
files from XML documents, so you don't have to write your own for this
common task. <link linkend="pgui_misc_ant">See here...</link></para>
</section>
</chapter>
<chapter xml:id="xgui_imperative">
<title>Imperative XML processing</title>
<indexterm>
<primary>XML</primary>
<secondary>imperative processing</secondary>
</indexterm>
<section xml:id="xgui_imperative_learn">
<title>Basics</title>
<note>
<para>This section uses the DOM tree and the variable made in the
<link linkend="xgui_expose">previous chapter</link>.</para>
</note>
<para>Assume that the programmer has put the XML document into the
data-model as variable <literal>doc</literal>. This variable
corresponds to the root of the <link linkend="xgui_expose_dom">DOM
tree</link>, the <quote>document</quote>. The actual variable
structure behind <literal>doc</literal> is wily enough, and only
roughly resembles the DOM tree. So instead of getting lost in the
details, let's see how to use it by example.</para>
<section>
<title>Accessing elements by name</title>
<para>This FTL prints the title of the book:</para>
<programlisting role="template">&lt;h1&gt;${doc.book.title}&lt;/h1&gt;</programlisting>
<para>The output will be:</para>
<programlisting role="output">&lt;h1&gt;Test Book&lt;/h1&gt;</programlisting>
<para>As you see, both <literal>doc</literal> and
<literal>book</literal> can be used as hashes; you get their child
nodes as sub variables. Basically, you describe the path by which
you reach the target (element <literal>title</literal>) in the DOM
tree. You may notice that there was some swindle above: with
<literal>${doc.book.title}</literal>, it seems that we instruct
FreeMarker to print the <literal>title</literal> element itself, but
we should print its child text node (check the <link
linkend="xgui_expose_dom">DOM tree</link>). It still works, because
elements are not only hash variables, but string variables as well.
The scalar value of an element node is the string resulting from the
concatenation of all its text child nodes. However, trying to use an
element as scalar will cause error if the element has child
elements. For example <literal>${doc.book}</literal> would stop with
error.</para>
<para>This FTL prints the titles of the two chapters:</para>
<programlisting role="template">&lt;h2&gt;${doc.book.chapter[0].title}&lt;/h2&gt;
&lt;h2&gt;${doc.book.chapter[1].title}&lt;/h2&gt;</programlisting>
<para>Here, as <literal>book</literal> has 2
<literal>chapter</literal> element children,
<literal>doc.book.chapter</literal> is a sequence that stores the
two element nodes. Thus, we can generalize the above FTL, so it
works with any number of chapters:</para>
<programlisting role="template">&lt;#list doc.book.chapter as ch&gt;
&lt;h2&gt;${ch.title}&lt;/h2&gt;
&lt;/#list&gt;</programlisting>
<para>But what's if there is only one chapter? Actually, when you
access an element as hash subvariable, it is
<emphasis>always</emphasis> a sequence as well (not only hash and
string), but if the sequence contains exactly 1 item, then the
variable also acts as that item itself. So, returning to the first
example, this would print the book title as well:</para>
<programlisting role="template">&lt;h1&gt;${doc.book[0].title[0]}&lt;/h1&gt;</programlisting>
<para>But you know that there is exactly 1 <literal>book</literal>
element, and that a book has exactly 1 title, so you can omit the
<literal>[0]</literal>-s.
<literal>${doc.book.chapter.title}</literal> would work too, if the
book happen to have only 1 <literal>chapter</literal>-s (otherwise
it is ambiguous: how is it to know if the <literal>title</literal>
of which <literal>chapter</literal> you want? So it stops with an
error.). But since a book can have multiple chapters, you don't use
this form. If the element <literal>book</literal> has no
<literal>chapter</literal> child, then
<literal>doc.book.chapter</literal> will be a 0 length sequence, so
the FTL with <literal>&lt;#list ...&gt;</literal> will still
work.</para>
<para>It is important to realize the consequence that, for example,
if <literal>book</literal> has no <literal>chapter</literal>-s then
<literal>book.chapter</literal> is an empty sequence, so
<literal>doc.book.chapter??</literal> will <emphasis>not</emphasis>
be <literal>false</literal>, it will be always
<literal>true</literal>! Similarly,
<literal>doc.book.somethingTotallyNonsense??</literal> will not be
<literal>false</literal> either. To check if there was no children
found, use <literal>doc.book.chapter[0]??</literal> (or
<literal>doc.book.chapter?size == 0</literal>). Of course you can
use similarly all the <link
linkend="dgui_template_exp_missing">missing value handler
operators</link> (e.g.
<literal>doc.book.author[0]!"Anonymous"</literal>), just don't
forget that <literal>[0]</literal>.</para>
<note>
<para>The rule with sequences of size 1 is a convenience feature
of the XML wrapper (implemented via multi-type FTL variables). It
will not work with other sequences in general.</para>
</note>
<para>Now we finish the example by printing all the
<literal>para</literal>-s of each chapter:</para>
<programlisting role="template">&lt;h1&gt;${doc.book.title}&lt;/h1&gt;
&lt;#list doc.book.chapter as ch&gt;
&lt;h2&gt;${ch.title}&lt;/h2&gt;
&lt;#list ch.para as p&gt;
&lt;p&gt;${p}
&lt;/#list&gt;
&lt;/#list&gt;</programlisting>
<para>this will print:</para>
<programlisting role="output">&lt;h1&gt;Test&lt;/h1&gt;
&lt;h2&gt;Ch1&lt;/h2&gt;
&lt;p&gt;p1.1
&lt;p&gt;p1.2
&lt;p&gt;p1.3
&lt;h2&gt;Ch2&lt;/h2&gt;
&lt;p&gt;p2.1
&lt;p&gt;p2.2</programlisting>
<para>The above FTL could be written more nicely as:</para>
<programlisting role="template">&lt;#assign book = doc.book&gt;
&lt;h1&gt;${book.title}&lt;/h1&gt;
&lt;#list book.chapter as ch&gt;
&lt;h2&gt;${ch.title}&lt;/h2&gt;
&lt;#list ch.para as p&gt;
&lt;p&gt;${p}
&lt;/#list&gt;
&lt;/#list&gt;</programlisting>
<para>Finally, a generalized usage of the child selector mechanism:
this template lists all <literal>para</literal>-s of the example XML
document:</para>
<programlisting role="template">&lt;#list doc.book.chapter.para as p&gt;
&lt;p&gt;${p}
&lt;/#list&gt;</programlisting>
<para>The output will be:</para>
<programlisting role="output"> &lt;p&gt;p1.1
&lt;p&gt;p1.2
&lt;p&gt;p1.3
&lt;p&gt;p2.1
&lt;p&gt;p2.2
</programlisting>
<para>This example shows that hash sub variables select the children
of a sequence of notes (just in the earlier examples that sequence
happened to be of size 1). In this concrete case, subvariable
<literal>chapter</literal> returns a sequence of size 2 (since there
are two <literal>chapter</literal>-s), and then subvariable
<literal>para</literal> selects the <literal>para</literal> child
nodes of all nodes in that sequence.</para>
<para>A negative consequence of this mechanism is that things like
<literal>doc.somethingNonsense.otherNonsesne.totalNonsense</literal>
will just evaluate to an empty sequence, and you don't get any error
messages.</para>
</section>
<section>
<title>Accessing attributes</title>
<para>This XML is the same as the original, except that it uses
attributes for the titles, instead of elements:</para>
<programlisting role="unspecified">&lt;!-- THIS XML IS USED FOR THE "Accessing attributes" CHAPTER ONLY! --&gt;
&lt;!-- Outside this chapter examples use the XML from earlier. --&gt;
&lt;book title="Test"&gt;
&lt;chapter title="Ch1"&gt;
&lt;para&gt;p1.1&lt;/para&gt;
&lt;para&gt;p1.2&lt;/para&gt;
&lt;para&gt;p1.3&lt;/para&gt;
&lt;/chapter&gt;
&lt;chapter title="Ch2"&gt;
&lt;para&gt;p2.1&lt;/para&gt;
&lt;para&gt;p2.2&lt;/para&gt;
&lt;/chapter&gt;
&lt;/book&gt;</programlisting>
<para>The attributes of an element can be accessed in the same way
as the child elements of the element, except that you put an at-sign
(@) before the name of the attribute:</para>
<programlisting role="template">&lt;#assign book = doc.book&gt;
&lt;h1&gt;${book.@title}&lt;/h1&gt;
&lt;#list book.chapter as ch&gt;
&lt;h2&gt;${ch.@title}&lt;/h2&gt;
&lt;#list ch.para as p&gt;
&lt;p&gt;${p}
&lt;/#list&gt;
&lt;/#list&gt;</programlisting>
<para>This will print exactly the same as the previous
example.</para>
<para>Getting attributes follows the same logic as getting child
elements, so the result of <literal>ch.@title</literal> above is a
sequence of size 1. If there were no <literal>title</literal>
attribute, then the result would be a sequence of size 0. So be
ware, using existence built-ins is tricky here too: if you are
curious if <literal>foo</literal> has attribute
<literal>bar</literal> then you have to write
<literal>foo.@bar[0]??</literal>. (<literal>foo.@bar??</literal> is
wrong, because it always returns <literal>true</literal>.)
Similarly, if you want a default value for the
<literal>bar</literal> attribute, then you have to write
<literal>foo.@bar[0]!"theDefaultValue"</literal>.</para>
<para>As with child elements, you can select the attributes of
multiple nodes. For example, this template prints the titles of all
chapters:</para>
<programlisting role="template">&lt;#list doc.book.chapter.@title as t&gt;
${t}
&lt;/#list&gt;</programlisting>
</section>
<section>
<title>Exploring the tree</title>
<para>This FTL will enumerate all child nodes of the book
element:</para>
<programlisting role="template">&lt;#list doc.book?children as c&gt;
- ${c?node_type} &lt;#if c?node_type == 'element'&gt;${c?node_name}&lt;/#if&gt;
&lt;/#list&gt;</programlisting>
<para>this will print:</para>
<programlisting role="output">- text
- element title
- text
- element chapter
- text
- element chapter
- text</programlisting>
<para>The meaning of <literal>?node_type</literal> is probably clear
without explanation. There are several node types that can occur in
a DOM tree, such as <literal>"element"</literal>,
<literal>"text"</literal>, <literal>"comment"</literal>,
<literal>"pi"</literal>, ...etc.</para>
<para>The <literal>?node_name</literal> returns the name of element
for element nodes. For other node types, it also returns something,
but that's mainly useful for declarative XML processing, which will
be discussed in a <link linkend="xgui_declarative">later
chapter</link>.</para>
<para>If the book element had attributes, they would
<emphasis>not</emphasis> appear in the above list, for practical
reasons. But you can get a list that contains all attributes of the
element, with subvariable <literal>@@</literal> of the element
variable. If you modify the first line of the XML to this:</para>
<programlisting role="unspecified">&lt;book foo="Foo" bar="Bar" baaz="Baaz"&gt;</programlisting>
<para>and run this FTL:</para>
<programlisting role="template">&lt;#list doc.book.@@ as attr&gt;
- ${attr?node_name} = ${attr}
&lt;/#list&gt;</programlisting>
<para>then you get this output (or something similar):</para>
<programlisting role="output">- baaz = Baaz
- bar = Bar
- foo = Foo</programlisting>
<para>Returning to the listing of children, there is a convenience
subvariable to list only the element children of an element:</para>
<programlisting role="template">&lt;#list doc.book.* as c&gt;
- ${c?node_name}
&lt;/#list&gt;</programlisting>
<para>This will print:</para>
<programlisting role="output">- title
- chapter
- chapter</programlisting>
<para>You get the parent of an element with the
<literal>parent</literal> built-in:</para>
<programlisting role="template">&lt;#assign e = doc.book.chapter[0].para[0]&gt;
&lt;#-- Now e is the first para of the first chapter --&gt;
${e?node_name}
${e?parent?node_name}
${e?parent?parent?node_name}
${e?parent?parent?parent?node_name}</programlisting>
<para>This will print:</para>
<programlisting role="output">para
chapter
book
@document</programlisting>
<para>In the last line you have reached the root of the DOM tree,
the document node. It's not an element, and this is why it has that
strange name; don't deal with it now. Obviously, the document node
has no parent.</para>
<para>You can quickly go back to the document node using the
<literal>root</literal> built-in:</para>
<programlisting role="template">&lt;#assign e = doc.book.chapter[0].para[0]&gt;
${e?root?node_name}
${e?root.book.title}</programlisting>
<para>This will print:</para>
<programlisting role="output">@document
Test Book</programlisting>
<para>For the complete list of built-ins you can use to navigate in
the DOM tree, read the <link linkend="ref_builtins_node">reference
of node built-ins</link>.</para>
</section>
<section xml:id="xgui_imperative_learn_xpath">
<title>Using XPath expressions</title>
<note>
<para>XPath expressions work only if <link
xlink:href="http://xml.apache.org/xalan/">Apache Xalan</link> or
<link xlink:href="http://jaxen.org/">Jaxen</link> (at least 1.1)
classes are available. However, up to Java 1.8 you don't need any
additional dependencies, as Apache Xalan is included in Java with
changed package names, which FreeMarker will automatically use
(unless plain Apache Xalan is also present). This internal Xalan
isn't available anymore on OpenJDK 9, but is still available on
Oracle JDK/JRE 9 (at least on official stable release <quote>build
9+181</quote>).</para>
</note>
<note>
<para>Don't use the sample XML from the previous section, where
<literal>title</literal> is an attribute; that applies only to
that section.</para>
</note>
<para>If a hash key used with a node variable can't be interpreted
otherwise (see the <link linkend="xgui_imperative_formal">next
section</link> for the precise definition), then it will by
interpreted as an XPath expression. For more information on XPath,
please visit <link
xlink:href="http://www.w3.org/TR/xpath">http://www.w3.org/TR/xpath</link>.</para>
<para>For example, here we list the <literal>para</literal> elements
of the chapter with <literal>title</literal> element (not
attribute!) content "Ch1'':</para>
<programlisting role="template">&lt;#list doc["book/chapter[title='Ch1']/para"] as p&gt;
&lt;p&gt;${p}
&lt;/#list&gt;</programlisting>
<para>It will print:</para>
<programlisting role="output"> &lt;p&gt;p1.1
&lt;p&gt;p1.2
&lt;p&gt;p1.3</programlisting>
<para>The rule with sequences of length 1 (explained in earlier
sections) stands for XPath results as well. That is, if the
resulting sequence contains exactly 1 node, it also acts as the node
itself. For example, print the first paragraph of chapter
<quote>Ch1</quote>:</para>
<programlisting role="template">${doc["book/chapter[title='Ch1']/para[1]"]}</programlisting>
<para>which prints the same as:</para>
<programlisting role="template">${doc["book/chapter[title='Ch1']/para[1]"][0]}</programlisting>
<para>The context node of the XPath expression is the node (or
sequence of nodes) whose hash subvariable is used to issue the XPath
expression. Thus, this prints the same as the previous
example:</para>
<programlisting role="template">${doc.book["chapter[title='Ch1']/para[1]"]}</programlisting>
<para>Note that currently you can use a sequence of 0 or multiple
(more than 1) nodes as context only if the programmer has set up
FreeMarker to use Jaxen instead of Xalan.</para>
<para>Also note that XPath indexes sequence items from 1, while FTL
indexes sequence items from 0. Thus, to select the first chapter,
the XPath expression is <literal>"/book/chapter[1]"</literal>, while
the FTL expression is <literal>book.chapter[0]</literal>.</para>
<para>If the programmer has set up FreeMarker to use Jaxen instead
of Xalan, then FreeMarker variables are visible with XPath variable
references:</para>
<programlisting role="template">&lt;#assign <emphasis>currentTitle</emphasis> = "Ch1"&gt;
&lt;#list doc["book/chapter[title=<emphasis>$currentTitle</emphasis>]/para"] as p&gt;
<replaceable>...</replaceable></programlisting>
<para>Note that <literal>$currentTitle</literal> is not a FreeMarker
interpolation, as there are no <literal>{</literal> and
<literal>}</literal> there. That's an XPath expression.</para>
<para>The result of some XPath expressions is not a node-set, but a
string, a number, or a boolean. For those XPath expressions, the
result is an FTL string, number, or boolean variable respectively.
For example, the following will count the total number of
<literal>para</literal> elements in the XML document, so the result
is a number:</para>
<programlisting role="template">${x["count(//para)"]}</programlisting>
<para>The output will be:</para>
<programlisting role="output">5</programlisting>
</section>
<section>
<title>XML namespaces</title>
<indexterm>
<primary>XML namespace</primary>
<secondary>in imperative processing</secondary>
</indexterm>
<para>Be default, when you write something like
<literal>doc.book</literal>, then it will select the element with
name <literal>book</literal> that does not belongs to any XML
namespace (similarly to XPath). If you want to select an element
that is inside an XML namespace, you must register a prefix and use
that. For example, if element <literal>book</literal> is in XML
namespace <literal>http://example.com/ebook</literal>, then you have
to associate a prefix with it at the top of the template with the
<literal>ns_prefixes</literal> parameter of the <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link>:</para>
<programlisting role="template">&lt;#ftl ns_prefixes={"e":"http://example.com/ebook"}&gt;
</programlisting>
<para>And now you can write expressions as
<literal>doc["e:book"]</literal>. (The usage of square bracket
syntax was required because the colon would confuse FreeMarker
otherwise.)</para>
<para>As the value of <literal>ns_prefixes</literal> is a hash, you
can register multiple prefixes:</para>
<programlisting role="template">&lt;#ftl ns_prefixes={
"e":"http://example.com/ebook",
"f":"http://example.com/form",
"vg":"http://example.com/vectorGraphics"}
&gt;</programlisting>
<para>The <literal>ns_prefixes</literal> parameter affects the whole
<link linkend="dgui_misc_namespace">FTL namespace</link>. This means
in practice that the prefixes you have registered in the main page
template will be visible in all <literal>&lt;#include
...&gt;</literal>-d templates, but not in <literal>&lt;#imported
...&gt;</literal>-d templates (often referred as FTL libraries). Or
from another point of view, an FTL library can register XML
namespace prefixes for it's own use, without interfering with the
prefix registrations of the main template and other
libraries.</para>
<para>Note that, if an input document is dominated by a given XML
namespace, you can set that as the default namespace for
convenience. This means that if you don't use prefix, as in
<literal>doc.book</literal>, then it selects element that belongs to
the default namespace. The setting of the default namespace happens
with reserved prefix <literal>D</literal>, for example:</para>
<programlisting role="template">&lt;#ftl ns_prefixes={"D":"http://example.com/ebook"}&gt;
</programlisting>
<para>Now expression <literal>doc.book</literal> select the
<literal>book</literal> element that belongs to XML namespace
<literal>http://example.com/ebook</literal>. Unfortunately, XPath
does not support this idea of a default namespace. Thus, in XPath
expressions, element names without prefixes always select the
elements that does not belong to any XML namespace. However, to
access elements in the default namespace you can directly use prefix
<literal>D</literal>, for example:
<literal>doc["D:book/D:chapter[title='Ch1']"]</literal>.</para>
<para>Note that when you use a default namespace, then you can
select elements that does not belong to any node namespace with
reserved prefix <literal>N</literal>, for example
<literal>doc.book["N:foo"]</literal>. It doesn't go for XPath
expressions, where the above can be witten as
<literal>doc["D:book/foo"]</literal>.</para>
</section>
<section>
<title>Don't forget escaping!</title>
<para>As we generate output of HTML format in these examples, and
HTML format reserves characters as <literal>&lt;</literal>,
<literal>&amp;</literal>, etc., we have to ensure that those will be
escaped. For that, either FreeMarker has to be <link
linkend="pgui_config_outputformatsautoesc">properly
configured</link>, or add <literal>output_format="HTML"</literal> in
the template to the <literal>ftl</literal> directive calls.</para>
<para>So if the book title is "Romeo &amp; Juliet", the resulting
HTML output will be correctly:</para>
<programlisting role="output"><replaceable>...</replaceable>
&lt;h1&gt;Romeo &amp;amp; Juliet&lt;/h1&gt;
<replaceable>...</replaceable></programlisting>
</section>
</section>
<section xml:id="xgui_imperative_formal">
<title>Details</title>
<para>Every variable that corresponds to a single node in the DOM tree
is a multi-type variable of type node and type hash (for programmers:
implements both <literal>TemplateNodeModel</literal> and
<literal>TemplateHashModel</literal>). Thus, you can use the <link
linkend="ref_builtins_node">node built-ins</link> with them. Hash keys
are interpreted as XPath expressions, except the special keys shown in
the table below. Some of the node variables also have string type, so
you can use them as string variables (for programmers: they implement
<literal>TemplateScalarModel</literal>).</para>
<anchor xml:id="misc.xguiTable"/>
<informaltable border="1">
<thead>
<tr>
<th>Node type (<literal>?node_type</literal>)</th>
<th>Node name (<literal>?node_name</literal>)</th>
<th>String value (e.g. <literal>&lt;p&gt;${node}</literal>)</th>
<th>Special hash keys</th>
</tr>
</thead>
<tbody>
<tr>
<td><literal>"document"</literal></td>
<td><literal>"@document"</literal></td>
<td>No string value. (Error when you try to use it as
string.)</td>
<td><literal><replaceable>elementName</replaceable></literal>,
<literal>"<replaceable>prefix</replaceable>:<replaceable>elementName</replaceable>"</literal>,
<literal>*</literal>, <literal>**</literal>,
<literal>@@markup</literal>, <literal>@@nested_markup</literal>,
<literal>@@text</literal>, <literal>@@local_name</literal>,
<literal>@@qname</literal>, <literal>@@namespace</literal></td>
</tr>
<tr>
<td><literal>"element"</literal></td>
<td><literal>"<replaceable>name</replaceable>"</literal>: the
name of the element. This is the local name (i.e. name without
namespace prefix).</td>
<td>If it has no element children, the text of all text node
children concatenated together. Error otherwise, when you try to
use it as string.</td>
<td><literal><replaceable>elementName</replaceable></literal>,
<literal>"<replaceable>prefix</replaceable>:<replaceable>elementName</replaceable>"</literal>,
<literal>*</literal>, <literal>**</literal>,
<literal>@<replaceable>attrName</replaceable></literal>,
<literal>"@<replaceable>prefix</replaceable>:<replaceable>attrName</replaceable>"</literal>,
<literal>@@</literal>, <literal>"@*"</literal>,
<literal>@@start_tag</literal>, <literal>@@end_tag</literal>,
<literal>@@attributes_markup</literal>,
<literal>@@next_sibling_element</literal>,
<literal>@@previous_sibling_element</literal>,
<literal>@@markup</literal>, <literal>@@nested_markup</literal>,
<literal>@@text</literal>, <literal>@@local_name</literal>,
<literal>@@qname</literal>, <literal>@@namespace</literal></td>
</tr>
<tr>
<td><literal>"text"</literal></td>
<td><literal>"@text"</literal></td>
<td>The text itself.</td>
<td><literal>@@markup</literal>,
<literal>@@nested_markup</literal>, <literal>@@text</literal>,
<literal>@@local_name</literal>, <literal>@@qname</literal>,
<literal>@@namespace</literal></td>
</tr>
<tr>
<td><literal>"pi"</literal></td>
<td><literal>"@pi$<replaceable>target</replaceable>"</literal></td>
<td>The part between the target name and the
<literal>?&gt;</literal>.</td>
<td><literal>@@markup</literal>,
<literal>@@nested_markup</literal>, <literal>@@text</literal>,
<literal>@@local_name</literal>, <literal>@@qname</literal>,
<literal>@@namespace</literal></td>
</tr>
<tr>
<td><literal>"comment"</literal></td>
<td><literal>"@comment"</literal></td>
<td>The text of the comment, without the delimiters
<literal>&lt;!--</literal> and <literal>--&gt;</literal>.</td>
<td><literal>@@markup</literal>,
<literal>@@nested_markup</literal>, <literal>@@text</literal>,
<literal>@@local_name</literal>, <literal>@@qname</literal>,
<literal>@@namespace</literal></td>
</tr>
<tr>
<td><literal>"attribute"</literal></td>
<td><literal>"<replaceable>name</replaceable>"</literal>: the
name of the attribute. This is the local name (i.e. name without
namespace prefix).</td>
<td>The value of the attribute.</td>
<td><literal>@@markup</literal>,
<literal>@@nested_markup</literal>, <literal>@@text</literal>,
<literal>@@qname</literal>, <literal>@@local_name</literal>,
<literal>@@qname</literal>, <literal>@@namespace</literal></td>
</tr>
<tr>
<td><literal>"document_type"</literal></td>
<td><literal>"@document_type$<replaceable>name</replaceable>"</literal>:
<literal><replaceable>name</replaceable></literal> is the name
of the document element.</td>
<td>No string value. (Error when you try to use it as
string.)</td>
<td><literal>@@markup</literal>,
<literal>@@nested_markup</literal>, <literal>@@text</literal>,
<literal>@@local_name</literal>, <literal>@@qname</literal>,
<literal>@@namespace</literal></td>
</tr>
</tbody>
</informaltable>
<para>Notes:</para>
<itemizedlist>
<listitem>
<para>There is no CDATA type. CDATA nodes are transparently
considered as text nodes.</para>
</listitem>
<listitem>
<para>These variables do <emphasis>not</emphasis> support
<literal>?keys</literal> and <literal>?values</literal>.</para>
</listitem>
<listitem>
<para>Element and attribute node names are local names, that is,
they do not contain the namespace prefix. The URI of the namespace
the node belongs to can be queried with the
<literal>?node_namespace</literal> built-in.</para>
</listitem>
<listitem>
<para>XPath expression needs Jaxen (recommended, but please use
1.1-beta-8 or later; <link xlink:href="http://jaxen.org/">download
it here</link>) or Apache Xalan classes available, or an error
will stop template execution. Note, however, that as some special
hash keys hide the XPath expressions of the same meaning, those
XPath expressions will work even if there is no XPath
implementation available. <phrase role="forProgrammers">If both
Xalan and Jaxen is available, FreeMarker will use Xalan, unless
you choose Jaxen by calling
<literal>freemarker.ext.dom.NodeModel.useJaxenXPathSupport()</literal>
from Java.</phrase></para>
</listitem>
<listitem>
<para>If Jaxen is used for the XPath support (not Xalan), then
FreeMarker variables are visible with XPath variable references
(e.g.
<literal>doc["book/chapter[title=$currentTitle]"]</literal>).</para>
</listitem>
</itemizedlist>
<para>Meaning of special hash keys:</para>
<itemizedlist>
<listitem>
<para><literal><replaceable>elementName</replaceable></literal>,
<literal>"<replaceable>prefix</replaceable>:<replaceable>elementName</replaceable>"</literal>:
Returns the sequence of child nodes that are elements of name
<literal><replaceable>elementName</replaceable></literal>. (Note
that the term <quote>child</quote> means
<emphasis>immediate</emphasis> descendant.) The selection is XML
name-space aware, unless the XML document was persed with an XML
parser that was not in namespace aware mode. In XML name-space
aware mode, names without prefix
(<replaceable>elementName</replaceable>) selects only elements
that doesn't belong to any XML name-space (unless you have
registered a default XML namespace), and names with prefix
(<replaceable>prefix</replaceable>:<replaceable>elementName</replaceable>)
selects only elements that are belonging to the XML namespace
denoted by the prefix. The registration of prefixes and the
setting of the default XML namespace is done with the
<literal>ns_prefixes</literal> parameter of the <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link>.</para>
</listitem>
<listitem>
<para><literal>*</literal>: Returns the sequence of all child
(direct descendant) <emphasis>element</emphasis> nodes. The
sequence will contain the elements in the <quote>document
order</quote>, that is, in the order in which the first character
of the XML representation of each node occurs (after expansion of
general entities).</para>
</listitem>
<listitem>
<para><literal>**</literal>: Returns the sequence of all
descendant <emphasis>element</emphasis> nodes. The sequence will
contain the elements in the document order.</para>
</listitem>
<listitem>
<para><literal>@<replaceable>attName</replaceable></literal>,
<literal>"@<replaceable>prefix</replaceable>:<replaceable>attrName</replaceable>"</literal>:
Returns the attribute
<literal><replaceable>attName</replaceable></literal> of the
element as a sequence of size 1 that contains the attribute node,
or as an empty sequence if the attribute does not exist (so to
check if an attribute exists use
<literal>foo.@<replaceable>attName</replaceable>[0]??</literal>,
<emphasis>not</emphasis>
<literal>foo.@<replaceable>attName</replaceable>??</literal>). As
with special key
<literal>"<replaceable>elementName</replaceable>"</literal>, if
the length of the sequence is 1, then it also acts as its first
subvariable. If no
<literal><replaceable>prefix</replaceable></literal> is used, then
it returns only attribute that does not use XML namespace (even if
you have set a default XML namespace). If a
<literal><replaceable>prefix</replaceable></literal> is used, it
returns only the attribute that belongs to the XML namespace
associated with the
<literal><replaceable>prefix</replaceable></literal>. The
registration of prefixes is done with the
<literal>ns_prefixes</literal> parameter of the <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link>.</para>
</listitem>
<listitem>
<para><literal>@@</literal> or <literal>"@*"</literal>: Returns
the sequence of attribute nodes belonging to the parent element.
This is the same as XPath <literal>@*</literal>.</para>
</listitem>
<listitem>
<para><literal>@@qname</literal>: Returns the full-qualified name
of the element (such as <literal>e:book</literal>, in contrast to
the local name returned by <literal>?node_name</literal> that is
<literal>book</literal>) . The prefix used (as
<literal>e</literal>) is chosen based on the prefix registered in
the current namespace with the <literal>ns_prefixes</literal>
parameter of the <literal>ftl</literal> directive, and not
influenced by the prefix used in the source XML document. If you
have set a default XML namespace, then for nodes that use that,
prefix <literal>D</literal> will be used. For nodes that does not
belong to an XML namespace, no prefix is used (even if you have
set a default namespace). If there is no prefix registered for the
namespace of the node, the result is a non-existent variable
(<literal>node.@@qname??</literal> is
<literal>false</literal>).</para>
</listitem>
<listitem>
<para><literal>@@local_mame</literal>: The name of the node
without the namespace prefix.</para>
</listitem>
<listitem>
<para><literal>@@namespace</literal>: The namespace URL (not the
namespace prefix) of the node.</para>
</listitem>
<listitem>
<para><literal>@@markup</literal>: This returns the full XML
markup of a node, as a string. (Full XML markup means that it also
contains the markup of the child nodes, and the markup of the
children of the child nodes, and so on.) The markup you get is not
necessary the same as the markup in the source XML file, it's just
semantically identical. Especially, note that CDATA sections will
become to plain text. Also note that depending on how did you
wrapped the original XML document with FreeMarker, comment or
processing instruction nodes may were removed, and then they will
be missing from the output of course. The first outputted start
tag will contain
<literal>xmlns:<replaceable>prefix</replaceable></literal>
attributes for each XML name-spaces used in the outputted XML
fragment, and those prefixes will be used in the outputted element
and attribute names. These prefixes will be the same as the
prefixes registered with the <literal>ns_prefixes</literal>
parameter of the <literal>ftl</literal> directive (no prefix will
be used for <literal>D</literal>, as it will be registered as the
default name-space with an <literal>xmlns</literal> attribute), or
if no prefix was assigned for a XML name-space with that, then an
arbitrary chosen unused prefix is used.</para>
</listitem>
<listitem>
<para><literal>@@nested_markup</literal>: This is similar to
<literal>@@markup</literal>, but it returns the XML markup of an
element without its opening and closing tags. For the document
node, it returns the same as <literal>@@markup</literal>. For
other node types (text, processing instruction, etc.), it returns
an empty string. Unlike with <literal>@@markup</literal>, no
<literal>xmlns:<replaceable>prefix</replaceable></literal>
attributes will be placed into the output, but regarding the
prefixes used in element and attribute names the rules are the
same.</para>
</listitem>
<listitem>
<para><literal>@@text</literal>: This returns the value of all
text nodes that occur within the node (all descendant text nodes,
not just direct children), concatenated together into a single
string. If the node has no text node children, then the result is
an empty string.</para>
</listitem>
<listitem>
<para><literal>@@start_tag</literal>: Returns the markup of the
<link linkend="gloss.startTag">start-tag</link> of the element
node. As with <literal>@@markup</literal>, the output is not
necessary the same as in the original XML document, but it is
semantically equivalent with that. Regarding the XML name-spaces
(<literal>xmlns:<replaceable>prefix</replaceable></literal>
attributes in the output, etc.) the rules are the same as with
<literal>"@@markup"</literal></para>
</listitem>
<listitem>
<para><literal>@@end_tag</literal>: Returns the markup of the
<link linkend="gloss.endTag">end-tag</link> of the element node.
As with <literal>@@markup</literal>, the output is not necessary
the same as in the original XML document, but it is semantically
equivalent with that.</para>
</listitem>
<listitem>
<para><literal>@@attributes_markup</literal>: Returns the markup
of the <link linkend="gloss.attribute">attributes</link> of the
element node. As with <literal>@@markup</literal>, the output is
not necessary the same as in the original XML document, but it is
semantically equivalent with that.</para>
</listitem>
<listitem>
<para><literal>@@next_sibling_element</literal> (since 2.3.26):
The following sibling element of an element node or an empty node
sequence if there's no such element. An element counts as a
sibling of another element if they are on the same hierarchical
level, and there's no other element or non-whitespace character
data (text or CDATA) between the two elements. For example in
<literal>&lt;a/&gt;&lt;!-- comment
--&gt;&amp;#x20;&lt;b/&gt;</literal> the two elements are
siblings, but not in <literal>&lt;a/&gt;text&lt;b/&gt;</literal>
or <literal>&lt;a/&gt;&lt;x/&gt;&lt;b/&gt;</literal>.</para>
</listitem>
<listitem>
<para><literal>@@previous_sibling_element</literal> (since
2.3.26): The previous sibling element of an element node or an
empty node sequence if there's no such element. See the last point
for the meaning of sibling.</para>
</listitem>
</itemizedlist>
<section>
<title>Node sequences</title>
<para>Many of the special hash keys (indicated in the above list),
and XPath expressions that result in node-sets (see the <link
xlink:href="http://www.w3.org/TR/xpath">XPath recommendation</link>)
return a sequence of nodes.</para>
<para>These node sequences, if they store exactly 1 subvariable,
will also act as the subvariable itself. For example,
<literal>${book.title[0]}</literal> will do the same as
<literal>${book.title}</literal>, if there is only one
<literal>title</literal> element child of element
<literal>book</literal>.</para>
<para>Returning an empty node sequence is a normal situation. For
example, if in a concrete XML document, element
<literal>book</literal> has no child element
<literal>chapter</literal>, then <literal>book.chapter</literal>
results in an empty node sequence. Beware! This also means, that
<literal>book.chaptre</literal> (note the typo) will also return
empty node sequence, and will not stop with error. Also,
<literal>book.chaptre??</literal> (note the typo) will return
<literal>true</literal> because the empty sequence exists, so you
have to use <literal>book.chaptre[0]??</literal> for the
check.</para>
<para>Node sequences that store not 1 nodes (but 0 or more than 1
nodes) also support some of the hash keys described above. Namely,
the following special keys are supported:</para>
<itemizedlist>
<listitem>
<para><literal><replaceable>elementName</replaceable></literal>,
<literal>"<replaceable>prefix</replaceable>:<replaceable>elementName</replaceable>"</literal></para>
</listitem>
<listitem>
<para><literal>@<replaceable>attrName</replaceable></literal>,
<literal>"@<replaceable>prefix</replaceable>:<replaceable>attrName</replaceable>"</literal></para>
</listitem>
<listitem>
<para><literal>@@markup</literal>,
<literal>@@nested_markup</literal></para>
</listitem>
<listitem>
<para><literal>@@text</literal></para>
</listitem>
<listitem>
<para><literal>*</literal>, <literal>**</literal></para>
</listitem>
<listitem>
<para><literal>@@</literal>, <literal>"@*"</literal></para>
</listitem>
</itemizedlist>
<para>When you apply one of the above special keys on a node
sequence that contains more than 1 or 0 nodes, then for each node in
the sequence (where the special key does make sense, e.g. text nodes
will be skipped for key <literal>*</literal> or
<literal>@foo</literal>), the special key will be applied as it was
explained for single nodes, and the results will be concatenated to
form the final result. The results will be concatenated in the order
as the corresponding nodes occur in the node sequence. The
concatenation means string or sequence concatenation depending on
the type of the results. If the special key would result in a string
for a single node, then for multiple nodes the result is a single
string too (the results for the single nodes concatenated), and if
the special key would return a sequence for a single node, then for
multiple nodes the result is a single sequence too. If there are 0
nodes in the sequence you apply the special key on, the string
result is an empty string or an empty sequence respectively.</para>
<para>XPath expressions can be used with node sequences. However,
for 0 or more than 1 nodes it will work only if you use Jaxen
instead of Xalan, because of the limitations of the Xalan XPath
implementation.</para>
</section>
</section>
</chapter>
<chapter xml:id="xgui_declarative">
<title>Declarative XML processing</title>
<indexterm>
<primary>XML</primary>
<secondary>declarative processing</secondary>
</indexterm>
<indexterm>
<primary>XSLT</primary>
</indexterm>
<section xml:id="xgui_declarative_basics">
<title>Basics</title>
<note>
<para>This section uses the DOM tree and the variable made in <link
linkend="xgui_expose">a previous chapter</link>.</para>
</note>
<para>With the imperative approach of XML processing -- this was shown
in the previous chapter -- you write an FTL program that walks the
tree to find the different kind of nodes. With the declarative
approach, you rather define how to handle the different kind of nodes,
and then let FreeMarker walk the tree and call the handlers you have
defined. This approach is useful for complex XML schemas, where the
same element can occur as the child of many other elements. Examples
of such schemas are XHTML and XDocBook.</para>
<para>The directive you most often use with the declarative approach
is the <link
linkend="ref.directive.recurse"><literal>recurse</literal>
directive</link>. This directive gets a node variable as parameter,
and <quote>visits</quote> all its children nodes, one after the other,
starting with the first child. <quote>Visiting</quote> a node means
that it calls a user-defined directive (like a macro) that has the
same name as the name of the child node
(<literal>?node_name</literal>). We say on this, that the user-defined
directive <emphasis>handles</emphasis> the node. The node that the
user-defined directive just handles is available as special variable
<literal>.node</literal>. For example, this FTL:</para>
<programlisting role="template">&lt;#recurse doc&gt;
&lt;#macro book&gt;
I'm the book element handler, and the title is: ${.node.title}
&lt;/#macro&gt;</programlisting>
<para>will print (I have removed some disturbing white-space form the
output):</para>
<programlisting role="output">I'm the book element handler, and the title is: Test Book
</programlisting>
<para>If you call <literal>recurse</literal> without parameter, then
it uses <literal>.node</literal>, that is, it visits all children
nodes of the node currently handled. So this FTL:</para>
<programlisting role="template">&lt;#recurse doc&gt;
&lt;#macro book&gt;
Book element with title ${.node.title}
&lt;#recurse&gt;
End book
&lt;/#macro&gt;
&lt;#macro title&gt;
Title element
&lt;/#macro&gt;
&lt;#macro chapter&gt;
Chapter element with title: ${.node.title}
&lt;/#macro&gt;</programlisting>
<para>will print (I have removed disturbing white-space form the
output):</para>
<programlisting role="output">Book element with title Test Book
Title element
Chapter element with title: Ch1
Chapter element with title: Ch2
End book</programlisting>
<para>You have seen how to define handlers for element nodes, but not
how to define handler for the text nodes. Since the name of the
handler is the same as the node-name of nodes it handles, and as the
node-name of all text nodes is <literal>@text</literal> (see <link
linkend="misc.xguiTable">the table</link>), you define handler for the
text nodes like this:</para>
<programlisting role="template">
&lt;#macro @text&gt;${.node?html}&lt;/#macro&gt;
</programlisting>
<para>Note the <literal>?html</literal>. You have to HTML-escape the
text, since you generate output of HTML format.</para>
<para>Here it is the template that transforms the XML to complete
HTML:</para>
<anchor xml:id="misc.example.declarativeBookProcessor"/>
<programlisting role="template">&lt;#recurse doc&gt;
&lt;#macro book&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;&lt;#recurse .node.title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;&lt;#recurse .node.title&gt;&lt;/h1&gt;
&lt;#recurse&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/#macro&gt;
&lt;#macro chapter&gt;
&lt;h2&gt;&lt;#recurse .node.title&gt;&lt;/h2&gt;
&lt;#recurse&gt;
&lt;/#macro&gt;
&lt;#macro para&gt;
&lt;p&gt;&lt;#recurse&gt;
&lt;/#macro&gt;
&lt;#macro title&gt;
&lt;#--
We have handled this element imperatively,
so we do nothing here.
--&gt;
&lt;/#macro&gt;
&lt;#macro @text&gt;${.node?html}&lt;/#macro&gt;</programlisting>
<para>and the output will be (now I will honestly include the annoying
white-space...):</para>
<programlisting role="output"> &lt;html&gt;
&lt;head&gt;
&lt;title&gt;Test Book&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Test Book&lt;/h1&gt;
&lt;h2&gt;Ch1&lt;/h2&gt;
&lt;p&gt;p1.1
&lt;p&gt;p1.2
&lt;p&gt;p1.3
&lt;h2&gt;Ch2&lt;/h2&gt;
&lt;p&gt;p2.1
&lt;p&gt;p2.2
&lt;/body&gt;
&lt;/html&gt;
</programlisting>
<para>Note that you can reduce substantially the amount of superfluous
whitespace in the output by using the <link
linkend="ref_directive_t">trim directives</link>, as
<literal>&lt;#t&gt;</literal>. See also: <xref
linkend="dgui_misc_whitespace"/></para>
<para>You may say that the FTL that did it with imperative approach
was much shorter. That's true, but the example XML uses a very simple
schema, and as I said, the declarative approach brings its form with
XML schemas that are not that firm about what element can occur where.
Say, introduce element <literal>mark</literal>, that should color text
to red, does not mater where do you use it; in a
<literal>title</literal>, or in a <literal>para</literal>. For this,
with the declarative approach, you just add a macro:</para>
<programlisting role="template">&lt;#macro mark&gt;&lt;font color=red&gt;&lt;#recurse&gt;&lt;/font&gt;&lt;/#macro&gt;</programlisting>
<para>And then <literal>&lt;mark&gt;...&lt;/mark&gt;</literal> will
automatically work everywhere. So for certain XML schemas, declarative
XML processing will actually result in shorter, and what is even more
important, much clearer FTL-s, than imperative XML processing. It's up
to you to decide which approach to use when; don't forget that you can
mix the two approaches freely. Say, in an element handler, you can use
imperative approach to process the contents of that element.</para>
</section>
<section xml:id="xgui_declarative_details">
<title>Details</title>
<section>
<title>Default handlers</title>
<para>For some XML node types, there is a default handler, which
will handle the node if you haven't defined a handler for the node
(i.e. if there is no user-defined directive available with name
identical to the node name). Here are these node types, and what the
default handler does:</para>
<itemizedlist>
<listitem>
<para>Text node: prints the text as it. Note, that in most
applications, this will not be good for you, because you should
escape the text before you send it to the output (with
<literal>?html</literal> or <literal>?xml</literal> or
<literal>?rtf</literal>, ...etc. depends on the output
format).</para>
</listitem>
<listitem>
<para>Processing instruction node: call handler called
<literal>@pi</literal> if you have created such user-defined
directive, otherwise do nothing (ignore the node).</para>
</listitem>
<listitem>
<para>Comment node, document type node: Do nothing (ignore the
node).</para>
</listitem>
<listitem>
<para>Document node: Call <literal>recurse</literal>, that is,
visit all children of the document node.</para>
</listitem>
</itemizedlist>
<para>Element and attribute nodes will be handled according to the
usual, XML independent mechanism. That is,
<literal>@<replaceable>node_type</replaceable></literal> will be
called as handler, and if that's not defined, then an error stops
template processing.</para>
<para>In the case of element nodes, this means that if you define a
macro (or other kind of user-defined directive) called
<literal>@element</literal>, that will catch all element nodes,
which has no more specific handler. If you have no
<literal>@element</literal> handler, then you
<emphasis>must</emphasis> define a handler for all possible
elements.</para>
<para>Attribute nodes are not visited by the
<literal>recurse</literal> directive, so you don't need to write
handlers for them.</para>
</section>
<section>
<title>Visiting a single node</title>
<para>With the <link
linkend="ref.directive.visit"><literal>visit</literal>
directive</link> you can visit a single node, instead of the
children of the node:
<literal>&lt;#visit <replaceable>nodeToVisist</replaceable>&gt;</literal>.
This can be useful sometimes.</para>
</section>
<section>
<title>XML namespaces</title>
<indexterm>
<primary>XML namespaces</primary>
<secondary>in declarative processing</secondary>
</indexterm>
<para>We said that the name of the handler user-defined directive
(like a macro) for an element is the name of the element. In fact,
it is the full-qualified name of the element:
<literal><replaceable>prefix</replaceable>:<replaceable>elementName</replaceable></literal>.
The rules regarding the usage of
<literal><replaceable>prefix</replaceable></literal>-es is the same
as with imperative processing. Thus, the user-defined
<literal>book</literal> directive handles only element
<literal>book</literal> that does not belong to any XML namespace
(unless you have specified a default XML namespace). So if the
example XML would use XML namespace
<literal>http://example.com/ebook</literal>:</para>
<programlisting role="unspecified">&lt;book xmlns="http://example.com/ebook"&gt;
<replaceable>...</replaceable></programlisting>
<para>Then the FTL should look as this:</para>
<programlisting role="template"><emphasis>&lt;#ftl ns_prefixes={"e":"http://example.com/ebook"}&gt;</emphasis>
&lt;#recurse doc&gt;
&lt;#macro "<emphasis>e:</emphasis>book"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;&lt;#recurse .node["<emphasis>e:</emphasis>title"]&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;&lt;#recurse .node["<emphasis>e:</emphasis>title"]&gt;&lt;/h1&gt;
&lt;#recurse&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/#macro&gt;
&lt;#macro "<emphasis>e:</emphasis>chapter"&gt;
&lt;h2&gt;&lt;#recurse .node["<emphasis>e:</emphasis>title"]&gt;&lt;/h2&gt;
&lt;#recurse&gt;
&lt;/#macro&gt;
&lt;#macro "<emphasis>e:</emphasis>para"&gt;
&lt;p&gt;&lt;#recurse&gt;
&lt;/#macro&gt;
&lt;#macro "<emphasis>e:</emphasis>title"&gt;
&lt;#--
We have handled this element imperatively,
so we do nothing here.
--&gt;
&lt;/#macro&gt;
&lt;#macro @text&gt;${.node?html}&lt;/#macro&gt;</programlisting>
<para>Or, you can define a default XML namespace, and then the
further part of the template remains the same as in the original XML
namespace free example:</para>
<programlisting role="template">&lt;#ftl ns_prefixes={"<emphasis>D</emphasis>":"http://example.com/ebook"}&gt;
&lt;#recurse doc&gt;
&lt;#macro book&gt;
<replaceable>...</replaceable></programlisting>
<para>But in this case don't forge that in XPath expressions (we
didn't used any in the example) the default XML namespace must be
accessed with an explicit <literal>D:</literal> since names without
prefix always refer to nodes with no XML namespace in XPath. Also
note that with the same logic as with imperative XML processing, the
name of handlers for elements that has no XML namespace is
<literal>N:<replaceable>elementName</replaceable></literal> if (and
only if) there is a default XML namespace. However, for nodes that
are not of type element (such as text nodes), you never use the
<literal>N</literal> prefix in the handler name, because those nodes
are free of the idea of XML namespaces. So for example, the handler
for text nodes is always just <literal>@text</literal>.</para>
<para>For more detailed information, please read <link
linkend="ref_directive_visit">the reference of
<literal>recurse</literal> and <literal>visit</literal></link>
directives.</para>
</section>
</section>
</chapter>
</part>
<part xml:id="app">
<title>Appendixes</title>
<appendix xml:id="app_faq">
<title>FAQ</title>
<indexterm>
<primary>FAQ</primary>
</indexterm>
<qandaset>
<qandaentry xml:id="faq_jsp_vs_freemarker">
<question>
<para>JSP versus FreeMarker?</para>
<indexterm>
<primary>JSP</primary>
</indexterm>
</question>
<answer>
<para>We compare FreeMarker with the JSP 2.0 + JSTL combo
here.</para>
<para>FreeMarker Pros:</para>
<itemizedlist>
<listitem>
<para>FreeMarker is not tied to Servlets or networking/Web; it
is just a class library to generate text output by merging a
template with Java objects (the data-model). You can execute
templates anywhere and anytime; no HTTP request forwarding or
similar tricks needed, no Servlet environment needed at all.
Because of this you can easily integrate it into any
system.</para>
</listitem>
<listitem>
<para>Terser syntax. Consider this JSP (assuming
<literal>&lt;%@ taglib prefix="c"
uri="http://java.sun.com/jsp/jstl/core"
%&gt;</literal>):</para>
<programlisting role="template">&lt;c:if test="${t}"&gt;
True
&lt;/c:if&gt;
&lt;c:choose&gt;
&lt;c:when test="${n == 123}"&gt;
Do this
&lt;/c:when&gt;
&lt;c:otherwise&gt;
Do that
&lt;/c:otherwise&gt;
&lt;/c:choose&gt;
&lt;c:forEach var="i" items="${ls}"&gt;
- ${i}
&lt;/c:forEach&gt;</programlisting>
<para>and the equivalent FTL:</para>
<programlisting role="template">&lt;#if t&gt;
True
&lt;/#if&gt;
&lt;#if n == 123&gt;
Do this
&lt;#else&gt;
Do that
&lt;/#if&gt;
&lt;#list ls as i&gt;
- ${i}
&lt;/#list&gt;</programlisting>
</listitem>
<listitem>
<para><link linkend="dgui_misc_autoescaping">Auto-escaping
option</link> to escape HTML and XML special characters
printed with
<literal>${<replaceable>...</replaceable>}</literal>. So you
can just write <literal>${x}</literal> instead of
<literal>&lt;c:out value="${x}"/&gt;</literal>, and most
importantly, you can't accidentally forget to do
escaping.</para>
</listitem>
<listitem>
<para>Locale-sensitive number and date formatting by default.
When you output for a human audience, all you need to do is
just write <literal>${x}</literal> rather than
<literal>&lt;fmt:formatNumber value="${x}"
/&gt;</literal>.</para>
</listitem>
<listitem>
<para>No servlet specific scopes and other highly technical
things in templates (unless, of course, you expose them into
the data-model deliberately). It was made for MVC from the
beginning, it focuses only on the presentation.</para>
</listitem>
<listitem>
<para>You can load the templates from anywhere; from the class
path, from a data-base, etc.</para>
</listitem>
<listitem>
<para>Easier to define ad-hoc macros and functions.</para>
</listitem>
<listitem>
<para>No sweeping errors under the carpet. Missing variables
and <literal>null</literal>-s will not silently default to
<literal>0</literal>/<literal>false</literal>/empty-string,
but cause error. <link
linkend="faq_picky_about_missing_vars">See more about this
here...</link></para>
</listitem>
<listitem>
<para><quote>Object wrapping</quote>. This lets you show the
objects to templates in a customized, presentation oriented
way (e.g. <link linkend="xgui_imperative_learn">see
here</link> how a W3C DOM nodes can be seen by templates using
this technology.)</para>
</listitem>
<listitem>
<para>Macros and functions are just variables, so they can be
easily passed around as parameter values, put into the
data-model, etc., just like any other values.</para>
</listitem>
<listitem>
<para>Virtually unnoticeable delay when visiting a page for
the first time (or after it was changed), because no expensive
compilation happens.</para>
</listitem>
</itemizedlist>
<para>FreeMarker Cons:</para>
<itemizedlist>
<listitem>
<para>Not a <quote>standard</quote>. There are fewer tools and
IDE integrations, fewer developers knows it and there's much
less industry support in general. (However, most JSP tag
libraries can work in FreeMarker templates with the proper
setup, unless they are base on <literal>.tag</literal>
files.)</para>
</listitem>
<listitem>
<para>Its syntax doesn't follow the HTML/XML rules apart from
some visual similarity, which is confusing for new users (it's
the price of the terseness). JSP doesn't follow it either, but
it's closer to it.</para>
</listitem>
<listitem>
<para>Since macros and functions are just variables, incorrect
directive and parameter names and missing required parameters
can be detected only on runtime.</para>
</listitem>
<listitem>
<para>Doesn't work with JSF. (It could work technically, but
nobody has implemented that yet.)</para>
</listitem>
</itemizedlist>
<para>You may read this if you are considering replacing JSP with
FreeMarker in an existing application or in a legacy framework
that only supports JSP: <xref
linkend="pgui_misc_servlet_model2"/></para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_picky_about_missing_vars">
<question>
<para>Why is FreeMarker so picky about <literal>null</literal>-s
and missing variables, and what to do with it?</para>
</question>
<answer>
<para>To recapitulate what's this entry is about: FreeMarker by
default treats an attempt to access a non-existent variable or a
<literal>null</literal> value (<link linkend="faq_null">this two
is the same for FreeMarker</link>) as error, which aborts the
template execution.</para>
<para>First of all, you should understand the reason of being
picky. Most scripting languages and template languages are rather
forgiving with missing variables (and with
<literal>null</literal>-s), and they usually treat them as empty
string and/or 0 and/or logical false. This behavior has several
problems:</para>
<itemizedlist>
<listitem>
<para>It potentially hides accidental mistakes, like a typo in
a variable name, or when the template author refers to a
variable that the programmer doesn't put into the data-model
for that template, or for which the programmer uses a
different name. Humans are prone to do such mistakes, while
computers are not, so missing this opportunity that the
template engine can show these errors is a bad business. Even
if you very carefully check the output of the templates during
development, it is easy to look over mistakes like
<literal>&lt;#if hasWarnigs&gt;<replaceable>print warnings
here...</replaceable>&lt;/#if&gt;</literal>, which would then
silently never print the warnings, since you have mistyped the
variable name (have you noticed it?). Also think about
maintenance, when you later modify your application; probably
you will not re-check templates (many applications has
hundreds of them) that carefully each time, for all possible
scenarios. Unit tests typically doesn't cover web page content
very good either (if you have them at all...); they mostly
only check certain manually set patterns in the web page, so
they will often gloss though changes that are actually bugs.
But if the page fails with exception, that's something human
testers will notice and unit test will notice (as the whole
page will fail), and in production the maintainers will notice
(assuming somebody check error logs).</para>
</listitem>
<listitem>
<para>Makes dangerous assumptions. The script language or
template engine knows nothing about the application domain, so
when it decides the value of something that it doesn't know to
be 0/false, it is a quite irresponsible and arbitrary thing.
Just because it's not know what's your current balance at your
bank, can we just say it's $0? Just because it is not known if
a patient has penicillin allergy, can we just say he/she
doesn't have it? Just consider the implications of such
mistakes. Showing an error page is often better than showing
incorrect information that looks good, leading to bad
decisions on the user side.</para>
</listitem>
</itemizedlist>
<para>Being not picky is mostly sweeping under the carpet in this
case (not facing the problems), which of course most people feels
more convenient, but still, we believe that in most cases being
strict will save your time and increase your software quality on
the long run.</para>
<para>On the other hand, we recognize that there are cases where
you don't want FreeMarker to be that picky for good reason, and
there is solution for them:</para>
<itemizedlist>
<listitem>
<para>It's often normal that your data-model contains
<literal>null</literal>-s or have optional variables. In such
cases use <link linkend="dgui_template_exp_missing">these
operators</link>. If you use them too often, try to rethink
your data-model, because depending on them too much won't just
make the templates too verbose, but increases the probability
of hiding errors and printing arbitrary incorrect output (for
the reasons described earlier).</para>
</listitem>
<listitem>
<para>In some application you may rather want to show an
incomplete/damaged page than an error page. In this case you
can <link linkend="pgui_config_errorhandling">use another
error handler</link> than the default one. A custom error
handler can skip the problematic part, or show an error
indicator there, instead of aborting the whole page rendering.
Note, however, that although the error handlers don't give
arbitrary default values to variables, for pages that show
critical information it's maybe still better to show an error
page.</para>
</listitem>
<listitem>
<para>If the pages contain parts that aren't critically
important (like some side bars), another feature you may
interested in is <link linkend="ref_directive_attempt">the
<literal>attempt</literal>/<literal>recover</literal>
directives</link>.</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_number_grouping">
<question>
<para>Why does FreeMarker print the numbers with strange
formatting (as 1,000,000 or 1 000 000 instead of 1000000)?</para>
</question>
<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
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
example:</para>
<programlisting role="unspecified">cfg.setNumberFormat("0.######"); // now it will print 1000000
// where cfg is a freemarker.template.Configuration object</programlisting>
<para>Note however than humans often find it hard to read big
numbers without grouping separator. So in general it is
recommended to keep them, and in cases where the numbers are for
''computer audience'' (which is confused on the grouping
separators), use the <link
linkend="ref_builtin_c"><literal>c</literal> built-in</link>. For
example:</para>
<programlisting role="template">&lt;a href="/shop/productdetails?id=${<emphasis>product.id?c</emphasis>}"&gt;Details...&lt;/a&gt;</programlisting>
<para>For computer audience you need <literal>?c</literal> anyway,
as the decimal separators can also wary depending on the
locale.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_number_decimal_point">
<question>
<para>Why does FreeMarker print bad decimal and/or grouping
separator symbol (as 3.14 instead of 3,14)?</para>
</question>
<answer>
<para>Different countries use different decimal/grouping separator
symbols. If you see incorrect symbols, then probably your locale
is not set properly. Set the default locale of the JVM or override
the default locale with the <literal>locale</literal> <link
linkend="pgui_config_settings">FreeMarker setting</link>. For
example:</para>
<programlisting role="unspecified">cfg.setLocale(java.util.Locale.ITALY);
// where cfg is a freemarker.template.Configuration object</programlisting>
<para>However, sometimes you want to output a number not for human
audience, but for <quote>computer audience</quote> (like you want
to print a size in CSS), in which case you must use dot as decimal
separator, regardless of the locale (language) of the page. For
that use the <link linkend="ref_builtin_c"><literal>c</literal>
built-in</link>, for example:</para>
<programlisting role="template">font-size: ${<emphasis>fontSize?c</emphasis>}pt;</programlisting>
</answer>
</qandaentry>
<qandaentry xml:id="faq_number_boolean_formatting">
<question>
<para>Why does FreeMarker give an error when I try to print a
boolean like <literal>${aBoolean}</literal>, and how to fix
it?</para>
</question>
<answer>
<para><literal>${<replaceable>...</replaceable>}</literal> meant
to format values for human consumption, and unlike numbers,
booleans has no commonly accepted format
(<literal>true</literal>/<literal>false</literal> is common in
computer languages, but you rarely use it outside that). The
proper format depends quite much on the context, therefore,
usually the template author should decide the proper format for
each case, like <literal>${washable?string("yes",
"no")}</literal>, <literal>${caching?string("Enabled",
"Disabled")}</literal>, <literal>${heating?string("on",
"off")}</literal>, etc.</para>
<para>However, there are two cases where this gets
impractical:</para>
<itemizedlist>
<listitem>
<para>When printing boolean to generate computer language
output, and hence you want
<literal>true</literal>/<literal>false</literal>. In such case
use <literal>${<replaceable>someBoolean</replaceable><link
linkend="ref_builtin_c_boolean">?c</link>}</literal> (requires
FreeMarker 2.3.20). If you never generate for human
consumption, only for computer language output, you might want
to set <literal>boolean_format</literal> to
<literal>c</literal> (available since FreeMarker 2.3.29), and
then <literal>${<replaceable>aBoolean</replaceable>}</literal>
will behave as
<literal>${<replaceable>aBoolean</replaceable>?c}</literal>.</para>
<para>Before 2.3.20, if you really can't upgrade FreeMarker,
try if
<literal>${<replaceable>someBoolean</replaceable>?string}</literal>.
By default that prints
<literal>true</literal>/<literal>false</literal>. Then somehow
try to ensure that <literal>boolean_format</literal> won't be
changed later by someone, breaking your output.</para>
</listitem>
<listitem>
<para>When you have format most of the booleans on the same
way. In this case you can set the
<literal>boolean_format</literal> setting
(<literal>Configuration.setBooleanFormat</literal>) to reflect
that, and then since FreeMarker 2.3.20 you can just write
<literal>${<replaceable>someBoolean</replaceable>}</literal>.
(Note that this doesn't work for
<literal>true</literal>/<literal>false</literal> though - you
have to use <literal>?c</literal> there.)</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_template_not_found">
<question>
<para>FreeMarker can't find my templates
(<literal>TemplateNotFoundException</literal> or
<literal>FileNotFoundException</literal>, <quote>Template not
found</quote> error message)</para>
</question>
<answer>
<para>First of all, you should know that FreeMarker doesn't load
templates from file system paths directly. Instead, it uses a
simple virtual file system that might reads non-filesystem
resources (templates from inside jar-s, from inside a database
table, etc.). What that virtual file is decided by a configuration
setting,
<literal>Configuration.setTemplateLoader(TemplateLoader)</literal>.
Even if the <literal>TemplateLoader</literal> your are using maps
to the file system, it will have a base directory that contains
all the templates, and that will be the root of your virtual file
system that you can't reach out from (i.e., absolute paths will be
still relative to the virtual file system root).</para>
<para>Tips to solve the problem:</para>
<itemizedlist>
<listitem>
<para>If you are the one who configure FreeMarker, be sure
that you set a proper
<literal>TemplateLoader</literal>.</para>
</listitem>
<listitem>
<para>Otherwise see if the template-not-found error's message
contains the description of the
<literal>TemplateLoader</literal> used. If it doesn't, you are
using an old FreeMarker version, so update it. Getting
<literal>FileNotFoundException</literal> instead of
<literal>TemplateNotFoundException</literal> is also a sign of
that, and so you will get less helpful error messages. (If the
<literal>TemplateLoader</literal> in the error message is like
<literal>foo.SomeTemplateLoader@64f6106c</literal> and so
doesn't show some relevant parameters, you may should ask the
author to define a nicer
<literal>toString()</literal>.)</para>
</listitem>
<listitem>
<para>A frequent mistake is using a
<literal>FileTemplateLoader</literal> for a Servlet-based web
application, instead of a
<literal>WebappTemplateLoader</literal>. It may works in one
environment, but not in another, as the Servlet specification
makes no promises about your resources being accessible as
plain files, not even when the <literal>war</literal> file is
extracted.</para>
</listitem>
<listitem>
<para>Know that when you are including/importing a template
from another template, if you don't start the template name
with <literal>/</literal>, it will be interpreted relatively
to the directory of the including template. The error message
contains the full (resolved) name, so you should notice this
there.</para>
</listitem>
<listitem>
<para>Check that you aren't using <literal>\</literal>
(backslash) instead of <literal>/</literal> (slash).
(FreeMarker 2.3.22 and later will warn you about that in the
error message.)</para>
</listitem>
<listitem>
<para>As a last resort, turn on debug level logging (in the
logging framework that you are using) for the category
<literal>freemarker.cache</literal>, to see more of what's
going on.</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_check_version">
<question>
<para>The documentation writes about feature
<replaceable>X</replaceable>, but it seems that FreeMarker doesn't
know that, or it behaves in a different way as documented, or a
bug that was supposedly fixed is still present.</para>
</question>
<answer>
<para>Are you sure that you are using the documentation written
for the same version of FreeMarker that you actually use?
Especially, note that our online documentation is for the latest
stable FreeMarker release. You may use an older release; update
it.</para>
<para>Are you sure that the Java class loader finds the same
<literal>freemarker.jar</literal> that you expect to use? Maybe
there is an older version of <literal>freemarker.jar</literal>
around, which shadows the never. To check this, try to print the
version number in a template with <literal>${.version}</literal>.
(If it dies with <quote>Unknown built-in variable: version</quote>
error message, then you use a very, very old release.).</para>
<para>If you suspect that the problem is that you have multiple
<literal>freemarker.jar</literal>-s, the typical culprit is that
some module has a Maven or Ivy dependency with the old
<literal>freemarker</literal> group ID, as opposed to the more
modern <literal>org.freemarker</literal> group ID. Because of the
different group ID-s these aren't seen as conflicting artifacts by
Maven or Ivy, and so both version gets in. In this case you have
to exclude the <literal>freemarker</literal> dependency.</para>
<para>If you think that the documentation or FreeMarker is wrong,
please report it using the bug tracker, or the mailing list. Thank
you!</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_alternative_syntax">
<question>
<para>The <literal>&lt;</literal> and <literal>&gt;</literal> of
FreeMarker tags confuses my editor or the XML parser. What to
do?</para>
</question>
<answer>
<para>You can use <literal>[</literal> and <literal>]</literal>
instead of <literal>&lt;</literal> and <literal>&gt;</literal>;
see more about square bracket tag syntax <link
linkend="dgui_misc_alternativesyntax">here.</link> The comparison
operators, like <literal>&lt;</literal>, also have an alternative
syntax (<literal>lt</literal> and <literal>&amp;lt;</literal> in
this case); see more about them <link
linkend="dgui_template_exp_comparison">here</link>. Also, the
<literal>&amp;&amp;</literal> operator (which is not well-format
HTML/XML) can be written as <literal>\and</literal> or
<literal>&amp;amp;&amp;amp;</literal> since 2.3.27.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_alternative_syntax_interpolation">
<question>
<para><literal>${<replaceable>...</replaceable>}</literal> and/or
<literal>#{<replaceable>...</replaceable>}</literal> is used in
the output I have to generate a lot, and FreeMarker tries to
resolve them. What to do?</para>
</question>
<answer>
<para>You can escape them like
<literal>${'$'}{<replaceable>...</replaceable>}</literal>, however
that's impractical if you have to do that often. So starting from
FreeMarker 2.3.28 you can use
<literal>[=<replaceable>...</replaceable></literal><literal>]</literal>
instead; see more about the square bracket interpolation syntax
<link linkend="dgui_misc_alternativesyntax">here.</link> If you
are going to generate JSP files or even FreeMarker templates, this
is very useful.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_legal_variable_names">
<question>
<para>What are the legal variable names?</para>
<indexterm>
<primary>variables</primary>
<secondary>names</secondary>
</indexterm>
</question>
<answer>
<para>FreeMarker has no limitations regarding the characters used
in variable names, nor regarding the length of the variable names,
but for your convenience try to chose variable names that can be
used with the simple variable reference expressions (see it <link
linkend="dgui_template_exp_var_toplevel">here</link>). If you have
to choose a more extreme variable name, that's not a big problem
either: <link linkend="faq_strange_variable_name">see
here</link>.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_strange_variable_name">
<question>
<para>How can I use variable names (macro name, parameter name)
that contain minus sign (<literal>-</literal>), colon
(<literal>:</literal>), dot (<literal>.</literal>), or or other
special characters?</para>
</question>
<answer>
<para>If you have a variable with strange name like
<quote>foo-bar</quote>, FreeMarker will misunderstand what you
mean if you just use it like in <literal>${foo-bar}</literal>. In
this case, it will believe that you want to subtract the value of
<literal>bar</literal> from <literal>foo</literal>. This FAQ entry
explains how to handle situations like this.</para>
<para>First of all it should be clear that these are just
syntactical problems, as otherwise FreeMarker has no limitations
regarding the characters used in variable names, nor regarding the
length of them.</para>
<para>If the special character is one of minus sign
(<literal>-</literal>, UCS 0x2D) or dot (<literal>.</literal>, UCS
0x2E) or colon (<literal>:</literal>, UCS 0x3A), then all you have
to do is putting a backslash (<literal>\</literal>) before these
characters, like in <literal>foo\-bar</literal> (since FreeMarker
2.3.22). Then FreeMarker will know that you didn't mean the
operator with the same symbol. This works everywhere where you
specify unquoted identifiers, like for macro and function names,
parameter names, and all kind of variable references in general.
(Note that these escapes only work in identifiers, not in string
literals.)</para>
<para>When the special character is not one of minus sign, dot, or
colon, then it gets trickier. Let's say the problematic variable
name is <quote>a+b</quote>. Then:</para>
<itemizedlist>
<listitem>
<para>If you want to read the variable: If it's a subvariable
of something, you can write
<literal>something["a+b"]</literal> (remember,
<literal>something.x</literal> is equivalent to
<literal>something["x"])</literal>. If it's a top-level
variable, those are accessible through the special hash
variable ,<literal>.vars</literal>, so you can write
<literal>.vars["a+b"]</literal>. Naturally, this trick works
with macro and function invocations too:
<literal>&lt;@.vars["a+b"]/&gt;</literal>,
<literal>.vars["a+b"](1, 2)</literal>.</para>
</listitem>
<listitem>
<para>If you want to create or modify the variable: All
directives that let you create or modify a variable (such as
<literal>assign</literal>, <literal>local</literal>,
<literal>global</literal>, <literal>macro</literal>,
<literal>function</literal>, etc.) allows the quotation of the
destination variable name. For example, <literal>&lt;#assign
foo = 1&gt;</literal> is the same as <literal>&lt;#assign
"foo" = 1&gt;</literal>. So you can write things like
<literal>&lt;#assign "a+b" = 1&gt;</literal> and
<literal>&lt;#macro "a+b"&gt;</literal>.</para>
</listitem>
<listitem>
<para>Unfortunately, you can't use such a variable name (that
contains special characters other than <literal>-</literal>,
<literal>.</literal> and <literal>:</literal>) as macro
parameter name.</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_jsp_custom_tag_syntax">
<question>
<para>Why do I get "java.lang.IllegalArgumentException: argument
type mismatch" when I try to use <replaceable>X</replaceable> JSP
custom tag?</para>
</question>
<answer>
<para>Fist of all, update FreeMarker, because 2.3.22 and later
gives a much more helpful error message, that pretty much answers
the question. Anyway, the reason is as follows. On JSP pages you
quote all parameter (attribute) values, it does not mater if the
type of the parameter is string or boolean or number. But since
custom tags are accessible in FTL templates as plain user-defined
FTL directives, you have to use the FTL syntax rules inside the
custom tags, not the JSP rules. Thus, according to FTL rules, you
must not quote boolean and numerical parameter values, or they are
interpreted as string values, and this will cause a type mismatch
error when FreeMarker tries to pass the value to the custom tag
that expects non-string value.</para>
<para>For example, the <literal>flush</literal> parameter to
Struts Tiles <literal>insert</literal> tag is boolean. In JSP the
correct syntax was:</para>
<programlisting role="template">&lt;tiles:insert page="/layout.jsp" <emphasis>flush="true"</emphasis>/&gt;
<replaceable>...</replaceable></programlisting>
<para>but in FTL you should write:</para>
<programlisting role="template">&lt;@tiles.insert page="/layout.ftl" <emphasis>flush=true</emphasis>/&gt;
<replaceable>...</replaceable></programlisting>
<para>Also, for similar reasons, this is wrong:</para>
<programlisting role="template">&lt;tiles:insert page="/layout.jsp" <emphasis>flush="${needFlushing}"</emphasis>/&gt;
<replaceable>...</replaceable></programlisting>
<para>and you should write:</para>
<programlisting role="template">&lt;tiles:insert page="/layout.jsp" <emphasis>flush=needFlushing</emphasis>/&gt;
<replaceable>...</replaceable></programlisting>
<para>(Not <literal>flush=${needFlushing}</literal>!)</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_servlet_include">
<question>
<para>How to include other resources in a way as
<literal>jsp:include</literal> does it?</para>
</question>
<answer>
<para>Not with <literal>&lt;#include ...&gt;</literal>, as that
just includes another FreeMarker template without involving the
Servlet container.</para>
<para>Since the inclusion method you look for is Servlet-related,
and pure FreeMarker is unaware of Servlets or even HTTP, it's the
Web Application Framework that decides if you can do this and if
so how. For example, in Struts 2 you can do this like this:</para>
<programlisting role="template">&lt;@s.include value="/WEB-INF/just-an-example.jspf" /&gt;</programlisting>
<para>If the FreeMarker support of the Web Application Framework
is based on
<literal>freemarker.ext.servlet.FreemarkerServlet</literal>, then
you can also do this (since FreeMarker 2.3.15):</para>
<programlisting role="template">&lt;@include_page path="/WEB-INF/just-an-example.jspf" /&gt;</programlisting>
<para>but if the Web Application Framework provides its own
solution, then you may prefer that, after all it may does
something special.</para>
<para>For more information about <literal>include_page</literal>
<link linkend="pgui_misc_servlet_include">read
this...</link></para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_parameter_unwrapping">
<question>
<para>How can I get the parameters to my
plain-Java-method/<literal>TemplateMethodModelEx</literal>/<literal>TemplateTransformModel</literal>/<literal>TemplateDirectiveModel</literal>
implementation as plain
<literal>java.lang.*</literal>/<literal>java.util.*</literal>
objects?</para>
</question>
<answer>
<para>Unfortunately, there is no simple general-purpose solution
for this problem. The problem is that FreeMarker object wrapping
is very flexible, which is good when you access variables from
templates, but makes unwrapping on the Java side a tricky
question. For example, it is possible to wrap a
non-<literal>java.util.Map</literal> object as
<literal>TemplateHashModel</literal> (FTL hash variable). But
then, it can't be unwrapped to <literal>java.util.Map</literal>,
since there is no wrapped <literal>java.util.Map</literal> around
at all.</para>
<para>So what to do then? Basically there are two cases:</para>
<itemizedlist>
<listitem>
<para>Directives and methods that are written for presentation
purposes (like kind of <quote>tools</quote> for helping
FreeMarker templates) should declare their arguments as
<literal>TemplateModel</literal>-s and the more specific sub
interfaces of that. After all, the object wrapping is about
transforming the data-model to something that serves the
purpose of the presentation layer, and these methods are part
of the presentation layer. If you still need a plain Java type
there, you may turn to the
<literal>ObjectWrapperAndUnwrapper</literal> interface of the
current <literal>ObjectWrapper</literal> (can be get with
<literal>Environment.getObjectWrapper()</literal>).</para>
</listitem>
<listitem>
<para>Methods that are not for presentation related tasks (but
for business logic and like) should be implemented as plain
Java methods, and should not use any FreeMarker specific
classes at all, since according the MVC paradigm they must be
independent of the presentation technology (FreeMarker). If
such a method is called from a template, then it is the
responsibility of the <link
linkend="pgui_datamodel_objectWrapper">object wrapper</link>
to ensure the conversion of the arguments to the proper type.
If you use the <link
linkend="pgui_datamodel_defaultObjectWrapper"><literal>DefaultObjectWrapper</literal></link>
or the <link
linkend="pgui_misc_beanwrapper"><literal>BeansWrapper</literal></link>
then this will happen automatically. For
<literal>DefaultObjectWrapper</literal>, this mechanism works
much better, if you <link
linkend="topic.defaultObjectWrapperIcI">set its
<literal>incompatibleImprovements</literal> to
2.3.22</link>.</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_nonstring_keys">
<question>
<para>Why I can't use non-string key in the
<literal>myMap[myKey]</literal> expression? And what to do
now?</para>
<indexterm>
<primary>hash</primary>
<secondary>key type</secondary>
</indexterm>
</question>
<answer>
<para>The <quote>hash</quote> type of the FreeMarker Template
Language (FTL) is not the same as Java's <literal>Map</literal>.
FTL's hash is an associative array too, but it uses string keys
exclusively. This is because it was introduced for sub variables
(as <literal>password</literal> in
<literal>user.password</literal>, which is the same as
<literal>user["password"]</literal>), and variable names are
strings.</para>
<para>If you only need to list the key-value pairs of a
<literal>Map</literal>, you can just write something like
<literal>&lt;#list myMap as k, v&gt;${k}:
${v}&lt;/#list&gt;</literal> (see more about <link
linkend="ref.directive.list">the <literal>list directive</literal>
here</link>). This enumerates the <literal>Map</literal> entries,
and supports non-string keys. This requires FreeMarker 2.3.25 or
later. (If for some reason you can't upgrade to 2.3.25, you can
use the Java API of <literal>Map</literal> instead, like
<literal>&lt;#list myMap?api.entrySet() as kvp&gt;${kvp.key}:
${kvp.value}&lt;/#list&gt;</literal>.)</para>
<para>If you need to do more than listing, you will have to turn
to the Java API of the <literal>Map</literal>. You can do it like
this: <literal>myMap?api.get(nonStringKey)</literal>. However, for
<literal>?api</literal> to be enabled, you may need to configure
FreeMarker a bit (<link linkend="ref_buitin_api_and_has_api">see
more here</link>).</para>
<para>Note that as Java's <literal>Map</literal> is particular
about the exact class of the key, at least for numerical keys
calculated inside the templates you will have to cast them to the
proper Java type, otherwise the item will not be found. For
example if you use <literal>Integer</literal> keys in a Map, then
you should write <literal>${myMap.get(numKey?int)}</literal>. This
is because of FTL's deliberately simplified type system has only a
single numerical type, while Java distinguishes a lot of numerical
types. Note that the casting is not needed when the key value
comes directly from the data-model (i.e., you didn't modified its
value with arithmetical calculations in the template), including
the case when it's the return value of a method, and it was of the
proper class before wrapping, because then the result of the
unwrapping will be of the original type.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_simple_map">
<question>
<para>When I list the contents of a map (a hash) with
<literal>?keys</literal>/<literal>?values</literal>, I get the
<literal>java.util.Map</literal> methods mixed with the real map
entries. Of course, I only want to get the map entries.</para>
</question>
<answer>
<para>Certainly you are using pure <literal>BeansWrapper</literal>
as your object wrapper (instead of the default,
<literal>DefaultObjectWrapper</literal>), or a custom subclass of
it, and the <literal>simpleMapWrapper</literal> property of that
is left to <literal>false</literal>. Unfortunately, that's the
default of <literal>BeansWrapper</literal> (for backward
compatibility), so you have to explicitly set it to
<literal>true</literal> where you instantiate it. Also, at least
since 2.3.22, applications should just use
<literal>DefaultObjectWrapper</literal> (with <link
linkend="topic.defaultObjectWrapperIcI">its
<literal>incompatibleImprovements</literal> set to at least
2.3.22</link> - that's especially important if you are switching
from pure <literal>BeansWrapper</literal>), which never had this
problem.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_modify_seq_and_map">
<question>
<para>How can I modify sequences (lists) and hashes (maps) in
FreeMarker templates?</para>
<indexterm>
<primary>modify hashes</primary>
</indexterm>
<indexterm>
<primary>modify sequences</primary>
</indexterm>
<indexterm>
<primary>sequence</primary>
<secondary>modify</secondary>
</indexterm>
<indexterm>
<primary>hash</primary>
<secondary>modify</secondary>
</indexterm>
</question>
<answer>
<para>First of all, you may don't want to modify the
sequence/hash, just concatenate (add) two or more of them, which
results in a new sequence/hash, rather than modifying an existing
one. In this case use the <link
linkend="dgui_template_exp_sequenceop_cat">sequence
concatenation</link> and <link
linkend="dgui_template_exp_hashop_cat">hash concatenation
operators</link>. Also, you may use the <link
linkend="dgui_template_exp_seqenceop_slice">subsequence
operator</link> instead of removing sequence items. However, be
aware of the performance implications: these operations are fast,
but the hashes/sequences that are the result of many subsequent
applications of these operations (i.e., when you use the result of
the operation as the input of yet another operation, and so on)
will be slow to read.</para>
<para>Now if you still want to modify sequences/hashes, then read
on...</para>
<para>The FreeMarkes Template Language doesn't support the
modification of sequences/hashes. It's for displaying already
calculated things, not for calculating data. Keep templates
simple. But don't give it up, you will see some advices and tricks
bellow.</para>
<para>The best is if you can divide the work between the
data-model builder program and the template so that the template
doesn't need to modify sequences/hashes. Maybe if you rethink your
data-model, you will realize this is possible. But, seldom there
are cases where you need to modify sequences/hashes for some
complex but purely presentation related algorithms. It seldom
happens, so think twice whether that calculation (or parts of it)
rather belongs to the data-model domain than to the presentation
domain. Let's assume you are sure it belongs to the presentation
domain. For example, you want to display a keyword index on some
very smart way, whose algorithm need you to create and write some
sequence variables. Then you should do something like this (ugly
situations has ugly solutions...):</para>
<programlisting role="template">&lt;#assign caculatedResults =
'com.example.foo.SmartKeywordIndexHelper'?new().calculate(keywords)&gt;
&lt;#-- some simple algorithms comes here, like: --&gt;
&lt;ul&gt;
&lt;#list caculatedResults as kw&gt;
&lt;li&gt;&lt;a href="${kw.link}"&gt;${kw.word}&lt;/a&gt;
&lt;/#list&gt;
&lt;/ul&gt;</programlisting>
<para>That is, you move out the complex part of the presentation
task from the template into Java code. Note that it doesn't affect
the data-model, so the presentation is still kept separated from
other the other application logic. Of course the drawback is that
for this the template author will need the help of a Java
programmer, but for complex algorithms that's probably needed
anyway.</para>
<para>Now, if you still say you need to modify sequences/hashes
directly with the FreeMarker template, here are some solutions,
but please read the warning after them:</para>
<itemizedlist>
<listitem>
<para>You can access the Java API of a
<literal>java.util.Map</literal> with the help of the
<literal>api</literal> built-in, like
<literal>myMap?api.put(11, "eleven")</literal>. You will need
to get a <literal>Map</literal> from somewhere though (an FTL
hash literal like <literal>{}</literal> won't suffice, as it's
read only and doesn't support <literal>api</literal> either).
For example, you could expose a Java method or
<literal>TemplateMethodModelEx</literal> to the template that
returns a <literal>new LinkeHashMap()</literal>, so you can do
<literal>&lt;#assign myMap =
utils.newLinkedHashMap()&gt;</literal>.</para>
</listitem>
<listitem>
<para>You can write a <literal>TemplateMethodModelEx</literal>
and <literal>TemplateDirectiveModel</literal> implementation
that can modify certain types of sequences/hashes. Just
certain types, because
<literal>TemplateSequenceModel</literal> and
<literal>TemplateHashModel</literal> doesn't have methods for
modification, so you will need the sequence or hash to
implement some additional methods. An example of this solution
can be seen in FMPP. It allows you to do things like this
(<literal>pp</literal> stores the services provided by FMPP
for templates):</para>
<programlisting role="template">&lt;#assign a = pp.newWritableSequence()&gt;
&lt;@pp.add seq=a value="red" /&gt;</programlisting>
<para>The <literal>pp.add</literal> directive works only with
sequences that were created with
<literal>pp.newWritableSequence()</literal>. So for example
the template author can't modify a sequence that comes from
the data-model with this.</para>
</listitem>
<listitem>
<para>A sequence can have some methods/directives if you use a
customized wrapper (so you can write something like
<literal>&lt;@myList.append foo /&gt;</literal>).</para>
</listitem>
</itemizedlist>
<para>But beware, these solutions have a problem: The <link
linkend="dgui_template_exp_sequenceop_cat">sequence
concatenation</link>, <link
linkend="dgui_template_exp_seqenceop_slice">sequence slice</link>
operator (like <literal>seq[5..10]</literal>) and
<literal>?reverse</literal> do not copy the original sequence,
just wraps it (for efficiency), so the resulting sequence will
change if the original sequence is changed later (an abnormal
aliasing effect). The same problem exists with the result of <link
linkend="dgui_template_exp_hashop_cat">hash concatenation</link>;
it just wraps the two hashes, so the resulting hash will magically
change if you modify the hashes you have added earlier. As a
work-around, after you did the above problematic operations,
either be sure you will not modify the objects that were used as
input, or create a copy of the result with a method provided by
the solution described in above two points (e.g. in FMPP you could
do <literal>&lt;#assign b =
pp.newWritableSequence(a[5..10])&gt;</literal> and
<literal>&lt;#assign c = pp.newWritableHash(hashA +
hashB)&gt;</literal>). Of course this is easy to miss... so again,
rather try to build the data-model so you will not need to modify
collections, or use a presentation task helper class as was shown
earlier.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_null">
<question>
<para>What about <literal>null</literal> and the FreeMarker
template language? <indexterm>
<primary>null</primary>
</indexterm></para>
</question>
<answer>
<para>The FreeMarker template language doesn't know the Java
language <literal>null</literal> at all. It doesn't have
<literal>null</literal> keyword, and it can't test if something is
<literal>null</literal> or not. When it technically faces with a
<literal>null</literal>, it treats it exactly as a missing
variable. For example, both if <literal>x</literal> is
<literal>null</literal> in the data-model and if it's not present
at all, <literal>${x!'missing'}</literal> will print
<quote>missing</quote>, you can't tell the difference. Also, if
for example you want to test if a Java method has returned
<literal>null</literal>, just write something like
<literal>&lt;#if foo.bar()??&gt;</literal>.</para>
<para>You may interested in the rationale behind this. From the
viewpoint of the presentation layer a <literal>null</literal> and
non-existent thing is almost always the same. The difference
between this two is usually just a technical detail, which is
rather the result of implementation details than of the
application logic. That you can't compare something to
<literal>null</literal> (unlike in Java); it doesn't make sense to
compare something with <literal>null</literal> in a template,
since the template language doesn't do identity comparison (like
the Java <literal>==</literal> operator when you compare two
objects) but the more common sense value comparison (like Java's
<literal>Object.equals(Object)</literal>; that doesn't work with
<literal>null</literal> either). And how could FreeMarker tell if
something concrete equals with something that is missing and thus
unknown? Or if two missing (unknown) things are equal? Of course
these questions can't be answered.</para>
<para>There is at least one problem with this
<literal>null</literal>-unaware approach. When you call a Java
method from a template, you may want to pass a
<literal>null</literal> value as argument (since the method was
designed to be used in Java language, where the concept of
<literal>null</literal> is known). In this case you can exploit a
bug of FreeMarker (that we will not fix until we provide a correct
solution for passing <literal>null</literal> values to a method):
if you specify a missing variable as the argument, then it will
not cause an error, but a <literal>null</literal> will be passed
to the method instead. Like <literal>foo.bar(nullArg)</literal>
will call the <literal>bar</literal> method with
<literal>null</literal> as argument, assuming that there is no
variable exists with <quote>nullArg</quote> name.</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_capture">
<question>
<para>How can I use the output of a directive (macro) in
expressions (as a parameter to another directive)?</para>
</question>
<answer>
<para>Capture the output into a variable with the
<literal>assign</literal> or <literal>local</literal> directive.
For example:</para>
<programlisting role="template">&lt;#assign capturedOutput&gt;&lt;@outputSomething /&gt;&lt;/#assign&gt;
&lt;@otherDirective someParam=capturedOutput /&gt;</programlisting>
</answer>
</qandaentry>
<qandaentry xml:id="faq_questionmark">
<question>
<para>Why do I have <quote>?</quote>-s in the output instead of
character <replaceable>X</replaceable>?</para>
</question>
<answer>
<para>This is because the character that you want to print can't
be represented with the <link
linkend="gloss.charset">charset</link> (encoding) used for the
output stream, so the Java platform (not FreeMarker) substitutes
the problematic character with question mark. In general you
should use the same charset for the output as for the template
(use the <literal>getEncoding()</literal> method of the template
object), or which is even safer, you should always use UTF-8
charset for the output. The charset used for the output stream is
not decided by FreeMarker, but by you, when you create the
<literal>Writer</literal> that you pass to the
<literal>process</literal> method of the template.</para>
<para>Example: Here I use UTF-8 charset in a servlet:</para>
<programlisting role="unspecified">...
resp.setContentType("text/html; charset=utf-8");
Writer out = resp.getWriter();
...
t.process(root, out);
...</programlisting>
<para>Note that the question marks (or other substitution
characters) may be produced outside FreeMarker, in which case the
above obviously will not help. For example a bad/missconfigured
database connection or JDBC driver may bring the text already with
substitution characters in it. HTML forms are another potential
source of encoding problems. It's a good idea to print the
numerical code of the characters of the string on various places,
to see where the problem occurs first.</para>
<para>You can read more about charsets and FreeMarker <link
linkend="pgui_misc_charset">here...</link></para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_retrieve_calculated_values">
<question>
<para>How to retrieve values calculated in templates after
template execution done?</para>
</question>
<answer>
<para>First of all, be sure your application is designed well:
templates should display data, and almost never calculate data. If
you are still sure you want to do it, read on...</para>
<para>When you use <literal>&lt;#assign x = "foo"&gt;</literal>,
then you do not actually modify the data-model (since that is
read-only, see: <xref linkend="pgui_misc_multithreading"/>), but
create the <literal>x</literal> variable in the runtime <link
linkend="gloss.environment">environment</link> of the processing
(see <xref linkend="pgui_misc_var"/>). The problem is that this
runtime environment will be discarded when
<literal>Template.process</literal> returns, as it was created for
a single <literal>Template.process</literal> call:</para>
<programlisting role="unspecified">// internally an Environment will be created, and then discarded
myTemplate.process(root, out);</programlisting>
<para>To prevent this, you can do the below, which is equivalent
with the above, except that you have chance to return the
variables created in the template:</para>
<programlisting role="unspecified">Environment env = myTemplate.createProcessingEnvironment(root, out);
env.process(); // process the template
TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
</answer>
</qandaentry>
<qandaentry xml:id="faq_assign_to_dynamic_variable_name">
<question>
<para>How to assign to (or <literal>#import</literal> into) a
dynamically constructed variable name (like to name that's stored
in another variable)?</para>
</question>
<answer>
<para>If you really can't avoid doing that (you should, as it's
confusing), you can solve that with constructing the appropriate
FTL source code dynamically in a string, then using the <link
linkend="ref_builtin_interpret"><literal>interpret</literal>
built-in</link>. For example, if you want to assign to the
variable whose name is stored in the <literal>varName</literal>
variable:</para>
<programlisting role="template">&lt;@"&lt;#assign ${varName}='example'&gt;"?interpret /&gt;</programlisting>
</answer>
</qandaentry>
<qandaentry xml:id="faq_template_uploading_security">
<question>
<indexterm>
<primary>security</primary>
<secondary>user-provided templates</secondary>
</indexterm>
<para>Can I allow users to upload templates and what are the
security implications?</para>
</question>
<answer>
<para>In general you shouldn't allow that, unless those users are
application developers, system administrators, or other highly
trusted personnel. Consider templates as part of the source code
just like <literal>*.java</literal> files are. If you still want
to allow untrusted users to upload templates, here's what to
consider:</para>
<itemizedlist>
<listitem>
<para>Data-model and wrapping
(<literal>Configuration.setObjectWrapper</literal>): The
data-model might gives access to the public Java API of some
objects that you have put into the data-model. By default, for
objects that aren't instances of the bunch of specially
handled types (<literal>String</literal>,
<literal>Number</literal>, <literal>Boolean</literal>,
<literal>Date</literal>, <literal>Map</literal>,
<literal>List</literal>, array, and a few others), their
public Java API will be exposed, including most methods
inherited from standard Java classes
(<literal>getClass()</literal>, etc.). To avoid that, you have
to construct the data-model so that it only exposes the
members that are really necessary for the template. One
possibility is using <literal>SimpleObjectWrapper</literal>
(via <literal>Configuration.setObjectWrapper</literal> or the
<literal>object_wrapper</literal> setting) and then create the
data-model purely from <literal>Map</literal>-s,
<literal>List</literal>-s, <literal>Array</literal>-s,
<literal>String</literal>-s, <literal>Number</literal>-s,
<literal>Boolean</literal>-s and <literal>Date</literal>-s.
But for many applications that's too restrictive, and instead
you have to create a
<literal>WhitelistMemberAccessPolicy</literal>, and create a
<literal>DefaultObjectWrapper</literal> (or other
<literal>BeansWrapper</literal> subclass that you would use)
that uses that. See the Java API documentation of
<literal>WhitelistMemberAccessPolicy</literal> for more. (Or,
you can roll your own <literal>MemberAccessPolicy</literal>
implementation, or even your own restrictive
<literal>ObjectWrapper</literal> implementation of
course.)</para>
<para>Always expect that templates may get some objects that
you haven't put into the data-model yourself. Notably,
templates can always get a <literal>Locale</literal> object
with the <literal>.locale_object</literal> expression. Or the
web application framework you are using may exposes some
objects, like attributes from the Servlet scopes. Such objects
will be still wrapped with the
<literal>ObjectWrapper</literal> that you set in the
<literal>Configuration</literal>, and this is why it's
important to ensure safety on that level. Controlling what
objects the template will have access to is hard, but you can
control centrally what members of any object they have access
to.</para>
<para>If you are creating <literal>TemplateModel</literal>-s
in custom code (instead of the
<literal>ObjectWrapper</literal> creating those), be sure that
you avoid deprecated container constructors like <literal>new
SimpleSequence()</literal>, as those will use the also
deprecated default object wrapper instance, which doesn't have
the same restrictions than the
<literal>ObjectWrapper</literal> you have set on the
<literal>Configuration</literal>.</para>
<para>Also, don't forget about the <link
linkend="ref_buitin_api_and_has_api"><literal>?api</literal>
built-in</link>, if you have enabled it (it's disabled by
default). While the Java API of <literal>Map</literal>-s,
<literal>List</literal>-s and similar container-like objects
is not directly exposed by most
<literal>ObjectWrapper</literal>-s, so
<literal>someMap.someJavaMethod()</literal> won't work, using
<literal>?api</literal> the template author can still get to
the Java API-s of these objects, like
<literal>someMap?api.someJavaMethod()</literal>. But note that
the <literal>ObjectWrapper</literal> is still in control, as
it decides what objects support <literal>?api</literal>, and
what will <literal>?api</literal> expose for them (it usually
exposes the same as for a generic POJO). Members not allowed
by the <literal>MemberAccessPolicy</literal> also won't be
visible with <literal>?api</literal> (assuming you are using a
well behaving <literal>ObjectWrapper</literal>, like
<literal>DefaultObjectWrapper</literal>.)</para>
<para>If you are using the default object wrapper class
(<literal>freemarker.template.DefaultObjectWrapper</literal>),
or a subclass of it, you should disable the XML (DOM) wrapping
feature of it, by setting its
<literal>DOMNodeSupport</literal> property to
<literal>false</literal>. The problem with the XML wrapping
feature, which wraps <literal>org.w3c.dom.Node</literal>
objects on special way to make them easier to work with in
templates, is that this facility by design lets template
authors evaluate arbitrary XPath expressions, and XPath can do
too much in certain setups. If you really need the XML
wrapping facility, review carefully what XPath expressions are
possible in your setup. Also, be sure you don't use the long
deprecated, and more dangerous
<literal>freemarker.ext.xml</literal> package, only
<literal>freemarker.ext.dom</literal>. Also, note that when
using the XML wrapping feature, not allowing
<literal>org.w3c.dom.Node</literal> methods in the
<literal>MemberAccessPolicy</literal> has no effect, since it
doesn't expose Java <literal>Node</literal> members to
templates directly.</para>
<para>Last not least, some maybe aware of the historical
legacy that standard object wrappers filter out some well
known <quote>unsafe</quote> methods, like
<literal>System.exit</literal>. Do not ever rely on that,
since it only blocks the methods from a small predefined list.
The standard Java API is huge and ever growing, and then there
are the 3rd party libraries, and the API-s of your own
application. Clearly it's impossible to blacklist all the
problematic members in those.</para>
</listitem>
<listitem>
<para>Template-loader
(<literal>Configuration.setTemplateLoader</literal>):
Templates may load other templates by name (by path), like
<literal>&lt;#include "../secret.txt"&gt;</literal>. To avoid
loading sensitive data, you have to use a
<literal>TemplateLoader</literal> that double-checks that the
file to load is something that should be exposed. FreeMarker
tries to prevent the loading of files outside the template
root directory regardless of template loader, but depending on
the underlying storage mechanism, exploits may exist that
FreeMarker can't consider (like, just as an example,
<literal>~</literal> jumps to the current user's home
directory). Note that
<literal>freemarker.cache.FileTemplateLoader</literal> checks
the canonical paths, so that's maybe a good candidate for this
task, yet, adding a file extension check (file must be
<literal>*.ftl</literal>) is maybe a good idea.</para>
</listitem>
<listitem>
<para>The <literal>new</literal> built-in
(<literal>Configuration.setNewBuiltinClassResolver</literal>,
<literal>Environment.setNewBuiltinClassResolver</literal>):
It's used in templates like
<literal>"com.example.SomeClass"?new()</literal>, and is
important for FTL libraries that are partially implemented in
Java, but shouldn't be needed in normal templates. While
<literal>new</literal> will not instantiate classes that are
not <literal>TemplateModel</literal>-s, FreeMarker contains a
<literal>TemplateModel</literal> class that can be used to
create arbitrary Java objects. Other "dangerous"
<literal>TemplateModel</literal>-s can exist in you
class-path. Plus, even if a class doesn't implement
<literal>TemplateModel</literal>, its static initialization
will be run. To avoid these, you should use a
<literal>TemplateClassResolver</literal> that restricts the
accessible classes to the absolute minimum (possibly based on
which template asks for them), such as
<literal>TemplateClassResolver.ALLOWS_NOTHING_RESOLVER</literal>.
Do <emphasis>not</emphasis> use
<literal>TemplateClassResolver.SAFER_RESOLVER</literal>, it's
not restrictive enough for this purpose! Note that if, and
only if your <literal>ObjectWrapper</literal> is a
<literal>BeansWrapper</literal> or a subclass of it (typically
<literal>DefaultObjectWrapper</literal>), constructors not
allowed by the <literal>MemberAccessPolicy</literal> also
won't be accessible for <literal>?new</literal>.</para>
</listitem>
<listitem>
<para>Denial-of-Service (DoS) attacks: It's trivial to create
templates that run practically forever (with a loop), or
exhaust memory (by concatenating to a string in a loop).
FreeMarker can't enforce CPU or memory usage limits, so this
is something that has no solution on the
FreeMarker-level.</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_implement_function_or_macro_in_java">
<question>
<para>How to implement a function or macro in Java Language
instead of in the template language?</para>
</question>
<answer>
<para>It's not possible (yet), but something very similar is
possible if you write a class that implements
<literal>freemarker.template.TemplateMethodModelEx</literal> or
<literal>freemarker.template.TemplateDirectiveModel</literal>
respectively, and then where you were write <literal>&lt;#function
my
<replaceable>...</replaceable>&gt;<replaceable>...</replaceable>&lt;/#function&gt;</literal>
or <literal>&lt;#macro my
<replaceable>...</replaceable>&gt;<replaceable>...</replaceable>&lt;/#macro&gt;</literal>
you write <literal>&lt;#assign my = "your.package.YourClass
"?</literal><link
linkend="ref_builtin_new"><literal>new</literal></link><literal>()&gt;</literal>
instead. Note that using the <literal>assign</literal> directive
for this works because functions (and methods) and macros are just
plain variables in FreeMarker. (For the same reason you could also
put <literal>TemplateMethodModelEx</literal> or
<literal>TemplateDirectiveModel</literal> instances into the
data-model before calling the template, or into the shared
variable map (see:
<literal>freemarker.template.Configuration.setSharedVariable(String,
TemplateModel)</literal>) when you initialize the
application.)</para>
</answer>
</qandaentry>
<qandaentry xml:id="faq_nice_error_page">
<question>
<para><anchor xml:id="misc.faq.niceErrorPage"/> In my Servlet
based application, how do I show a nice error page instead of a
stack trace when error occurs during template processing?</para>
</question>
<answer>
<para>First of all, use <literal>RETHROW_HANDLER</literal> instead
of the default <literal>DEBUG_HANDLER</literal> (for more
information about template exception handlers <link
linkend="pgui_config_errorhandling">read this...</link>). Now
FreeMarker will not print anything to the output when an error
occurs, so the control is in your hands. After you have caught the
exception of
<literal>Template.process(<replaceable>...</replaceable>)</literal>
basically you can follow two strategies:</para>
<itemizedlist>
<listitem>
<para>Call <literal>httpResp.isCommitted()</literal>, and if
that returns <literal>false</literal>, then you call
<literal>httpResp.reset()</literal> and print a <quote>nice
error page</quote> for the visitor. If the return value was
<literal>true</literal>, then try to finish the page be
printing something that makes clear for the visitor that the
page generation was abruptly interrupted because of an error
on the Web server. You may have to print a lot of redundant
HTML end-tags and set colors and font size to ensure that the
error message will be actually readable in the browser window
(check the source code of the
<literal>HTML_DEBUG_HANDLER</literal> in
<literal>src\freemarker\template\TemplateException.java</literal>
to see an example).</para>
</listitem>
<listitem>
<para>Use full page buffering. This means that the
<literal>Writer</literal> doesn't send the output to the
client progressively, but buffers the whole page in the
memory. Since you provide the <literal>Writer</literal>
instance for the
<literal>Template.process(<replaceable>...</replaceable>)</literal>
method, this is your responsibility, FreeMarker has nothing to
do with it. For example, you may use a
<literal>StringWriter</literal>, and if
<literal>Template.process(<replaceable>...</replaceable>)</literal>
returns by throwing an exception, then ignore the content
accumulated by the <literal>StringWriter</literal>, and send
an error page instead, otherwise you print the content of
<literal>StringWriter</literal> to the output. With this
method you surely don't have to deal with partially sent
pages, but it can have negative performance implications
depending on the characteristic of the pages (for example, the
user will experience more response delay for a long page that
is generated slowly, also the server will consume more RAM).
Note that using a <literal>StringWriter</literal> is surely
not the most efficient solution, as it often reallocates its
buffer as the accumulated content grows.</para>
</listitem>
</itemizedlist>
</answer>
</qandaentry>
<qandaentry xml:id="faq_html_editor_mangles">
<question>
<para>I'm using a visual HTML editor that mangles template tags.
Will you change the template language syntax to accommodate my
editor?</para>
</question>
<answer>
<para>We won't change the standard version, because a lot of
templates depend on it.</para>
<para>Our view is that the editors that break template code are
themselves broken. A good editor should ignore, not mangle, what
it doesn't understand.</para>
<para>You maybe interested in that starting from FreeMarker 2.3.4
you can use <literal>[</literal> and <literal>]</literal> instead
of <literal>&lt;</literal> and <literal>&gt;</literal>. For more
details <link linkend="dgui_misc_alternativesyntax">read
this...</link></para>
</answer>
</qandaentry>
</qandaset>
</appendix>
<appendix xml:id="app_versions">
<title>Version history</title>
<section xml:id="versions_2_3_31">
<title>2.3.31</title>
<para>Release date: 2021-02-16</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Added <literal>?eval_json</literal> to evaluate JSON given
as flat string. This was added as <literal>?eval</literal> is
routinely misused for the same purpose, which not only doesn't
work for all JSON-s, but can be a security problem. <link
linkend="ref_builtin_eval_json">See more here...</link></para>
</listitem>
<listitem>
<para>Added new special variable, <literal>time_zone</literal>
(referred like <literal>.time_zone</literal>, like all special
variables), to retrieve the current value of the
<literal>time_zone</literal> setting as a string.</para>
</listitem>
<listitem>
<para>Allowed escaping <literal>#</literal> with backlash in
identifier names (not in string), as it used to occur in
database column names. Like if you have a column name like
<literal>#users</literal>, you can refer to it as
<literal>row.\#users</literal>. (Alternatively,
<literal>row['#users']</literal> always worked, but is often
less convenient.)</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/projects/FREEMARKER/issues/FREEMARKER-169">FREEMARKER-169</link>:
Fixed bug that made <literal>?c</literal> and
<quote>computer</quote> number format inconsistent. If <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incomplatible_improvements</literal></link>
is set to 2.3.31 (or higher), when you set the
<literal>number_format</literal> setting to
<literal>computer</literal> (or you call
<literal>Environment.getCNumberFormat()</literal>), the format
now matches the behavior of <literal>?c</literal>, when
formatting infinite (positive and negative), and NaN. Matching
the behavior of <literal>?c</literal> was always the intent, but
before this incompatible improvement, the
<literal>computer</literal> format always behaved like
<literal>?c</literal> before incompatible improvements 2.3.21,
where instead of <quote>INF</quote>, and <quote>NaN</quote>, the
results used Unicode characters U+221E, and U+FFFD.</para>
</listitem>
<listitem>
<para>Fixed bug where <literal>.globals</literal> weren't seen
as namesapce, so something like <literal>&lt;#assign
<replaceable>name</replaceable> =
<replaceable>value</replaceable> in .globals&gt;</literal>
failed (although you should use <literal>&lt;#global
<replaceable>name</replaceable> =
<replaceable>value</replaceable>&gt;</literal> instead
anyway).</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>More helpful parser error messages for nesting problems
(caused by missed or malformed end-tags usually).</para>
</listitem>
<listitem>
<para>Added <literal>DOMNodeSupport</literal> and
<literal>JythonSupport</literal> <literal>boolean</literal>
properties to <literal>DefaultObjectWrapper</literal>. This
allows disabling the special wrapping of DOM nodes and Jython
classes. This might be desirable <link
linkend="faq_template_uploading_security">for security
reasons</link>.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-145">FREEMARKER-145</link>:
Fixed bug where methods with "overloaded" return type may become
inaccessible on Java 9+, if some overriding subclasses are not
public. (This is because
<literal>java.beans.Introspector</literal> behavior has changed
with Java 9.)</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-133">FREEMARKER-133</link>:
Fixed bug where FreeMarker sometimes tries to expose public
methods that are defined or overridden in a non-public class, if
the non-public class was then extended by a public class.
Calling such method just ends up with
<literal>IllegalAccessException</literal>, but they shouldn't be
exposed on the first place. Furthermore, such a wrong method
sometimes replaces the good version of the method, which would
be callable. When this glitch happens is somewhat unpredictable,
as it also depends on what methods
<literal>java.beans.Introspector</literal> exposes (which at
very least can depend on the Java version), and in what
order.</para>
</listitem>
<listitem>
<para>Fixed bug where OSGi
<literal>Bundle-RequiredExecutionEnvironment</literal> in
<literal>META-INF/MANIFEST.FM</literal> has incorrectly
contained JavaSE-1.6, J2SE-1.5</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-159">FREEMARKER-159</link>:
Set <literal>Automatic-Module-Name</literal> to
<literal>freemarker</literal> in
<literal>META-INF/MANIFEST.FM</literal>. In most cases this was
the deduced Java 9 module name earlier, but that was fragile, as
Java has deduced it from the jar file name.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-165">FREEMARKER-165</link>:
Fixed bug where where if the namespace expression in a block
assignment (like <literal>&lt;#assign
<replaceable>x</replaceable> in
<replaceable>someNamespace</replaceable>&gt;<replaceable>...</replaceable>&lt;/#assign&gt;</literal>)
refers to a missing variable, or has the wrong type, FreeMarker
has thrown <literal>NullPointerException</literal> or
<literal>ClassCastException</literal>, instead of
<literal>InvalidReferenceException</literal> and
<literal>NonNamespaceException</literal> with proper helpful
message.</para>
</listitem>
<listitem>
<para>Build related changes:</para>
<itemizedlist>
<listitem>
<para>Simplified the way Apache Ivy is used in our Ant
build. It's now used on the standard way, there's no
<literal>ant update-deps</literal> anymore.</para>
</listitem>
<listitem>
<para>Test suite is now ran on ARM (64 bit) as well on CI
(Travis).</para>
</listitem>
<listitem>
<para>FreeMarker Manual and web site now works much better
on mobile, because of developments in the Docgen
project.</para>
</listitem>
<listitem>
<para>Docgen is now a Maven project, and so a plain Maven
dependency of the other projects (although, it's still only
in the Apache Snapshot Repository, not in Central yet). With
this we could get rid of our Ivy repository.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_30">
<title>2.3.30</title>
<para>Release date: 2020-03-05</para>
<para>Please note that with this version the minimum required Java
version was increased from Java 5 to Java 7.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-107">FREEMARKER-107</link>:
Added
<literal>?<replaceable>with_args</replaceable>(dynamicArguments)</literal>
and
<literal>?<replaceable>with_args_last</replaceable>(dynamicArguments)</literal>
to add parameters dynamically to directive (like macro),
function and method calls. Actually, this built-in returns a
directive or macro or function that has different parameter
defaults. <link linkend="ref_builtin_with_args">See more
here...</link></para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-107">FREEMARKER-107</link>:
Added new special variable, <link
linkend="specvar.args"><literal>.args</literal></link>. This
evaluates to a hash in macros, and to a sequence in functions,
which contains all the arguments. This is useful for operations
that act on all the arguments uniformly, like for example to
pass the arguments to <link
linkend="ref_builtin_with_args"><literal>?with_args(<replaceable>...</replaceable>)</literal></link>.</para>
</listitem>
<listitem>
<para><link linkend="ref.directive.macro">Macro catch-all
parameters</link> (aka. varargs parameters), when capture
arguments passed by name (as opposed to by position), now keep
the original order of arguments. Earlier the order wasn't
predictable.</para>
</listitem>
<listitem>
<para>Bug fixed: In <literal>&lt;#escape
<replaceable>placeholder</replaceable> as
<replaceable>escExpression</replaceable>&gt;</literal>, the
<literal><replaceable>placeholder</replaceable></literal> wasn't
substituted inside lambda expressions inside
<literal><replaceable>escExpression</replaceable></literal>.
Fortunately it's very unlikely that anyone wanted to use lambdas
there (given the few built-ins that accept lambdas).</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>The minimum required Java version was increased from Java
5 to Java 7.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-124">FREEMARKER-124</link>:
Made the default filtering of class members more restrictive
(when you are using <literal>BeansWrapper</literal>, or its
subclasses like <literal>DefaultObjectWrapper</literal>). This
is not strictly backward compatible, but unlikely to break any
real-world applications; see
<literal>src/main/resources/freemarker/ext/beans/DefaultMemberAccessPolicy-rules</literal>
to see what was changed. This change was made for security
reasons, but the default behavior will never be safe enough if
untrusted users will edit templates; see <link
linkend="faq_template_uploading_security">in the FAQ</link>. In
the unlikely case this change breaks your application, then you
can still use the old behavior by setting the
<literal>memberAccessPolicy</literal> property of the object
wrapper to
<literal>LegacyDefaultMemberAccessPolicy.INSTANCE</literal>.</para>
</listitem>
<listitem>
<para>Added
<literal>freemarker.ext.beans.MemberAccessPolicy</literal>
interface, and the <literal>memberAccessPolicy</literal>
property to <literal>BeansWrapper</literal>, and subclasses like
<literal>DefaultObjectWrapper</literal>. This allows users to
implement their own program logic to decide what members of
classes will be exposed to the templates. See See the <olink
targetdoc="api">FreeMarker Java API documentation</olink> for
more details.</para>
</listitem>
<listitem>
<para>Added
<literal>freemarker.ext.beans.WhitelistMemberAccessPolicy</literal>,
which is a <literal>MemberAccessPolicy</literal> for use cases
where you want to allow editing templates to users who shouldn't
have the same rights as the developers (the same rights as the
Java application). Earlier, the only out of the box solution for
that was <literal>SimpleObjectWrapper</literal>, but that's too
restrictive for most applications where FreeMarker is used.
<literal>WhitelistMemberAccessPolicy</literal> works with
<literal>DefaultObjectWrapper</literal> (or any other
<literal>BeansWrapper</literal>), allowing you to use all
features of it, but it will only allow accessing members that
were explicitly listed by the developers, or was annotated with
<literal>@TemplateAccessible</literal>.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-125">FREEMARKER-125</link>:
FreeMarker now picks up <literal>DecimalFormatSymbols</literal>
provided by the <literal>DecimalFormatSymbolsProvider</literal>
SPI. This is useful if you need to change the decimal format
symbols provided for a locale by Java.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-120">FREEMARKER-120</link>:
<literal>BeansWrapper</literal> (and it's subclasses like
<literal>DefaultObjectWrapper</literal>) now has two protected
methods that can be overridden to monitor the accessing of
members: <literal>invokeMethod</literal> and
<literal>readField</literal>.</para>
</listitem>
<listitem>
<para>Setting <literal>incompatibleImprovements</literal> to the
instance returned by
<literal>Configuration.getVersion()</literal> will now be logged
as an error, but for backward compatibility it will still work.
This applies to said setting of
<literal>Configuration</literal>,
<literal>DefaultObjectWrapper</literal>, and
<literal>BeansWrapper</literal>. The typical bad pattern is
this: <literal>new
Configuration(Configuration.getVersion())</literal>. Doing that
defeats the purpose of
<literal>incompatibleImprovements</literal>, and makes upgrading
FreeMarker a potentially breaking change. Furthermore, doing
this probably won't be allowed starting from 2.4.0, and will
throw exception. So if above mistake is present in your
application, it should be fixed by setting
<literal>incompatibleImprovements</literal> to the highest
concrete version that's known to be compatible with the
application.</para>
</listitem>
<listitem>
<para>Added
<literal>Environment.getDataModelOrSharedVariable(String)</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed: AST traversal API now can properly traverse the
inside of lambda expressions (such as the parameter list)</para>
</listitem>
<listitem>
<para>Added a new <literal>SimpleHash</literal> constructor,
where the caller can provide the <literal>Map</literal> instance
used as the backing storage, thus allows controlling the
ordering, and other technical aspects (like the initial
capacity) of it.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_29">
<title>2.3.29</title>
<para>Release date: 2019-08-17</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Added new built-ins: <link
linkend="ref_builtin_filter"><literal>?filter(<replaceable>predicate</replaceable>)</literal></link>,
<link
linkend="ref_builtin_map"><literal>?map(<replaceable>mapper</replaceable>)</literal></link>,
<link
linkend="ref_builtin_take_while"><literal>?take_while(<replaceable>predicate</replaceable>)</literal></link>,
<link
linkend="ref_builtin_drop_while"><literal>?drop_while(<replaceable>predicate</replaceable>)</literal></link>.
These allow using lambda expressions, like
<literal>users?filter(user -&gt; user.superuser)</literal> or
<literal>users?map(user -&gt; user.name)</literal>, or accept a
function/method as parameter. Lambda expressions are also new in
this release, but they can only be used in said built-ins, so
they aren't like in Java for example, and also, unlike the
similar Java methods, these built-ins aren't lazy in general,
only in specific cases (see more <link
linkend="topic.filterLazyEval">here</link>). The main goal of
adding these built-ins was to allow conditionally skipping
elements in the <literal>list</literal> directive without nested
<literal>if</literal>-s that interfere with the <link
linkend="ref.directive.sep"><literal>sep</literal>
directive</link>, and the <link
linkend="ref_builtins_loop_var">loop variable built-ins</link>
(see examples <link
linkend="ref_list_skipping">here</link>).</para>
</listitem>
<listitem>
<para>Added new built-ins for truncating text.
<literal><replaceable>string</replaceable>?truncate(<replaceable>length</replaceable>)</literal>
truncates the text to the given length, and by default adds
<literal>[...]</literal> at the end if truncation has happened.
Truncation happens at word boundaries, unless the result is too
short that way, in which case it falls back to truncation mid
word. There's also <literal>?truncate_w</literal> to force Word
Boundary truncation, and <literal>?truncate_c</literal> (for
Character Boundary) that doesn't care about word boundaries. The
truncation algorithm is pluggable in the FreeMarker
configuration. See <link linkend="ref_builtin_truncate">the
reference</link> for more details.</para>
</listitem>
<listitem>
<para><link
linkend="ref_builtin_sequence"><literal>?sequence</literal></link>
now collaborates with
<literal><replaceable>seq</replaceable>?size</literal>,
<literal><replaceable>seq</replaceable>[<replaceable>index</replaceable>]</literal>,
<literal><replaceable>seq</replaceable>[<replaceable>range</replaceable>]</literal>,
and with some other built-ins (<literal>filter</literal>,
<literal>map</literal>, <literal>join</literal>, etc.) to spare
collecting all the elements into the memory when possible. For
example <literal>anIterator?sequence[1]</literal> will now just
fetch the first 2 items, while earlier it has built a sequence
that contains all the elements, only to get the 2nd element from
that. Or, <literal>anIterator?sequence?size</literal> will now
just count the elements, without collecting them into the
memory. See <link
linkend="ref_builtin_sequence_optimizations">the
reference</link> for more details.</para>
</listitem>
<listitem>
<para><link linkend="topic.extendedJavaDecimalFormat">Extended
decimal format</link> parameter <quote>multiplier</quote> was
incorrectly written as <quote>multipier</quote>. Now both words
are recognized.</para>
</listitem>
<listitem>
<para><literal>?min</literal> and <literal>?max</literal> will
now immediately stop with error when applied on a right
unbounded numerical range (like <literal>1..</literal>), as that
would run forever anyway.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-109">FREEMARKER-109</link>:
In JSP TLD-s, line breaks inside function parameter lists have
caused <literal>IllegalArgumentException</literal>
<quote>Invalid function signature</quote>.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-104">FREEMARKER-104</link>:
More helpful log and error messages (especially, no
<literal>NullPointerException</literal> cause exception logged
during FreeMarker XPath support initialization) if no XPath
implementation is available because Java 9 modules don't allow
accessing the internal Xalan that's stored under
<literal>com.sun</literal> packages. (The messages now recommend
adding Apache Xalan or Jaxen as dependency if you need XPath
support.)</para>
</listitem>
<listitem>
<para>The <literal>boolean_format</literal> configuration
setting now can be set to <literal>"c"</literal>. Then
<literal>${<replaceable>aBoolean</replaceable>}</literal> will
behave as
<literal>${<replaceable>aBoolean</replaceable>?c}</literal>.
This should only be used if you are generating output for
non-human (computer) consumption only. If your output has pieces
for human audience too, it's still recommended to use
<literal>${<replaceable>aBoolean</replaceable>?c}</literal>
where <literal>true</literal>/<literal>false</literal> output is
needed, and either not set the <literal>boolean_format</literal>
at all, or set it to something that's appropriate for everyday
users (like <literal>"yes,no"</literal>).</para>
</listitem>
<listitem>
<para>New configuration setting,
<literal>fallback_on_null_loop_variable</literal>: Specifies the
behavior when reading a loop variable (like <literal>i</literal>
in <literal>&lt;#list items as i&gt;</literal>, or in
<literal>&lt;@myMacro items; i&gt;</literal>) that's
<literal>null</literal> (missing); if <literal>true</literal>,
FreeMarker will look for a variable with the same name in higher
variable scopes, or if <literal>false</literal> the variable
will be simply <literal>null</literal> (missing). For backward
compatibility the default is <literal>true</literal>. The
recommended value for new projects is <literal>false</literal>,
as otherwise adding new variables to higher scopes (typically to
the data-model) can unintentionally change the behavior of
templates.</para>
</listitem>
<listitem>
<para>If the result of
<literal><replaceable>seq</replaceable>?size</literal> is
compared to an integer <emphasis>literal</emphasis> in a
template, like in <literal><replaceable>seq</replaceable>?size
!= 0</literal>, or <literal><replaceable>seq</replaceable>?size
&lt; 1</literal>, and to decide the answer it's enough to know
if <literal><replaceable>seq</replaceable></literal> is empty or
not (i.e., the exact size isn't needed), and
<literal><replaceable>seq</replaceable></literal> implements
<literal>TemplateCollectionModelEx</literal>, FreeMarker will
call <literal>TemplateCollectionModelEx.isEmpty()</literal>
instead of <literal>size()</literal>. Furthermore, if
<literal><replaceable>seq</replaceable></literal> is the result
of <literal>?filter</literal>, or of a similar built-ins that
can provide lazily generated result, it will do counting to
figure out the size (rather than constructing the whole sequence
in memory), and will limit how far it counts based on what
literal the result of <literal>?size</literal> is compared
with.</para>
</listitem>
<listitem>
<para>Added
<literal>TemplateModelUtils.wrapAsHashUnion(ObjectWrapper,
List&lt;?&gt;)</literal> and
<literal>wrapAsHashUnion(ObjectWrapper, Object...)</literal>,
which is useful when you want to compose the data-model from
multiple objects in a way so that their entries
(<literal>Map</literal> key-value pairs, bean properties, etc.)
appear together on the top level of the data-model.</para>
</listitem>
<listitem>
<para><literal>HTMLOutputFormat</literal>,
<literal>XMLOutputFormat</literal>,
<literal>XHTMLOutputFormat</literal> aren't final classes
anymore, furthermore <literal>XHTMLOutputFormat</literal> now
extends <literal>XMLOutputFormat</literal>. Same applies to the
respective <literal>TemplateOutputModel</literal>-s
(<literal>TemplateHTMLOutputModel</literal> is not final
anymore, etc.). This allows defining new custom markup output
format classes that will work with program logic that's only
prepared for the standard markup output formats, because
<literal>instanceof
<replaceable>SomeStandardOutputFromat</replaceable></literal>
will return <literal>true</literal> for them.</para>
</listitem>
<listitem>
<para>When configuring FreeMarker with string values (like with
a <literal>.properties</literal> file), in the settings that
support the <quote>object builder</quote> syntax, now you can
create a <literal>TemplateMarkupOutputModel</literal> value with
the new <literal>markup</literal> function, like
<literal>markup(HTMLOutputFormat(),
"&lt;p&gt;Example&lt;/p&gt;")</literal>.</para>
</listitem>
<listitem>
<para><literal>BeansWrapper.clearClassIntrospecitonCache</literal>
was deprecated as there's a typo in the method name; use
<literal>clearClassIntrospectionCache</literal> instead.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_28">
<title>2.3.28</title>
<para>Release date: 2018-04-04</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Added new <link linkend="ref_specvar">special
variable</link>, <literal>get_optional_template</literal> (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-84">FREEMARKER-84</link>).
It can be used when you need to include or import a template
that's possibly missing, and you need to handle that case on
some special way. <link
linkend="ref_specvar_get_optional_template">See the details
here...</link></para>
</listitem>
<listitem>
<para>Added new <link linkend="ref_specvar">special
variable</link>, <literal>caller_template_name</literal> (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-83">FREEMARKER-83</link>),
which returns the name (path) of the template from which the
current macro or function was called. It's mostly useful if you
want to resolve paths relative to the caller template.</para>
</listitem>
<listitem>
<para>Added new built-in,
<literal><replaceable>templateName</replaceable>?absolute_template_name</literal>
or
<literal><replaceable>templateName</replaceable>?absolute_template_name(<replaceable>baseName</replaceable>)</literal>,
which can be used to convert a relative template name to an
absolute template name. <link
linkend="ref_builtin_absolute_template_name">See more
here...</link></para>
</listitem>
<listitem>
<para>Added new built-ins:
<literal><replaceable>sequence</replaceable>?min</literal> and
<literal><replaceable>sequence</replaceable>?max</literal>
(<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-86">FREEMARKER-86</link>),
which return the smallest and greatest item from a list of
numbers or date/time/date-times. <link
linkend="ref_builtin_min_max">See more here...</link></para>
</listitem>
<listitem>
<para>The template language can now be configured to use
<literal>[=<replaceable>expression</replaceable>]</literal>
instead of
<literal>${<replaceable>expression</replaceable>}</literal> and
<literal>#{<replaceable>expression</replaceable>}</literal>,
which is very useful if you have a lot of
<literal>${<replaceable>...</replaceable>}</literal> or
<literal>#{<replaceable>...</replaceable>}</literal> in the text
that you are generating, and so they should be static text. See
<link linkend="dgui_misc_alternativesyntax_interpolation">more
about the square bracket interpolation syntax here.</link> The
template language can also be configured to only use
<literal>${<replaceable>expression</replaceable>}</literal>, and
treat
<literal>#{<replaceable>expression</replaceable>}</literal> as
static text. (See the <literal>interpolation_syntax</literal>
configuration setting, or the
<literal>Configuration.setInterpolationSyntax(int)</literal>
method.)</para>
</listitem>
<listitem>
<para>In string literals, <literal>\=</literal> is now a valid
escape sequence, resulting in a <literal>=</literal>. This is
useful when you are using the new
<literal>[=<replaceable>exp</replaceable>]</literal>
interpolation syntax, which can be escaped in a string literal
like <literal>"Literal [\=x]"</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-83">FREEMARKER-83</link>);
this fix is only active when <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incomplatible_improvements</literal></link>
is set to 2.3.28 (or higher). When calling a macro or function
(things defined in a template, not directly in Java) and the
argument list contains
<literal>.current_template_name</literal>, now it will correctly
evaluate to the template that contains the call, rather than to
the template that contains the macro or function definition. (Of
course, the parameter default value expression is still
evaluated in the context of the called macro or
function.)</para>
</listitem>
<listitem>
<para>Bug fixed: When
<literal><replaceable>string</replaceable>?split(<replaceable>separator</replaceable>)</literal>
is called with <literal>""</literal> as the argument, the string
will be split to characters now. Earlier it has thrown an
<literal>IllegalArgumentException</literal> (unless the
<literal>r</literal> flag was specified).</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Added new <literal>ParserConfiguration</literal> (such as
<literal>Configuration</literal> and
<literal>TemplateConfiguration</literal>) setting,
<literal>interpolation_syntax</literal>. It has 3 possible
values:</para>
<itemizedlist>
<listitem>
<para><literal>legacy</literal> (the default):
Interpolations look like
<literal>${<replaceable>...</replaceable>}</literal> or
<literal>#{<replaceable>...</replaceable>}</literal>. Note
that <literal>#{<replaceable>...</replaceable>}</literal> is
deprecated for a long time now.</para>
</listitem>
<listitem>
<para><literal>dollar</literal>: Interpolations look like
<literal>${<replaceable>...</replaceable>}</literal>. With
this syntax,
<literal>#{<replaceable>...</replaceable>}</literal> will be
just static text.</para>
</listitem>
<listitem>
<para><literal>square_bracket</literal>: Interpolations look
like <literal>[=<replaceable>...</replaceable>]</literal>.
With this syntax
<literal>${<replaceable>...</replaceable>}</literal> and
<literal>#{<replaceable>...</replaceable>}</literal> will be
just static text. So it's useful if you generate output in a
format where those (typically
<literal>${<replaceable>...</replaceable>}</literal>) are
already used, such as to generate JSP pages, or to generate
FreeMarker templates that use the default syntax.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>When specifying the <literal>output_format</literal>
configuration setting with
<literal>String</literal>-<literal>String</literal> key-value
pairs (like with <literal>Configuration.setSetting(String,
String)</literal> or in a <literal>.properties</literal> file),
it's now possible to specify the standard output formats by
short name (like <literal>output_format=HTML</literal>) rather
than by class name. (Custom formats still has to be referred by
class name, as FreeMarker can't discover what their names are,
since it's not aware of the custom classes.)</para>
</listitem>
<listitem>
<para>Added a new
<literal>Configuration.removeTemplateFromCache</literal>
overload that has a <literal>Object
customLookupCondition</literal> parameter. This is useful to
manually evacuate a template from the cache that was get with a
non-<literal>null</literal> custom lookup condition.</para>
</listitem>
<listitem>
<para>Added new property to
<literal>BeansWrapper.MethodAppearanceDecision</literal>:
<literal>replaceExistingProperty</literal>. This is useful when
a method like <literal>size()</literal> is exposed as a JavaBean
property via
<literal>MethodAppearanceDecision.exposeAsProperty</literal>,
but there's also a <quote>real</quote> JavaBean property (like
<literal>getSize()</literal>) with identical name. By default
the real property isn't replaced, but now with
<literal>replaceExistingProperty</literal> it can be.</para>
</listitem>
<listitem>
<para><literal>DirectiveCallPlace</literal> now has a
<literal>Template getTemplate()</literal> method, so you can
query if from which template was your
<literal>TemplateDirectiveModel</literal> called. (This has
similar role as <literal>.caller_template_name</literal> for
macros/functions.)</para>
</listitem>
<listitem>
<para>Added
<literal>Environment.rootBasedToAbsoluteTemplateName(String)</literal>,
which converts the root based names typically used for the
FreeMarker Java API-s (such as
<literal>Configuration.getTemplate(name)</literal>) to an
absolute path, which can be safely passed to
<literal>&lt;#include
<replaceable>path</replaceable>&gt;</literal> and such, as it
won't be misinterpreted to be relative to the directory of the
template.</para>
</listitem>
<listitem>
<para>Fixes in exception handling when calling JSP tags:</para>
<itemizedlist>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-88">FREEMARKER-88</link>):
If a <literal>TemplateException</literal> that's not a
<literal>TemplateModelExceptoin</literal> has occurred in
the body (nested content) of a JSP
<literal>SimpleTag</literal> (typically, an
<literal>InvalidReferenceException</literal>), that has
caused a <literal>ClassCastException</literal> in the
exception handling code, thus the template processing has
thrown that instead of the original exception.</para>
</listitem>
<listitem>
<para>Bug fixed: For JSP Tag based custom tags, if an
exception has occurred in the body (nested content), an
<literal>IndexOutOfBoundsException</literal> might have
occurred, replacing the original exception.</para>
</listitem>
<listitem>
<para>Wrapping of
non-<literal>TemplateModelException</literal>
<literal>TemplateException</literal>-s (typically
<literal>InvalidReferenceException</literal>-s) into
<literal>TemplateModelException</literal>-s is now avoided
when the <literal>TemplateException</literal> occurs in the
body of a JSP tag.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>The default arithmetic engine
(<literal>ArithmeticEngine.BIGDECIMAL_ENGINE</literal>) can now
compare infinite (both positive and negative) to any other
standard numerical type. Earlier, since
<literal>BigDecimal</literal> can't represent infinite, it was
only working in certain special cases. Also there were some
performance optimizations to slightly decrease the impact and
number of conversions to <literal>BigDecimal</literal>.</para>
</listitem>
<listitem>
<para>Avoided possible performance bottleneck when executing
templates on many threads, caused by that
<literal>java.beans.PropertyDescriptor.getReadMethod()</literal>
is synchronized (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-80">FREEMARKER-80</link>).</para>
</listitem>
<listitem>
<para>Added
<literal>TemplateModelUtils.getKeyValuePairIterator(TemplateHashModelEx)</literal>
static utility class, which can be used to get a
<literal>TemplateHashModelEx2.KeyValuePairIterator</literal>
even for a non-<literal>TemplateHashModelEx2</literal> object.
This simplifies Java code that iterates through key-value
pairs.</para>
</listitem>
<listitem>
<para><literal>freemarker.template.utility.DeepUnwrap</literal>
(a rarely used utility) now utilizes when the unwrapped
<literal>TemplateModel</literal> implements
<literal>TemplateHashModelEx2.getKeyValuePairIterator()</literal>,
and thus can unwrap such a hash value even if it has non-string
keys. Also, it nows keeps the iteration order of the hashes, as
it unwraps into a <literal>LinkedHashMap</literal> instead of
into a plain <literal>HashMap</literal>.</para>
</listitem>
<listitem>
<para><literal>freemarker.ext.beans.HashAdapter.size()</literal>
was overridden for better performance.</para>
</listitem>
<listitem>
<para>When the <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incompatible_improvements</literal>
setting</link> is set to 2.3.28 (or greater): Fixed legacy
parser glitch where a tag can be closed with an illegal
<literal>]</literal> (when it's not part of an expression)
despite that the tag syntax is set to angle brackets. For
example <literal>&lt;#if x]</literal> worked just like
<literal>&lt;#if x&gt;</literal>. Note that this legacy glitch
didn't affect the legal usage of <literal>]</literal>, like
<literal>&lt;#if x[0]&gt;</literal> has always worked
correctly.</para>
</listitem>
<listitem>
<para>Fixed parser bug that disallowed using
<literal>&gt;</literal> as the top-level expression inside an
interpolation (<literal>${...}</literal>). It had the same
reason why <literal>&lt;#if x &gt; y&gt;</literal> doesn't work
as naively expected, but there's no real ambiguity in
<literal>${x &gt; y}</literal>, so now it's allowed. Note that
<literal>${(x &gt; y)?c}</literal> and <literal>${(x &gt;
y)?string('y', 'n')}</literal>, which are how booleans are
commonly printed, have always worked, as the
<literal>&gt;</literal> operation is not on the top-level inside
the interpolation.</para>
</listitem>
<listitem>
<para>Fixed incorrect listing of valid
<literal>roundingMode</literal>-s in <link
linkend="topic.extendedJavaDecimalFormat">extended Java decimal
format</link> parsing error message</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>FreeMarker has graduated from the Apache Incubator (as of
2018-03-21), and now is a normal top-level project at Apache.
Therefore, the version number doesn't contain
<quote>-incubating</quote> anymore.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_27">
<title>2.3.27 (incubating at Apache)</title>
<para>Release date: 2017-11-03</para>
<para><emphasis role="bold">This is a stable, final
release.</emphasis> The <quote>incubating</quote> suffix is required
by the Apache Software Foundation until the project becomes a fully
accepted (graduated) Apache project.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New directive: <literal>continue</literal> (<link
xlink:href="https://sourceforge.net/p/freemarker/feature-requests/79/">sf.net
#79</link>, <link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-37">FREEMARKER-37</link>).
This can be used inside the <literal>list</literal> directive to
skip to the next iteration (similarly as in Java). <link
linkend="ref.directive.list.continue">See more...</link></para>
</listitem>
<listitem>
<para>Added alternative syntaxes for the
<literal>&amp;&amp;</literal> (logical <quote>and</quote>)
operator: <literal>\and</literal> and
<literal>&amp;amp;&amp;amp;</literal>. These are to work around
issues in applications where the template must be valid XML
(<literal>&amp;&amp;</literal> is not valid XML/HTML, at most
places), or where the template entered is stored after XML or
HTML escaping. Note that lonely <literal>&amp;amp;</literal>,
and <literal>and</literal> without <literal>\</literal> is not
recognized for backward compatibility.</para>
</listitem>
<listitem>
<para>New built-in, <literal>sequence</literal> (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-73">FREEMARKER-73</link>).
This can be used to work around situations where a listable
value lacks some features that you need in the template (like it
can't be listed twice, it can't tell its size, etc.), and you
can't modify the data-model to fix the problem. <link
linkend="ref_builtin_sequence">See more...</link></para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-70">FREEMARKER-70</link>):
The usage of loop variable built-ins, like
<literal><replaceable>loopVar</replaceable>?index</literal>, was
disallowed by the parser inside interpolations that are inside a
string literal expression (as in <literal>&lt;#list 1..3 as
loopVar&gt;${'${loopVar?index}'}&lt;/#list&gt;</literal>),
saying that there's no loop variable in scope with
<literal><replaceable>loopVar</replaceable></literal>
name.</para>
</listitem>
<listitem>
<para>Bug fixed: Comments were not allowed by the parser between
the <literal>switch</literal> tag and the first
<literal>case</literal> tag.</para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-71">FREEMARKER-71</link>):
When using
<literal><replaceable>exp</replaceable>?eval</literal>, if the
expression inside the evaluated string throws an exception, the
cause exception of that exception was lost.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Added new configuration setting (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-48">FREEMARKER-48</link>),
<literal>wrap_unchecked_exceptions</literal>
(<literal>Configurable.setWrapUncheckedExceptions(boolean)</literal>).
When this is <literal>true</literal>, unchecked exceptions
thrown during evaluating an expression or during executing a
custom directive will be wrapped into a
<literal>TemplateException</literal>-s. The advantage of that is
that thus the exception will include the location in the
template (not just the Java stack trace), and the
<literal>TemplateExceptionHandler</literal> will be invoked for
it as well. When this setting is <literal>false</literal> (which
is the default for backward compatibility), the the unchecked
exception will bubble up and thrown by
<literal>Template.process</literal>, just as in earlier
versions. (Note that plain Java methods called from templates
have always wrapped the thrown exception into
<literal>TemplateException</literal>, regardless of this
setting.)</para>
</listitem>
<listitem>
<para>Added new configuration setting,
<literal>attempt_exception_reporter</literal>
(<literal>Configurable.setAttemptExceptionReporter(AttemptExceptionReporter)</literal>),
to allow the customization of how the exceptions handled (and
thus suppressed) by the <link
linkend="ref.directive.attempt"><literal>attempt</literal>
directive</link> are reported. The default
<literal>AttemptExceptionReporter</literal> logs the exception
as an error, just as it was in earlier versions, though now the
error message will indicate that the exception was thrown inside
an <literal>attempt</literal> directive block.</para>
</listitem>
<listitem>
<para>Added new <literal>BeansWrapper</literal> setting,
<literal>preferIndexedReadMethod</literal>. This was added to
address a Java 8 compatibility problem; see the bug fix entry
below for more information.</para>
</listitem>
<listitem>
<para>When <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incomplatible_improvements</literal></link>
is set to 2.3.27 (or higher), the following unchecked exceptions
(but not their subclasses) will be wrapped into
<literal>TemplateException</literal>-s when thrown during
evaluating expressions or calling directives:
<literal>NullPointerException</literal>,
<literal>ClassCastException</literal>,
<literal>IndexOutOfBoundsException</literal>, and
<literal>InvocationTargetException</literal>. The goal of this
is the same as of setting the
<literal>wrap_unchecked_exceptions</literal> setting to
<literal>true</literal> (see that earlier), but this is more
backward compatible, as it avoids wrapping unchecked exceptions
that some application is likely to catch specifically (like
application-specific unchecked exceptions). (This is related to
<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-48">FREEMARKER-48</link>.)</para>
</listitem>
<listitem>
<para>Bug fixed: Starting from Java 8, when the same JavaBeans
property has both non-indexed read method (like
<literal>String[] getFoos()</literal>) and indexed read method
(like <literal>String getFoos(int index)</literal>),
<literal>BeansWrapper</literal> and
<literal>DefaultObjectWrapper</literal> have mistakenly used the
indexed read method to access the property. This is a problem
because then the array size was unknown, and thus the property
has suddenly become unlistable on Java 8 (that is,
<literal>&lt;#list myObject.foos as foo&gt;</literal> fails). To
enable the fix (where it will use the non-indexed read method),
you should increase the value of the
<literal>incompatibleImprovements</literal> constructor argument
of the used <literal>DefaultObjectWrapper</literal> or
<literal>BeansWrapper</literal> to 2.3.27. Note that if you
leave the <literal>object_wrapper</literal> setting of the
<literal>Configuration</literal> on its default, it's enough to
increase the <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incompatibleImprovements</literal>
setting</link> of the <literal>Configuration</literal> to
2.3.27, as that's inherited by the default
<literal>object_wrapper</literal>. In case increasing the
<literal>incompatibleImprovements</literal> is not an option
(because of the other changes it brings), you can instead set
the <literal>preferIndexedReadMethod</literal> property of the
object wrapper to <literal>false</literal>. Note that this bug
haven't surfaced before Java 8, as then
<literal>java.beans.Inrospector</literal> has only exposed the
non-indexed method when both kind of read method was
present.</para>
</listitem>
<listitem>
<para>Bug fixed (affects Java 8 and later): Regardless of the
value of the <literal>preferIndexedReadMethod</literal> setting
(see previous point), if one of the indexed read method and the
non-indexed read method is inaccessible (i.e., it's declared in
a non-public type, and wasn't inherited by a public type), while
the other read method is accessible, we will use the accessible
one. Earlier, if there was an indexed read method but it was
inaccessible, we have given up, and that bean property wasn't
visible. Such properties will now be visible again, just as
before Java 8. (Before Java 8
<literal>java.beans.Inrospector</literal> has only exposed the
non-indexed read method in this case, so we didn't have this
problem.)</para>
</listitem>
<listitem>
<para>Bug fixed: On OpenJDK 9 (but not on earlier versions, nor
on Oracle Java 9 (tested with <quote>build 9+181</quote>)), when
you try to use the DOM-based XML support
(<literal>freemarker.ext.dom.NodeModel</literal>), unless you
happen to have Apache Xalan in the class path, the
<literal>NodeModel</literal> constructor will fail with
<literal>IllegalAccessError</literal> because <quote>java.xml
does not export com.sun.org.apache.xml.internal.utils</quote>.
Note that while the exception is not thrown anymore in 2.3.27,
FreeMarker can't use the XPath support included in OpenJDK 9,
and so templates that try to use XPath expressions (like
<literal>doc['//foo']</literal>) will still fail, <link
linkend="xgui_imperative_learn_xpath">unless 3rd party XPath
support is present</link>.</para>
</listitem>
<listitem>
<para>Bug fixed: When the
<literal>TemplateExceptionHandler</literal> suppresses (i.e.,
doesn't re-throw) an exception, the <link
linkend="ref.directive.attempt"><literal>attempt</literal>
directive</link> won't log it anymore. (To be precise, the
<literal>AttemptExceptionReporter</literal> won't be invoked for
it anymore; the default one logs as error.)</para>
</listitem>
<listitem>
<para>Bug fixed (part of <link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-48">FREEMARKER-48</link>):
When an arithmetic exception has occurred in an expression
(typically division by zero), the template processing has thrown
the <literal>ArithmeticException</literal> as is, without
packaging it into a <literal>TemplateException</literal>. Thus,
the error location in the template wasn't visible in the
exception.</para>
</listitem>
<listitem>
<para>When logging error due to an error in an <link
linkend="ref.directive.attempt"><literal>attempt</literal>
directive</link> block, the log message now indicates that the
error was inside an <literal>attempt</literal> block.</para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-52">FREEMARKER-52</link>):
When setting the <literal>output_format</literal> from
<literal>Properties</literal> or the <literal>setSetting(String,
String)</literal> API, the <literal>XHTMLOutputFormat</literal>
abbreviation wasn't recognized (for example in a
<literal>.properties</literal> file,
<literal>output_format=XHTMLOutputFormat</literal> didn't work,
only
<literal>output_format=freemarker.core.XHTMLOutputFormat()</literal>
did).</para>
</listitem>
<listitem>
<para>Bug fixed: When setting the
<literal>new_builtin_resolver</literal> from
<literal>Properties</literal> or the <literal>setSetting(String,
String)</literal> API, it didn't recognize the camel case form
of the <literal>allowed_classes</literal> and
<literal>trusted_templates</literal> keywords, and throw
exception for them. Now <literal>allowedClasses</literal> and
<literal>trustedTemplates</literal> can be used as well.</para>
</listitem>
<listitem>
<para>Bug fixed: JSP support haven't tried using the thread
context class-loader to load the TLD, instead, it has only used
the defining class loader of the FreeMarker classes. This can
cause problem in the rare case where
<literal>freemarker.jar</literal> is installed on higher scope
than the web application (like on the Servlet container level),
but the web application contains the TLD.</para>
</listitem>
<listitem>
<para><literal>Constants.EMPTY_HASH</literal> and
<literal>GeneralPurposeNothing</literal> (the value of
<literal>missingVar!</literal>) now implements
<literal>TemplateHashModelEx2</literal>. Earlier they were only
a <literal>TemplateHashModelEx</literal>-s.</para>
</listitem>
<listitem>
<para>Added
<literal>Constants.EMPTY_KEY_VALUE_PAIR_ITERATOR</literal></para>
</listitem>
<listitem>
<para>Somewhat less synchronization when accessing JavaBean
properties (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-80">FREEMARKER-80</link>).
The problem was that the
<literal>java.beans.PropertyDescriptor.getReadMethod</literal>
method is synchronized, and
<literal>freemarer.ext.beans.BeanModel</literal> has called it
each time a property was read. Now that method is only called
when the class is first introspected.</para>
</listitem>
<listitem>
<para>Improved/fixed <literal>TemplateTransformModel</literal>
behavior (this is a legacy interface that's not used much in
user code):</para>
<itemizedlist>
<listitem>
<para><literal>Writer
TemplateTransformModel.getWriter(Writer out, Map
args)</literal> can now return the <literal>out</literal>
parameter as is, as FreeMarker now recognizes that it's the
same object and so won't call <literal>close()</literal> on
it after the end tag.</para>
</listitem>
<listitem>
<para>When <link
linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incomplatible_improvements</literal></link>
is set to 2.3.27 (or higher), and the returned
<literal>Writer</literal> implements
<literal>TransformControl</literal>, exceptions that are
used internally for flow control (for
<literal>&lt;#return&gt;</literal>,
<literal>&lt;#break&gt;</literal>, etc.) won't be passed to
<literal>TransformControl.onError(Throwable)</literal>
anymore. Earlier, if <literal>onError</literal> didn't
rethrow the exception (though almost all implementation
does), you couldn't use said directives inside the
transformed block.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Added workaround against <quote>IllegalStateException: zip
file closed</quote> and <quote>ZipException: ZipFile
closed</quote> issues (caused by bugs outside of FreeMarker)
when loading resources included in the FreeMarker jar (see
<literal>freemarker.template.utility.ClassUtil.loadProperties</literal>).</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_26">
<title>2.3.26 (incubating at Apache)</title>
<para>Release date: 2017-03-25</para>
<para><emphasis role="bold">This is a stable, final
release.</emphasis> The <quote>incubating</quote> suffix is required
by the Apache Software Foundation until the project becomes a fully
accepted (graduated) Apache project.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Added
<literal><replaceable>node</replaceable>?next_sibling</literal>
and
<literal><replaceable>node</replaceable>?previous_sibling</literal>
to move sideways in a node trees (<link
linkend="ref_builtin_next_sibling">see reference...</link>).
This works with XML DOM nodes, or with any custom
<literal>TemplateNodeModelEx</literal> implementations.</para>
</listitem>
<listitem>
<para>Added new <literal>@@</literal> keys to XML DOM models:
<literal>@@next_sibling_element</literal>,
<literal>@@previous_sibling_element</literal>. These get the
sibling node if that's an element, with the extra that they
silently skip any whitespace text and comment and processing
instruction between them. (See more about <literal>@@</literal>
keys <link
linkend="xgui_imperative_formal">here...</link>)</para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-42">FREEMARKER-42</link>):
<literal>?first</literal> now works with FTL collections (things
that can be listed but doesn't support getting items by index),
not only with sequences. The practical importance of this is
that <literal>?first</literal> now always works on Java
<literal>Set</literal>-s (which is useful for
<literal>Set</literal>-s with well defined ordering), while
earlier it has failed depending on the
<literal>object_wrapper</literal> configuration setting.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-24">FREEMARKER-24</link>:
Added workaround (not enabled by default) to expose Java 8
default methods (and the bean properties they define) to
templates, despite that
<literal>java.beans.Introspector</literal> (the official
JavaBeans introspector) ignores them, at least as of JRE
1.8.0_66. To enable this workaround, either increase the value
of the <literal>incompatibleImprovements</literal> constructor
argument of <literal>DefaultObjectWrapper</literal> or
<literal>BeansWrapper</literal> the used to 2.3.26, or set its
<literal>treatDefaultMethodsAsBeanMembers</literal> setting to
<literal>true</literal>. Note that if you leave the
<literal>object_wrapper</literal> setting of the
<literal>Configuration</literal> on its default, it's enough to
increase the <literal>incompatibleImprovements</literal> setting
of the <literal>Configuration</literal> to 2.3.26, as that's
inherited by the default
<literal>object_wrapper</literal>.</para>
</listitem>
<listitem>
<para>Added the
<literal>freemarker.template.TemplateNodeModelEx</literal>
interface which extends the <literal>TemplateNodeModel</literal>
instance with two methods, <literal>TemplateNodeModelEx
getNextSibling()</literal> and <literal>TemplateNodeModelEx
getPreviousSibling()</literal> methods. This is required by
<literal><replaceable>node</replaceable>?next_sibling</literal>
and
<literal><replaceable>node</replaceable>?previous_sibling</literal>
in the templates. This new interface is already implemented by
the standard W3C DOM node wrapper of FreeMarker.</para>
</listitem>
<listitem>
<para>Made <literal>+</literal> operator when adding two hashes
significantly faster (be removing the overhead caused be
throwing and then catching an exception).</para>
</listitem>
<listitem>
<para>Better error messages when someone tries to get an invalid
<literal>@@<replaceable>...</replaceable></literal> subvariable
of an XML DOM node. (Now it's not issued by the XPath
implementation, which just sees it as a syntactical
error.)</para>
</listitem>
<listitem>
<para>Added
<literal>Configuration.is<replaceable>Xxx</replaceable>ExplictlySet</literal>
and
<literal>Configuration.unset<replaceable>Xxx</replaceable></literal>
methods for the Configuration settings:
<literal>locale</literal>, <literal>time_zone</literal>,
<literal>default_encoding</literal>. (This can be utilized in
frameworks to detect if the application has missed setting
these. The backward compatible default values are often
unwanted, as they are the default locale, time zone and file
encoding of the Java environment.)</para>
</listitem>
<listitem>
<para>The <literal>locale</literal> and
<literal>default_encoding</literal> configuration settings now
supports the special <literal>"JVM default"</literal> value when
set from Java <literal>.properties</literal> file, or via
<literal>Configuration.setSettings(Properties)</literal>, or via
the <literal>#setting</literal> directive. Earlier only the
<literal>time_zone</literal> setting has supported this
value.</para>
</listitem>
<listitem>
<para>Bug fixed: The OSGi
<literal>Bundle-RequiredExecutionEnvironment</literal> entry in
<literal>META-INF/MANIFEST.MF</literal> has incorrectly stated
that the minimum required version is
<literal>J2SE-1.4</literal>, while it's in fact
<literal>J2SE-1.5</literal>. Also the highest utilized version
was raised to <literal>JavaSE-1.8</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed: If <link
linkend="pgui_config_incompatible_improvements_how_to_set">the
<literal>incompatible_improvements</literal> setting</link> is
set to 2.3.26 (or higher),
<literal><replaceable>exp</replaceable>?interpret</literal>
always gets the parser-related settings from the template that
it's called from. Earlier, sometimes it got those from the
topmost (main) template instead. Similarly, the generated name
of the template that <literal>?interpret</literal> creates will
always refer to the template where's it's called from.</para>
</listitem>
<listitem>
<para>Bug fixed: <literal>MultiTemplateLoader</literal>, when
it's in sticky mode (the default), and the
<literal>TemplateLoader</literal> that was successfully used for
a given name last time doesn't find the template now (let's call
it the sticked <literal>TemplateLoader</literal>), and thus
<literal>MultiTemplateLoader</literal> falls back to trying all
the <literal>TemplateLoader</literal>-s in order, will now skip
the sticked <literal>TemplateLoader</literal>, as that was
already attempted in the same
<literal>MultiTemplateLoader.findTemplateSource</literal>
invocation.</para>
</listitem>
<listitem>
<para>Bug fixed:
<literal>NodeModel.mergeAdjacentText(Node)</literal> didn't
merged all adjacent text nodes, only pairs of adjacent text
nodes. (Luckily this method is hardly ever used, and the more
often used <literal>NodeModel.simplify(Node)</literal> was
working correctly.)</para>
</listitem>
<listitem>
<para>Performance improvements in the static utility methods of
<literal>NodeModel</literal>: <literal>simplify(Node)</literal>,
<literal>mergeAdjacentText(Node)</literal>,
<literal>removeComments(Node)</literal>,
<literal>removePIs(Node)</literal>.</para>
</listitem>
<listitem>
<para>Added warning to the JavaDoc of
<literal>NodeModel.parse</literal> methods to inform users about
the possibility of XML External Entity (XXE) attacks if the
source XML (not a template) comes from untrusted source. This is
just an XML fact (i.e., that in an XML you can have external
entities and they can be exploited), and has no much to do with
FreeMarker. Also note that FreeMarker itself never calls
<literal>NodeModel.parse</literal>; these are merely convenience
methods that some applications directly call themselves to
create a <literal>NodeModel</literal> from an XML file. As this
method encapsulates the call to the platform XML parser, we
thought it's better to point this risk out.</para>
</listitem>
<listitem>
<para><literal>DefaultObjectWrapper</literal>, only with its
<literal>incompatible_improvements</literal> set to 2.3.26
(<link linkend="topic.defaultObjectWrapperIcI">see how
here...</link>), wraps
<literal>java.util.Enumeration</literal>-s into
<literal>freemarker.template.DefaultEnumerationAdapter</literal>
(a new class) instead of into
<literal>freemarker.ext.beans.EnumerationModel</literal> (as far
as <literal>useAdaptersForContainers</literal> is
<literal>true</literal>, which is the default). This adapter is
cleaner than <literal>EnumerationModel</literal> as it only
implements the minimally required FTL type, which avoids some
ambiguous situations. (Note that Java API methods aren't exposed
anymore as subvariables; if you really need them, you can use
<literal>?api</literal>).</para>
</listitem>
<listitem>
<para><literal>DefaultIteratorAdapter</literal> now supports
<literal>?api</literal>. It was an oversight that it
didn't.</para>
</listitem>
<listitem>
<para><literal>Configuration.setSetting(String,
String)</literal> and <literal>setSettings</literal> now allows
<literal>null</literal> value for
<literal>template_loader</literal> (because
<literal>Configuration.setTemplateLoader(null)</literal> is also
allowed for a while.).</para>
</listitem>
<listitem>
<para>The
<literal>freemarker.template.TemplateCollectionModelEx</literal>
interface and is not experimental anymore, so now it has
backward compatibility guarantees. Note that the
<literal>TemplateCollectionModelEx.contains(TemplateModel)</literal>
method was removed from it.</para>
</listitem>
<listitem>
<para><literal>freemarker.template.DefaultNonListCollectionAdapter</literal>
class is not experimental anymore, so now it has backward
compatibility guarantees.</para>
</listitem>
<listitem>
<para><literal>BeansWrapperConfiguration.classIntrospectorFactory</literal>
is not a protected field anymore, but a private one. Especially
as the class of that field
(<literal>ClassIntrospectorBuilder</literal>) was package
private, it's pretty much sure that nobody depends on this
field.</para>
</listitem>
<listitem>
<para>Various smaller code cleanups.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-17">FREEMARKER-17</link>:
Removed the Servlet- and JSP-related <literal>*.dtd</literal>
files to simplify licensing. We can operate without them as
before, as validation with them was disabled earlier too. At
this point, everything in the source code of the FreeMarker
engine, and everything in the produced
<literal>freemarker.jar</literal> was created inside the
FreeMarker project.</para>
</listitem>
<listitem>
<para><link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-27">FREEMARKER-27</link>:
Moved some content from the <literal>NOTICES</literal> files
over to the <literal>LICENSE</literal> file, to follow the
Apache Incubator guidelines closer.</para>
</listitem>
<listitem>
<para>Various smaller JavaDoc improvements.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_25">
<title>2.3.25 (incubating at Apache)</title>
<para>Release date: 2016-06-26</para>
<para><emphasis role="bold">This is a stable, final
release.</emphasis> The <quote>incubating</quote> suffix is required
by the Apache Software Foundation until the project becomes a fully
accepted (graduated) Apache project.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Extended the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link> to support listing hashes (such as
<literal>Map</literal>-s), like <literal>&lt;#list map as k,
v&gt;${k}: ${v}&lt;/#list&gt;</literal>, where
<literal>k</literal> and <literal>v</literal> are the key and
value in the key-value pairs of the hash.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Added the <literal>TemplateModelHashEx2</literal>
interface that extends <literal>TemplateModelHashEx</literal>
with a method for listing the content of the key-value pairs of
the hash. (This is utilized by the new hash listing capability
of the <link
linkend="ref.directive.list"><literal>list</literal>
directive</link>, but it's not required by it if all keys are
strings.)</para>
</listitem>
<listitem>
<para>Lazy imports: With the new boolean settings,
<literal>lazy_imports</literal> and
<literal>lazy_auto_imports</literal>, you can make imports (as
in <literal>&lt;#import "lib/utils.ftl" as u&gt;</literal>)
and/or auto-imports to be lazy. When the import is lazy, the
namespace variable (<literal>u</literal> in this example) will
be created immediately, just like before, but the imported
template will be loaded and processed only when (and if ever)
the content of the imported namespace is accessed. The main
application of this is with auto-imports, where you don't want
the overhead of importing templates that aren't actually used in
a template. (Also, a new
<literal>Environment.importLib</literal> method overload was
added, where you can specify if you want a lazy or an eager
import.) These new settings can be set on
<literal>Configuration</literal>, <literal>Template</literal>
(<literal>TemplateConfiguration</literal>) and
<literal>Environment</literal> level.</para>
</listitem>
<listitem>
<para>It's now possible to set the
<literal>auto_import</literal> and
<literal>auto_include</literal> settings on a per template basis
(like templates with a certain name pattern has different
auto-imports). This is now possible as these settings were moved
from the <literal>Configuration</literal> level down to the more
generic <literal>Configurable</literal> level, and so are
inherited by <literal>TemplateConfiguration</literal> and
<literal>Environment</literal> too.</para>
</listitem>
<listitem>
<para>New <literal>Configuration</literal> (and
<literal>TemplateConfiguration</literal>) setting,
<literal>tab_size</literal>. This only influences how the column
number reported in error messages is calculated (and the column
number available with other API-s). It doesn't influence the
output of the templates. Defaults to 8.</para>
</listitem>
<listitem>
<para>Added new setting to
<literal>DefaultObjectWrapper</literal> (and to
<literal>DefaultObjectWrapperBuilder</literal>):
<literal>iterableSupport</literal>. This fixes the issue when
you couldn't use <literal>#list</literal> (or
<literal>?has_next</literal>, etc.) on a value that only
implements Java 5 <literal>java.lang.Iterable</literal> (not to
be confused with <literal>Iterator</literal>), but not
<literal>Collection</literal>. This is not enabled by default as
it's not compatible with some existing templates, most often
because they have used
<literal>someIterable.iterator()</literal> in the template as a
workaround. When this is enabled, the
<literal>Iterable</literal> object won't be seen as a generic
Java object by FreeMarker anymore, and thus just like with
<literal>Collection</literal>-s, its API won't be exposed to the
templates (except through <literal>?api</literal>, of
course).</para>
</listitem>
<listitem>
<para>Added
<literal>Configurable.getCustomNumberFormatsWithoutFallback</literal>
and
<literal>Configurable.getCustomDateFormatsWithoutFallback</literal>
methods to make it easier for custom code to investigate the
custom formal setting <literal>Map</literal> hierarchy.</para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-18">FREEMARKER-18</link>):
If you had a JSP custom tag and an EL function defined in the
same TLD with the same name, the EL function has overwritten the
custom tag. This is a bug introduced in 2.3.23, when EL function
support was added. JSP allows a custom tag and an EL function in
the same TLD to have the same name. In such case now we combine
the two into a single value that is both callable as an user
defined directive (<literal>&lt;@my.foo...&gt;</literal>) and as
a function (<literal>my.f(...)</literal>).</para>
</listitem>
<listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-19">FREEMARKER-19</link>):
The column numbers calculated by the parser has assumed tab size
1 since 2.3.25 (an unwanted side effect of updating JavaCC),
while before it has assumed tab size 8. The default was restored
to 8. This bug has affected the column numbers in error
messages. It also broke the output of some rarely used AIP-s,
namely <literal>Template.getSource(beginCol, beginLine, endCol,
endLine)</literal>,
<literal>TemplateObject.getSource()</literal> and through that
<literal>TemplateObject.toString()</literal>, if the first or
last line has contain tab characters.</para>
</listitem>
<listitem>
<para>Bug fixed: There was a regression with 2.3.24, where
<literal>Configuration.setAutoImports()</literal> haven't
removed auto-imports added earlier. (Though it's unlikely that
an application uses that method and also adds auto-imports
earlier.)</para>
</listitem>
<listitem>
<para>Bug fixed:
<literal>TemplateConfiguration.apply(Template)</literal> didn't
merge the <literal>customDateFormats</literal> and
<literal>customNumberFormats</literal> <literal>Map</literal>-s
when they were set both in the <literal>Template</literal> and
in the applied <literal>TemplateConfiguration</literal>, instead
it just kept the value in the <literal>Template</literal> (just
like with atomic setting values). Note that it was unlikely to
run into this bug, as usually you (or FreeMarker) create a
single merged <literal>TemplateConfiguration</literal> with
<literal>TemplateConfiguration.merge(TemplateConfiguration)</literal>
and then apply it on a fresh template.</para>
</listitem>
<listitem>
<para>Removed FindBugs <literal>@SuppressFBWarnings</literal>
annotations from the binary (<literal>freemarker.jar</literal>),
as they have caused warnings like this when compiling dependant
project with Gradle: <quote>warning: Cannot find annotation
method 'value()' in type 'SuppressFBWarnings'</quote></para>
</listitem>
<listitem>
<para>The Maven source artifact now contains the JavaCC
generated java files and <literal>FTL.jj</literal>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_24">
<title>2.3.24 (incubating at Apache)</title>
<para>Release date: 2016-03-28</para>
<para><emphasis role="bold">This is a stable, final
release.</emphasis> The <quote>incubating</quote> suffix is required
by the Apache Software Foundation until the project becomes a fully
accepted (graduated) Apache project. See disclaimer below.</para>
<section>
<title>Legal changes</title>
<para>The owner of FreeMarker is now the Apache Software Foundation.
The license is still Apache License Version 2.0, just like earlier,
but the owner is different. The official full product name has
changed to Apache FreeMarker.</para>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>The most important new feature of this release is the
<link linkend="dgui_misc_autoescaping">auto-escaping and output
formats mechanism</link>, which deprecates escaping with the
<link linkend="ref_directive_escape"><literal>escape</literal>
directive</link>. These are the changes related to this new
mechanism (see earlier link for a guide):</para>
<itemizedlist>
<listitem>
<para>New <literal>ftl</literal> header options,
<literal>ouput_format</literal> and
<literal>auto_esc</literal> to override the
<literal>output_format</literal> and
<literal>auto_escaping</literal> settings of the template,
like <literal>&lt;#ftl
output_format='HTML'</literal><literal>
auto_esc=false&gt;</literal>.</para>
</listitem>
<listitem>
<para>New built-in: <link
linkend="ref_builtin_no_esc"><literal>no_esc</literal></link>.
Used to prevent auto-escaping, like
<literal>${descriptionInHtml?no_esc}</literal>. This doesn't
work with <literal>&lt;#escape
<replaceable>...</replaceable>&gt;</literal>, only with the
new auto-escaping mechanism.</para>
</listitem>
<listitem>
<para>New FTL type, <quote>markup output</quote>. This is
somewhat similar to string, but values of this type aren't
auto-escaped by the new escaping mechanism, because they are
known to already hold markup. (For example,
<literal>?esc</literal> and <literal>?no_esc</literal>
returns a value of this type, hence their results are
protected from double-escaping problems.)</para>
</listitem>
<listitem>
<para>New built-in: <link
linkend="ref_builtin_esc"><literal>esc</literal></link>.
Used for escaping with the current output format when
auto-escaping is disabled.</para>
</listitem>
<listitem>
<para>New built-in: <literal>markup_string</literal>. This
returns the markup of a <link
linkend="dgui_misc_autoescaping_movalues">markup output
value</link> as string.</para>
</listitem>
<listitem>
<para>New built-in: <literal>is_markup_output</literal>,
returns <literal>true</literal> if the value is of type
<quote>markup output</quote>.</para>
</listitem>
<listitem>
<para>New directive: <literal>outputformat</literal>, used
to change the output format for a section of a template,
like <literal>&lt;#outputformat
"XML"&gt;<replaceable>...</replaceable>&lt;/#outputformat&gt;</literal></para>
</listitem>
<listitem>
<para>New directives: <literal>noautoesc</literal> and
<literal>autoesc</literal>, used to turn auto-escaping off
and on for a section of a template, like
<literal>&lt;#noautoesc&gt;<replaceable>...</replaceable>&lt;/#noautoesc&gt;</literal>.</para>
</listitem>
<listitem>
<para>New built-in variable,
<literal>.output_format</literal>, returns the current
output format at the place of invocation.</para>
</listitem>
<listitem>
<para>New built-in variable, <literal>.auto_esc</literal>,
returns the boolean that tells if auto-escaping is active at
the place of invocation.</para>
</listitem>
<listitem>
<para>Block assignments, like <literal>&lt;#assign
<replaceable>captured</replaceable>&gt;<replaceable>...</replaceable>&lt;/#assign&gt;</literal>,
when the current <literal>output_format</literal> is some
kind of markup (like HTML), will store the captured output
not with string type, but with <quote>markup output</quote>
type. Thus
<literal>${<replaceable>captured</replaceable>}</literal>
will not get unwanted escaping.</para>
</listitem>
<listitem>
<para>The <literal>+</literal> operator (concatenation)
works with the new <quote>markup output</quote> type as
well. Like <literal>someMarkup + somePlainText</literal>
will result in markup where <literal>somePlainText</literal>
is escaped automatically before it's appended to the
markup.</para>
</listitem>
<listitem>
<para>The <literal>has_content</literal> built-in now
supports <quote>markup output</quote> values, considering 0
length markup as empty.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>You can now define custom number and date/time/datetime
formatters. These are defined by the programmers (and thus can
implement any kind of exotic formatting rules) when configuring
FreeMarker, and can be referred with strings starting with
<literal>"@"</literal>, like in <literal>&lt;#setting
number_format='@foo'&gt;</literal>, or
<literal>${n?string.@foo_params}</literal>,
<literal>&lt;#setting number_format='@foo params'&gt;</literal>,
or <literal>${n?string.@foo}</literal>,
<literal>${n?string.@foo_params}</literal>. For backward
compatibility, the initial <literal>@</literal> only has this
special meaning if either you have any custom formats or <link
linkend="pgui_config_incompatible_improvements">the
<literal>incompatible_improvements</literal> setting</link> is
at lest 2.3.24.</para>
</listitem>
<listitem>
<para>Everywhere where Java <literal>DecimalFormat</literal>
patterns are used (like in <literal>?string('0.##')</literal> or
<literal>&lt;#setting number_format="0.##"&gt;</literal>), now
it's possible to specify options like rounding mode or the
symbols used, with a FreeMarker-specific <link
linkend="topic.extendedJavaDecimalFormat">extension to the
<literal>DecimalFormat</literal> pattern syntax</link>.</para>
</listitem>
<listitem>
<para>Added new special variable:
<literal>.incompatible_improvements</literal>, which returns the
<link
linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
setting</link> of the current FreeMarker configuration, as a
string.</para>
</listitem>
<listitem>
<para><literal>?date</literal>, <literal>?time</literal> and
<literal>?datetime</literal> now can be called as 0 argument
method, like <literal>?date()</literal>, etc., which returns the
exact object that <literal>TemplateDateFormat.parse</literal>
returns, instead of the tricky multi-type object that just using
<literal>?date</literal> returns. Because custom
<literal>TemplateDateFormat</literal> implementations may return
custom <literal>TemplateDateModel</literal> implementations,
keeping the exact class can be important in some
applications.</para>
</listitem>
<listitem>
<para><literal>&lt;@</literal> and <literal>&lt;/@</literal> is
now allowed in string literals that contain
<literal>${<replaceable>exp</replaceable>}</literal>, and will
be part of the literal as is. Earlier it was a syntactical
error.</para>
</listitem>
<listitem>
<para>Bug fixed: With
<literal>incompatible_improvements</literal> set to 2.3.24
(<link linkend="topic.defaultObjectWrapperIcI">see how
here...</link>),
<literal><replaceable>m</replaceable>?is_sequence</literal>
doesn't return <literal>true</literal> for Java methods wrapped
by <literal>BeansWrapper</literal> and its subclasses (most
notably <literal>DefaultObjectWrapper</literal>) anymore, as
they only implement the
<literal>[<replaceable>index</replaceable>]</literal> operator,
but not <literal>?size</literal>, which causes
<literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
to fail, among others.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><emphasis role="strong">Attention!</emphasis> FreeMarker
now requires at least Java 1.5 (aka. Java 5). 2.3.24 has only
required Java 1.4. (Reason: Without this, new public API-s
couldn't use generics, which affect negatively the majority of
users, while old installations that are still using 1.4 are
unlikely to update FreeMarker anyway.)</para>
</listitem>
<listitem>
<para><emphasis role="strong">Attention!</emphasis> FreeMarker's
JSP support (if it's used) now requires at least JSP 2.0.
Earlier it only required JSP 1.1. (Reason: The
<literal>jsp-api</literal> dependency for JSP 1.x, which was
needed for building, can't be legally present in the Maven
Central Repository, nor be provided by freemarker.org.)</para>
</listitem>
<listitem>
<para>Added new configuration setting:
<literal>template_configurations</literal>. This allows
overriding the settings coming from the shared
<literal>Configuration</literal> object for individual
templates, based on template name patterns. <link
linkend="pgui_config_templateconfigurations">See more
here...</link></para>
</listitem>
<listitem>
<para>Related to the <link linkend="dgui_misc_autoescaping">new
auto-escaping mechanism</link>:</para>
<itemizedlist>
<listitem>
<para>As FTL has now a new type, <quote>markup
output</quote>, there's also a corresponding new model
interface, <literal>TemplateMarkupOutputModel</literal>.
This also means that you can prevent the auto-escaping of
values coming from the data-model by returning a
<literal>TemplateMarkupOutputModel</literal> instead of a
<literal>String</literal>. Like the template author can just
write <literal>${messages.foo}</literal>, and it will be
auto-escaped or not depending on if the message is known to
be markup or not.</para>
</listitem>
<listitem>
<para>Added new configuration setting:
<literal>recognize_standard_file_extensions</literal>. When
<literal>true</literal>, templates whose source name ends
with <literal>".ftlh"</literal> will get
<literal>HTML</literal> <literal>output_format</literal>,
and those whose name ends with <literal>".ftlx"</literal>
get <literal>XML</literal> <literal>output_format</literal>,
in both cases with auto-escaping on. If <link
linkend="pgui_config_incompatible_improvements_how_to_set">the
<literal>incompatible_improvements</literal> setting</link>
is set to 2.3.24 (or higher) then this setting defaults to
<literal>true</literal>. Otherwise it's default is
<literal>false</literal>, but enabling it is highly
recommended.</para>
</listitem>
<listitem>
<para>Added new configuration setting:
<literal>output_format</literal>. This specifies the <link
linkend="dgui_misc_autoescaping_outputformat">output
format</link> object to use (such as
<literal>HTMLOutputFormat.INSTANCE</literal>,
<literal>XMLOutputFormat.INSTANCE</literal>, etc.) that
governs auto-escaping. The output format can be different
for different templates, using the
<literal>template_configurations</literal> setting (<link
linkend="pgui_config_outputformatsautoesc">see here
how...</link>).</para>
</listitem>
<listitem>
<para>Added new configuration setting:
<literal>registered_custom_output_formats</literal>. With
this you can add new <literal>OutputFormat</literal>-s that
templates can refer to by name (like in <literal>&lt;#ftl
output_format="foo"&gt;</literal>).</para>
</listitem>
<listitem>
<para>Added new configuration setting:
<literal>auto_escaping_policy</literal>. This decides when
auto-escaping should be enabled depending on the current
output format.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Changes related to the custom number and
date/time/datetime formating feature:</para>
<itemizedlist>
<listitem>
<para>Added new classes for implementing custom formatters:
<literal>freemarker.core.TemplateNumberFormat</literal>,
<literal>TemplateNumberFormatFactory</literal>,
<literal>TemplateDateFormat</literal>,
<literal>TemplateDateFormatFactory</literal>, also the
exceptions these can throw. These allow implementing any
kind of formatting rule that's doable in Java (i.e., they
aren't restricted to any <literal>java.text</literal>
formatters). Furthermore these formatters get the
<literal>TemplateModel</literal> instead of a the bare
<literal>java.lang.Number</literal> or
<literal>java.util.Date</literal>, which lets you use the
extra application-specific meta information that you may
pack into the <literal>TemplateModel</literal>-s, such as
physical unit, preferred precision, and so on.</para>
</listitem>
<listitem>
<para>Added <literal>custom_number_formats</literal> and
<literal>custom_date_formats</literal> settings
(<literal>Configurable.setCustomNumberFormats(Map&lt;String,
TemplateNumberFormatFactory&gt;)</literal> and
<literal>Configurable.setCustomDateFormats(Map&lt;String,
TemplateDateFormatFactory&gt;)</literal>) with which you can
register your own formats. These formats can be referred
from everywhere where you can use a string to define a
format, with a format string like <literal>"@foo"</literal>
or <literal>"@foo params"</literal>, where
<literal>"foo"</literal> is the key in the
<literal>Map&lt;String, ...&gt;</literal> parameter of the
earlier shown methods, and the parameters (if any) are
interpreted by the
<literal>Template<replaceable>Xxx</replaceable>FormatFactory</literal>
implementation that you provide. Like, you can issue
<literal>cfg.setNumberFormat("@foo params")</literal>, or
<literal>&lt;#setting number_format='@foo
params'&gt;</literal>, or
<literal>${n?string.@foo_params}</literal>, similarly as you
can issue <literal>cfg.setNumberFormat("0.##")</literal>,
etc. For backward compatibility, the initial
<literal>@</literal> only has this special meaning if either
you have any custom formats or <link
linkend="pgui_config_incompatible_improvements">the
<literal>incompatible_improvements</literal> setting</link>
is at least 2.3.24. Note that the
<literal>custom_number_formats</literal> and
<literal>custom_date_formats</literal> settings can be set
per-template (via the new
<literal>template_configurations</literal> settings) or
per-<literal>Environment</literal> too, thus
<literal>@foo</literal> can mean something different in
different templates.</para>
</listitem>
<listitem>
<para>Added new <literal>Environment</literal> methods
returning <literal>TemplateNumberFormat</literal> and
<literal>TemplateDateFormat</literal> objects. See the
<literal>getTemplateNumberFormat(<replaceable>...</replaceable>)</literal>
and
<literal>getTemplateDateFormat(<replaceable>...</replaceable>)</literal>
variations in the API.</para>
</listitem>
<listitem>
<para>Added
<literal>freemarker.core.AliasTemplateNumberFormatFactory</literal>
and <literal>AliasTemplateDateFormatFactory</literal>, which
can be used to create custom formats that are aliases to
other formats. For example, instead of writing
<literal>${n?string["0.00"]}</literal> again and again, you
can define the custom format <literal>"price"</literal> as
the alias to the format string <literal>"0.00"</literal> in
the configuration, and then use
<literal>${n?string.@price}</literal>. Thus, you can control
at a central place how prices look. Furthermore, the alias
can chose a different target format string depending on the
current locale; this is especially useful for dates, where
conventions can significantly differ in different
countries.</para>
</listitem>
<listitem>
<para>It's now possible to have HTML or other markup in
number and date/time/datetime formatting results, like
<literal>1.23*10&lt;sup&gt;6&lt;/sup&gt;</literal>, which
won't be accidentally auto-escaped, as FreeMarker knows that
it's already HTML. This is done by returning a
<literal>TemplateMarkupOutputModel</literal> instead of a
<literal>String</literal>; see the new auto-escaping
mechanism earlier. Note that no out-of-the-box format
utilizes this (at the moment), but you could write such
custom format.</para>
</listitem>
<listitem>
<para>The internal format object caching architecture has
been reworked, so that it can handle custom formats too.
This reworking also fixes some bottlenecks under highly
concurrent load, and some (otherwise unlikely) memory leak
possibilities.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>In the <literal>number_format</literal> configuration
setting, when it holds a Java <literal>DecimalFormat</literal>
pattern (like <literal>"0.##"</literal>), it's now possible to
specify options like rounding mode or the symbols used, with a
FreeMarker-specific <link
linkend="topic.extendedJavaDecimalFormat">extension to the
pattern syntax</link>.</para>
</listitem>
<listitem>
<para>New <literal>FreemarkerServlet</literal> init-params (see
<link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">the
<literal>FreemarkerSerlvet</literal> API documentation</link>
for details):</para>
<itemizedlist>
<listitem>
<para><literal>OverrideResponseContentType</literal>:
Specifies when should we override the
<literal>contentType</literal> that's already set (i.e.,
non-<literal>null</literal>) in the
<literal>HttpServletResponse</literal>. Earlier, we have
always set it, and that's still the default behavior. But
now that this init-param exists, you can change that
behavior, so that the <literal>contentType</literal> you
have specified before forwarding to
<literal>FreemarkerServlet</literal> matters.</para>
</listitem>
<listitem>
<para><literal>OverrideResponseLocale</literal>: Specifies
if we should override the <literal>locale</literal> that's
already set (i.e., non-<literal>null</literal>) in the
<literal>HttpServletResponse</literal>. Earlier, we have
always set it, but now this behavior can be changed so that
we only set it if it wasn't already set.</para>
</listitem>
<listitem>
<para><literal>ResponseCharacterEncoding</literal>:
Deprecates the old (and quirky) logic of specifying the
output charset, which is putting it into the
<literal>ContentType</literal> init-param after the MIME
type, otherwise falling back to the template file charset.
The possible values are <literal>legacy</literal> (the
default for backward compatibility),
<literal>fromTemplate</literal> (which is
<literal>legacy</literal> without quirks, and is aware of
the <literal>outputEncoding</literal> setting),
<literal>doNotSet</literal> (keeps what the caller has
already set in the <literal>ServletRespone</literal>) and
<literal>force</literal> followed by a charset name (forces
a specific output charset).</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Added
<literal>freemarker.cache.ByteArrayTemplateLoader</literal>,
which is similar to <literal>StringTemplateLoader</literal>, but
stores the templates as <literal>byte[]</literal>-s instead of
as <literal>String</literal>-s.</para>
</listitem>
<listitem>
<para>Upgraded JavaCC (used during build to generate the FTL
parser) from 3.2 to 6.1.2.</para>
</listitem>
<listitem>
<para>Added <literal>Configurable.getSettingNames(boolean
camelCase)</literal>, which returns the set of valid setting
names. This can be useful for auto-completion and such.</para>
</listitem>
<listitem>
<para>Fixes and improvements in the <quote>object
builder</quote> mini-language used for configuring FreeMarker
from <literal>java.util.Properties</literal> or other
string-only sources (not used in templates). This is
<emphasis>not to be confused with the template language
syntax</emphasis>, which has nothing to do with the
<quote>object builder</quote> syntax we are writing about here.
The improvements are:</para>
<itemizedlist>
<listitem>
<para>Bug fixed: For nested builder expressions, the
top-level result class restriction were applied
accidentally.</para>
</listitem>
<listitem>
<para>When resolving an expression like
<literal>com.example.Foo()</literal>, if there's a builder
class (<literal>com.example.FooBuilder</literal>), the
non-builder class (<literal>com.example.Foo</literal>) need
not exist anymore. After all,
<literal>FooBuilder.build()</literal> instantiates from any
class it wants to anyway.</para>
</listitem>
<listitem>
<para><literal>TimeZone</literal> objects can be created
like <literal>TimeZone("UTC")</literal>, despite that
there's no a such constructor.</para>
</listitem>
<listitem>
<para>Added support for creating lists with <literal>[
<replaceable>item1</replaceable>,
<replaceable>item2</replaceable>,
<replaceable>...</replaceable>
<replaceable>itemN</replaceable> ]</literal> syntax.</para>
</listitem>
<listitem>
<para>Added support for creating maps with <literal>{
<replaceable>key1</replaceable>:
<replaceable>value1</replaceable>,
<replaceable>key2</replaceable>:
<replaceable>value2</replaceable>,
<replaceable>...</replaceable>
<replaceable>keyN</replaceable>:
<replaceable>valueN</replaceable> }</literal> syntax.</para>
</listitem>
<listitem>
<para>A number without decimal point will now be parsed to
<literal>Integer</literal>, <literal>Long</literal>, or
<literal>BigInteger</literal>, depending on the size of the
number. Earlier all numbers were parsed to
<literal>BigDecimal</literal>-s, but that had little
importance before lists and maps were added, as the number
was converted to the constructor or setter parameter type
anyway.</para>
</listitem>
<listitem>
<para>Number literals can have Java type suffixes
(<literal>f</literal>, <literal>d</literal>,
<literal>l</literal>), plus <literal>bd</literal> for
<literal>BigDecimal</literal> and <literal>bi</literal> for
<literal>BigInteger</literal>.</para>
</listitem>
<listitem>
<para>Public static fields can be referred, like
<literal>com.example.MyClass.MY_CONSTANT</literal> or
<literal>Configuration.AUTO_DETECT_TAG_SYNTAX</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Decreased the stack usage of template execution, which can
have importance if you have very very deeply nested
templates.</para>
</listitem>
<listitem>
<para>Added
<literal>MultiTemplateLoader.setSticky(boolean)</literal> and
<literal>MultiTemplateLoader.isSticky()</literal>, with which
you can disable the default behavior, where once a template was
found in a child <literal>TemplateLoader</literal>, it will be
searched there first next time (typically, when the template
update delay is expired). With the <literal>sticky</literal>
property set to <literal>false</literal>, the child
<literal>TemplateLoader</literal>-s will be always searched in
the order as they were added to the
<literal>MultiTemplateLoader</literal>.</para>
</listitem>
<listitem>
<para>Added
<literal>StringTemplateLoader.removeTemplate(String)</literal>
method.</para>
</listitem>
<listitem>
<para>Bug fixed, only with
<literal>incompatible_improvements</literal> set to 2.3.24
(<link linkend="topic.defaultObjectWrapperIcI">see how
here...</link>): Expressions inside interpolations that were
inside <emphasis>string literal expressions</emphasis> (not
<literal>${<replaceable>...</replaceable>}</literal>-s in
general), like in <literal>&lt;#assign s="Hello
${name}!"&gt;</literal>, always used
<literal>incompatibleImprovements</literal> 0 (2.3.0 in effect).
This means that expressions inside string literals had missed
the <literal>?html</literal>,
<literal>?iso_<replaceable>...</replaceable></literal>,
<literal>?is_enumerable</literal>, <literal>?c</literal>, etc.
fixes/improvements.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/439/">439</link>]:
<literal>FileTemplateLoader</literal> with
<literal>emulateCaseSensitiveFileSystem</literal> set to
<literal>true</literal> (used for development) wasn't properly
synchronized, leading to random
<literal>NullPointerException</literal>-s or other
misbehavior.</para>
</listitem>
<listitem>
<para>Bug fixed: It wasn't well defined when a Java
<literal>Iterator</literal> counts as empty. Depending on what
<literal>ObjectWrapper</literal> you are using, one of these
fixes apply:</para>
<itemizedlist>
<listitem>
<para><literal>DefaultObjectWrapper</literal> (fix is always
active): Operations on the <literal>Iterator</literal> that
only check if it's empty without reading an element from it,
such as <literal>?has_content</literal>, won't cause a later
iteration (or further emptiness check) to fail anymore.
Earlier, in certain situations, the second operation has
failed saying that the iterator <quote>can be listed only
once</quote>.</para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal> (when it's not
extended by <literal>DefaultObjectWrapper</literal>), if
it's <literal>incompatibleImprovements</literal> property is
set to 2.3.24 (or higher): <literal>Iterator</literal>-s
were always said to be non-empty when using
<literal>?has_content</literal> and such (i.e., operators
that check emptiness without reading any elements). Now an
<literal>Iterator</literal> counts as empty exactly if it
has no elements left. (Note that this bug has never affected
basic functionality, like <literal>&lt;#list
...&gt;</literal>.)</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fixed: The (rarely used) cause exception of
<literal>ParseException</literal>-s wasn't set</para>
</listitem>
<listitem>
<para>Bug fixed: When the
<literal>incomaptible_improvements</literal> setting of an
existing <literal>Configuration</literal> was changed, the
template cache sometimes wasn't recreated, hence old templates
could survive.</para>
</listitem>
<listitem>
<para>Bug fixed, with
<literal>incompatible_improvements</literal> set to 2.3.24
(<link linkend="topic.defaultObjectWrapperIcI">see how
here...</link>): The <literal>#import</literal> directive meant
to copy the library variable into a global variable if it's
executed in the main namespace, but that haven't happened when
the imported template was already imported earlier in another
namespace.</para>
</listitem>
<listitem>
<para>Fixes in the XML processing feature
(<literal>freemarker.ext.dom</literal>):</para>
<itemizedlist>
<listitem>
<para>Bug fixed: XPath queries that has only contained
characters that are valid in XML element names and has also
contained <literal>::</literal> (which is valid in names in
namespace-unware documents), like
<literal>e['following-sibling::foo']</literal>, were
interpreted as literal element names (giving 0 hits) rather
than as XPath expressions. Note that there were no such
problem with <literal>e['following-sibling::*']</literal>
for example, as it's not a valid XML element name according
the XML specification. This fix can actually break
applications that has processed namespace unaware XML that
use <literal>::</literal> as part of element or attribute
names, but such an application is highly unlikely, unlike
running into the fixed problem. (Unfortunately, using
<literal>incompatible_improvements</literal> wasn't
technically possible here.)</para>
</listitem>
<listitem>
<para>Bug fixed: The <literal>@@qname</literal> of elements
that belong to the XML namespace declared as the default via
<literal>&lt;#ftl ns_prefixes={'D':'...', ...
}&gt;</literal> no longer starts with <literal>D:</literal>,
instead they just start with no name space prefix.</para>
</listitem>
<listitem>
<para>Bug fixed: In the markup returned by the
<literal>@@markup</literal> key, when there were multiple
namespaces for which there was no prefix associated with via
<literal>&lt;#ftl
ns_prefixes=<replaceable>...</replaceable>&gt;</literal>,
all those namespaces were assigned to the same
auto-generated <literal>xmlns</literal> prefix (usually
<quote>a</quote>). Now they will get <quote>a</quote>,
<quote>b</quote>, <quote>c</quote>, etc. prefixes.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>JSP TLD loading now quotes the location of
<literal>jar</literal>-s (and other <literal>zip</literal>-s)
which can't be loaded due to zip format errors in the error
message.</para>
</listitem>
<listitem>
<para>Added an overload to
<literal>Configuration.getSupportedBuiltInNames</literal> and
<literal>Configuration.getSupportedBuiltInDirectiveNames</literal>
that has a <literal>namingConvention</literal> parameter. This
is useful for tooling as since 2.3.23 we support both camel case
naming convention (like
<literal><replaceable>s</replaceable>?upperCase</literal>) and
the legacy one (like
<literal><replaceable>s</replaceable>?upper_case</literal>).
Furthermore the old 0 argument overload will now utilize
<literal>Configuration.getNamingConvention()</literal> to only
return the relevant names if it's not
<literal>AUTO_DETECT_NAMING_CONVENTION</literal>.</para>
</listitem>
<listitem>
<para>Internal reworking to simplify the AST (the
<literal>TemplateElement</literal> structure). The related
technically public API was marked as internal for a good while.
For those who still use that API, the visible change is that
<literal>TemplateElement</literal>-s now almost never has a
<literal>MixedContent</literal> parent, instead, the parent is
directly whatever element the child element indeed belongs under
when you look at the source code (like the enclosing
<literal>#list</literal> for example, while earlier you often
had to go through a <literal>MixedContent</literal> first whose
parent was the <literal>#list</literal>). Note that when you
have moved downwards, i.e., towards the child elements, these
<literal>MixedContent</literal> parents weren't visible and were
silently skipped, so the tree traversal API was inconsistent.
Now it's consistent.</para>
</listitem>
<listitem>
<para>Due to the above change again, the return type of
<literal>freemarker.core.DebugBreak.accept()</literal> and
<literal>freemarker.core.TextBlock.accept()</literal> has
changed from <literal>void</literal> to
<literal>TemplateElement[]</literal>. This again is highly
unlikely to affect anyone, and these meant to be internal API-s
anyway, but as these two <literal>accept</literal> methods has
wider than package visibility for historical reasons, we mention
this change.</para>
</listitem>
<listitem>
<para>The non-public AST API of
<literal>freemarker.core.StringLiteral</literal>-s has been
changed. In principle it doesn't mater as it isn't a public API,
but some might used these regardless to introspect templates.
Earlier it had an <quote>embedded template</quote> parameter
inside, now it has 0 (for purely static string literals), one or
more <quote>value part</quote>-s, which are
<literal>String</literal>-s and
<literal>Interpolation</literal>-s.</para>
</listitem>
<listitem>
<para>Internal code cleanup: Mostly for consistent source code
formatting, also many parser construction/setup cleanup</para>
</listitem>
<listitem>
<para>Source code changes to conform to Apache source release
policy, such as adding copyright headers and getting rid of test
<literal>jar</literal>-s committed into the source code. Eclipse
project files were also removed, instead the
<literal>README</literal> describes how to set up the
project.</para>
</listitem>
<listitem>
<para>Build script and distribution artifact changes to conform
to Apache release policy, most notably it produces separate
source and binary releases.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes compared to 2.3.24 Release Candidate 1</title>
<itemizedlist>
<listitem>
<para>Added
<literal>MultiTemplateLoader.setSticky(boolean)</literal> and
<literal>MultiTemplateLoader.isSticky()</literal>, with which
you can disable the default behavior, where once a template was
found in a child <literal>TemplateLoader</literal>, it will be
searched there first next time (typically, when the template
update delay is expired). With the <literal>sticky</literal>
property set to <literal>false</literal>, the child
<literal>TemplateLoader</literal>-s will be always searched in
the order as they were added to the
<literal>MultiTemplateLoader</literal>.</para>
</listitem>
<listitem>
<para>Added
<literal>StringTemplateLoader.removeTemplate(String)</literal>
method.</para>
</listitem>
<listitem>
<para>Source code changes to conform to Apache release policy
and recommendations:</para>
<itemizedlist>
<listitem>
<para>No more binary test <literal>jar</literal>-s committed
into the source code (instead, they are generated
on-the-fly)</para>
</listitem>
<listitem>
<para>Eclipse project files were removed, instead, the
<literal>README</literal> describes how to set up the
project.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_23">
<title>2.3.23</title>
<para>Date of release: 2015-07-05</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Listing (<literal>#list</literal>) has received some
specialized convenience features that target typical tasks
people do again and again in templates.</para>
<itemizedlist>
<listitem>
<para>New <literal>list</literal> directive child
directives. There are <literal>else</literal> and
<literal>items</literal> to deal with special cases with
0-length lists, and <literal>sep</literal> for inserting
separators between items. For more details, see the <link
linkend="ref_directive_list"><literal>list</literal>
directive in the Reference</link>.</para>
</listitem>
<listitem>
<para><link linkend="ref_builtins_loop_var">New built-ins
that act on loop variables</link>:
<literal><replaceable>var</replaceable>?index</literal>
(deprecates
<literal><replaceable>var</replaceable>_index</literal>),
<literal><replaceable>var</replaceable>?counter</literal>
(1-based index),
<literal><replaceable>var</replaceable>?has_next</literal>
(deprecates
<literal><replaceable>var</replaceable>_has_next</literal>),
<literal><replaceable>var</replaceable>?is_first</literal>,
<literal><replaceable>var</replaceable>?is_last</literal>,
<literal><replaceable>var</replaceable>?item_parity</literal>
(returns <literal>"odd"</literal> or
<literal>"even"</literal>),
<literal><replaceable>var</replaceable>?item_parity_cap</literal>,
<literal><replaceable>var</replaceable>?item_cycle</literal><literal>(<replaceable>...</replaceable>)</literal>,
etc.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Added convenience assignment operators, which can be used
in assignment directives (<literal>#assign</literal>,
<literal>#global</literal> and <literal>#local</literal>
currently) only:</para>
<itemizedlist>
<listitem>
<para><literal>++</literal> and <literal>--</literal>: For
example, <literal>&lt;#assign counter++&gt;</literal> is
equivalent to <literal>&lt;#assign counter = counter +
1&gt;</literal>.</para>
</listitem>
<listitem>
<para><literal>+=</literal>, <literal>-=</literal>,
<literal>*=</literal>, <literal>/=</literal> and
<literal>%=</literal>: For example, <literal>&lt;#assign
counter += 2&gt;</literal> is equivalent to
<literal>&lt;#assign counter = counter +
2&gt;</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Added the <literal>then</literal> built-in, which can be
used like a ternary operator:
<literal><replaceable>someBoolean</replaceable>?then(<replaceable>whenTrue</replaceable>,
<replaceable>whenFalse</replaceable>)</literal>. Just like with
the ternary operator of most other languages, only one of the
parameter expressions will be evaluated. <link
linkend="ref_builtin_then">More details...</link></para>
</listitem>
<listitem>
<para>Added the <literal>switch</literal> built-in, which can be
used like an in-line (expression) switch-case-default statement:
<literal><replaceable>someValue</replaceable>?switch(<replaceable>case1</replaceable>,
<replaceable>result1</replaceable>,
<replaceable>case2</replaceable>,
<replaceable>result2</replaceable>, ...
<replaceable>caseN</replaceable>,
<replaceable>resultN</replaceable>,
<replaceable>defaultResult</replaceable>)</literal>, where
<literal><replaceable>defaultResult</replaceable></literal> can
be omitted (then it will be error if none of the cases matches).
<link linkend="ref_builtin_switch">More details...</link></para>
</listitem>
<listitem>
<para>Added camel case support for the identifiers that are part
of the template language (user defined names aren't affected).
For example, now
<literal>&lt;#noEscape&gt;${x?upperCase}&lt;/#noEscape&gt;</literal>
or <literal>&lt;#setting numberFormat="0.0"&gt;</literal> or
<literal>&lt;#ftl stripText=true&gt;</literal> are valid.
However, within the same template, FreeMarker will require you
to use the same naming convention consistently for all
identifiers that are part of the template language. It's also
possible to enforce the same naming convention on all templates
from Java via
<literal>Configuration.setNamingConvention(int)</literal>. It's
certain that camel case will be the recommended convention
starting from some future version, because the Java API-s users
call from templates use that too.</para>
</listitem>
<listitem>
<para>Added new <link linkend="ref_specvar">special
variables</link>, <literal>.current_template_name</literal> and
<literal>.main_template_name</literal>. These deprecate
<literal>.template_name</literal>, which was always broken when
it comes to macro calls. The new
<literal>.current_template_name</literal> always returns the
name of the template that contains the reference to the special
variable, and <literal>.main_template_name</literal> always
returns the name of the topmost template.</para>
</listitem>
<listitem>
<para>Smaller error message improvements. Like, added tip in the
error message for the frequent issue when
<literal><replaceable>someMap</replaceable>[<replaceable>someNumber</replaceable>]</literal>
complains that
<literal><replaceable>someMap</replaceable></literal> is not a
sequence nor is coercible to string.</para>
</listitem>
<listitem>
<para>Bug fixed, activated with setting
<literal>incompatible_improvements</literal> to 2.3.23: There's
a long existing parse-time rule that says that
<literal>#break</literal>, in the FTL source code itself, must
occur nested inside a breakable directive, such as
<literal>#list</literal> or <literal>#switch</literal>. This
check could be circumvented with <literal>#macro</literal> or
<literal>#function</literal>, like this: <literal>&lt;#list 1..1
as x&gt;&lt;#macro
callMeLater&gt;&lt;#break&gt;&lt;/#macro&gt;&lt;/#list&gt;&lt;@callMeLater
/&gt;</literal>. After activating this fix, this will be caught
as parse time error.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Added
<literal>Configuration.setNamingConvention(int)</literal>. By
default FreeMarker will auto-detect the naming convention
(legacy VS camel case) used for the identifiers that are part of
the template language, for each template independently. This
setting lets you enforce a naming convention instead.</para>
</listitem>
<listitem>
<para><literal>Configuration</literal> (and in fact any
<literal>Configurable</literal>) setting names now can be
written with camel case as well. For example, if you are
configuring FreeMarker from properties file, you can have
<literal>defaultEncoding=utf-8</literal> instead of
<literal>default_encoding=utf-8</literal>. You can use the two
naming conventions (camel case, and tradition snake case) mixed,
and <literal>Configuration.setNamingConvention(int)</literal>
does not influence this behavior.</para>
</listitem>
<listitem>
<para>Added
<literal>Configuration.setTemplateUpdateDelayMilliseconds(long)</literal>
and
<literal>Configuration.getTemplateUpdateDelayMilliseconds()</literal>.
This deprecates <literal>setTemplateUpdateDelay(int)</literal>,
which uses seconds resolution, hence going against Java
conventions and often leading to misunderstandings. (Also that
couldn't have a getter pair.)</para>
</listitem>
<listitem>
<para>The <literal>template_update_delay</literal> setting, when
specified as a string (as inside
<literal>java.util.Properties</literal>), supports time units,
like in <literal>template_update_delay=500 ms</literal>.</para>
</listitem>
<listitem>
<para>Added <literal>Environment.getCurrentTemplate()</literal>
method, which return the currently executed template (as opposed
to the main template).</para>
</listitem>
<listitem>
<para>Added
<literal>WebappTemplateLoader.setAttemptFileAccess(boolean)</literal>,
which can be used to disable the legacy trick where we try to
load templates through direct file access, so that template
updating works without restarting. Disabling URL connection
caches
(<literal>someURLBasedTemplateLoader.setURLConnectionUsesCaches(false)</literal>,
which is also the default since
<literal>incompatible_improvements</literal> 2.3.21) probably
solves that on modern Servlet containers.</para>
</listitem>
<listitem>
<para>In the <literal>FreemarkerServlet</literal>
<literal>TemplatePath</literal> init-param, paths (like
<literal>/templates</literal>) can have a
<literal>?settings(<replaceable>...</replaceable>)</literal>
postfix, with which you can set the JavaBean properties of the
resulting <literal>TemplateLoader</literal>. For example:
<literal>&lt;param-value&gt;/templates?settings(attemptFileAccess=false,
URLConnectionUsesCaches=false)&lt;/param-value&gt;</literal></para>
</listitem>
<listitem>
<para>Added
<literal>FileTemplateLoader.setEmulateCaseSensitiveFileSystem(boolean)</literal>.
This is handy when you are developing on Windows but will deploy
to a platform with case sensitive file system. The default is
<literal>false</literal>, and <literal>true</literal> is only
meant for development, not for production installations. The
default can be overridden by setting the
<literal>org.freemarker.emulateCaseSensitiveFileSystem</literal>
system property to <literal>true</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/424">424</link>]:
<literal>WebappTemplateLoader</literal> didn't find templates
that are stored in
<literal>WEB-INF/lib/*.jar/META-INF/resources</literal>. Files
under that directory are visible as
<literal>ServletContext</literal> resources since Servlet 3.0,
yet <literal>WebappTemplateLoader</literal> has usually failed
to see them because of some internal tricks.</para>
</listitem>
<listitem>
<para>Bug fixed: If a template <quote>file</quote> was
successfully opened for reading, but then there was an
<literal>IOException</literal> during reading its content, the
parser (JavaCC) acted like if the template <quote>file</quote>
was ended there, and the exception was suppressed. It's actually
a JavaCC quirk that affects many other JavaCC-based languages
too, but now FreeMarker has added a workaround in the
<literal>Template</literal> constructor, and so now an exception
will be thrown as expected.</para>
</listitem>
<listitem>
<para>Bug fixed:
<literal>InvalidReferenceException.FAST_INSTANCE</literal> could
accidentally store reference to an
<literal>Environment</literal> instance, which hence was never
garbage collected.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/426/">426</link>]:
When setting <literal>incompatible_improvements</literal> to
2.3.22, the special variable reference
<literal>.template_name</literal> in templates always returns
the name of the main (topmost) template, due to an oversight in
2.3.22. Setting <literal>incompatible_improvements</literal> to
2.3.23 restores the old, backward compatible behavior. (Note
that the old behavior that we emulate is itself broken, as it
doesn't work well with macro calls; you should use
<literal>.current_template_name</literal> or
<literal>.main_template_name</literal> instead.)</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/53/">53</link>]:
Template parsing was abnormally slow for templates with very
high number AST (abstract syntax tree) nodes on the same
hierarchy level.</para>
</listitem>
<listitem>
<para>Bug fixed: When the template was concurrently replaced on
the backing store during its first loading was still ongoing,
the older version of the template could get into the cache with
the time stamp of the new version, hence it wasn't reloaded
after the configured update delay.</para>
</listitem>
<listitem>
<para>Bug fixed: The <literal>log_template_exceptions</literal>
setting (added in 2.3.22) couldn't be set through the
<literal>Configurable.setSetting(String, String)</literal>
API.</para>
</listitem>
<listitem>
<para>Bug fixed:
<literal>StringUtil.FTLStringLiteralEnc</literal> has escaped
<literal>$</literal> (hence generating an illegal escape) and
haven't escaped <literal>{</literal> after <literal>$</literal>
and <literal>#</literal>. While this function is only used for
generating error messages by FreeMarker, it's a public methods
so anyone could use it.</para>
</listitem>
<listitem>
<para>Bugs fixed: Various canonical form glitches (they only
affect error messages as far as FreeMarker is concerned).</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Modernized Manual and site design with improved
functionality (always visible navigation tree, search inside the
Manual, etc.), thanks to Evangelia Dendramis. (Also now the Site
uses the same format and HTML generator as the Manual.)</para>
</listitem>
<listitem>
<para>Many smaller Manual and site content
updates/improvements.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Notes</title>
<para>Changes compared to 2.3.23 RC1:</para>
<itemizedlist>
<listitem>
<para><literal>.current_name_name</literal> and
<literal>.main_template_name</literal> is now missing
(<literal>null</literal>) instead of <literal>""</literal> if
the template has no name</para>
</listitem>
<listitem>
<para>Some minor error message improvements</para>
</listitem>
<listitem>
<para>Documentation refinements</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_22">
<title>2.3.22</title>
<para>Date of release: 2015-03-01</para>
<para>Note that since 2.3.22 is designed to be fully backward
compatible with the previous 2.3.x releases, <emphasis>some of the
improvements and fixes described below are only activated when you
specifically ask for 2.3.22 <quote>incompatible
improvements</quote></emphasis> (it's always clearly indicated),
because they could, with very small chance, break existing
applications. For actively maintained applications it's probably
better to allow them. See <link
linkend="pgui_config_incompatible_improvements_how_to_set">how to set
<quote>incomplatible improvements</quote> here</link>.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New built-ins: <literal>api</literal> and
<literal>has_api</literal>.
<literal><replaceable>value</replaceable>?api</literal> provides
access to the API (usually, the Java API) of
<literal><replaceable>value</replaceable></literal>, like
<literal><replaceable>value</replaceable>?api.<replaceable>someJavaMethod()</replaceable></literal>
or
<literal><replaceable>value</replaceable>?api.<replaceable>someBeanProperty</replaceable></literal>),
if the value itself supports exposing its API. This meant to be
used rarely, when you need to call a Java method of an object,
but the by-design simplistic view of the value that FreeMarker
exposes to the templates hides that, and there's no equivalent
built-in either. For example, when you put a
<literal>Map</literal> into the data-model (and you are using
the default object wrapper), <literal>myMap.myMethod()</literal>
in a template basically translates to <literal>((Method)
myMap.get("myMethod")).invoke(...)</literal> in Java, thus you
can't call <literal>myMethod</literal>. If, however, you write
<literal>myMap?api.myMethod()</literal> instead, that means
<literal>myMap.myMethod()</literal> in Java. Similarly,
<literal>myMap?api.myProperty</literal> translates to
<literal>myMap.getMyProperty()</literal> in Java, instead of to
<literal>myMap.get("myProperty")</literal>.</para>
<para><emphasis>If you can, rely on the capabilities of the FTL
types and the related built-ins as far as possible. Using
<literal>?api</literal> is only the last
resort.</emphasis></para>
<para>Using <literal>?api</literal> also happens to offer a
workaround for the lack of non-<literal>String</literal>
<literal>Map</literal> key support in FTL's
<literal>[]</literal> operator (as in
<literal>myMap[key]</literal>), because now you can write
<literal>myMap?api.get(nonStringKey)</literal>.</para>
<para><literal>?api</literal> is not enabled by default and
isn't available for all values. <link
linkend="ref_buitin_api_and_has_api">See more
here...</link></para>
</listitem>
<listitem>
<para>Identifiers (like <literal>someVariable</literal>) can now
contain minus (<literal>-</literal>), dot
(<literal>.</literal>), and colon (<literal>:</literal>) at any
position, but those characters <emphasis>must be escaped with a
preceding backslash</emphasis> (<literal>\</literal>), or else
they would be interpreted as operators. For example, to read the
variable whose name is <quote>data-id</quote>, the correct
expression is <literal>data\-id</literal>, as
<literal>data-id</literal> would be interpreted as <quote>data
minus id</quote>. This also works for named macro parameters,
which is useful when you want to accept arbitrary HTML
attributes in a catch-all parameter, like in <literal>&lt;@box
class="someCssClass" data\-id=product.id /&gt;</literal>. (When
you enumerate the catch-all parameter names inside the macro,
the key string you get is <literal>"data-id"</literal> without
<literal>\</literal> of course.)</para>
</listitem>
<listitem>
<para>Added <literal>?lower_abc</literal> and
<literal>?upper_abc</literal>. This converts
<literal>1</literal>, <literal>2</literal>,
<literal>3</literal>, etc., to the string
<literal>"a"</literal>, <literal>"b"</literal>,
<literal>"c"</literal>, etc. (or for <literal>"A"</literal>,
<literal>"B"</literal>, <literal>"C"</literal>, etc.). When
reaching <literal>"z"</literal>, it continues like
<literal>"aa"</literal>, <literal>"ab"</literal>, etc. This is
the same logic that you can see in column labels in spreadsheet
applications (like Excel or Calc). <link
linkend="ref_builtin_lower_abc">More details...</link></para>
</listitem>
<listitem>
<para>Added <literal>?keep_before_last</literal> and
<literal>?keep_after_last</literal>. Example:
<literal>"foo.bar.txt"?keep_before_last(".")</literal> returns
<literal>"foo.bar"</literal>,
<literal>"foo.bar.txt"?keep_after_last(".")</literal> returns
<literal>"txt"</literal>. (These work like
<literal>?keep_before</literal> and
<literal>?keep_after</literal>, but those look for the first
occurrence of the separator.)</para>
</listitem>
<listitem>
<para>Added many missing UNICODE letters and digits to the set
of legal identifier characters, like Korean letters (bug fixed:
[<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/129/">129</link>])</para>
</listitem>
<listitem>
<para>Error message quality improvements:</para>
<itemizedlist>
<listitem>
<para>Several improvements when calling custom JSP tags; see
them in its own section later.</para>
</listitem>
<listitem>
<para>Bug fixed: When localized lookup or template
acquisition has kicked in, error messages have still quoted
the name used for requesting the template, rather that the
actual template source name (like <literal>foo.ftl</literal>
instead of <literal>foo_en.ftl</literal>, when the template
was get as <literal>foo.ftl</literal>, but behind the scenes
was loaded from <literal>foo_en.ftl</literal>).</para>
</listitem>
<listitem>
<para><quote>Template not found</quote> errors are now more
detailed, giving hints about accidentally using
<literal>\</literal> instead of <literal>/</literal>, or
backing out of the <literal>TemplateLoader</literal>'s root
directory.</para>
</listitem>
<listitem>
<para>The <literal>#setting</literal> directive gives more
helpful error message when the setting name is not
recognized, and lists the allowed setting names or a
correction suggestion.</para>
</listitem>
<listitem>
<para>When a bad special variable name
(<literal>.<replaceable>name</replaceable></literal>) is
encountered, the list of available names is shown in the
error message.</para>
</listitem>
<listitem>
<para>When <literal>Map.get</literal> or
<literal>Map.containsKey</literal> of a wrapped
<literal>Map</literal> throws a
<literal>ClassCastException</literal> or
<literal>NullPointerException</literal>, the error will
point to the causing FTL expression (with some explanation),
rather than bubbling up as low level runtime error.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Object wrapping improvements:</para>
<itemizedlist>
<listitem>
<para><literal>DefaultObjectWrapper</literal>, only with its
<literal>incompatible_improvements</literal> set to 2.3.22
(<link linkend="topic.defaultObjectWrapperIcI">see how
here...</link>), or more precisely, with its new
<literal>useAdaptersForContainers</literal> setting set to
<literal>true</literal> (which defaults to
<literal>true</literal> when
<literal>incompatible_improvements</literal> is set to
2.3.22): It doesn't copy <literal>Map</literal>-s,
<literal>List</literal>-s, and arrays anymore when wrapping
them into <literal>TemplateModel</literal>-s (which is the
interface through with templates access all values), just
wraps them into thin <literal>TemplateModel</literal>
adapters, that will reach the original object for all
operations. The wrapped values will be instances of the new
<literal>DefaultMapAdapter</literal>,
<literal>DefaultListAdapter</literal> and
<literal>DefaultArrayAdapter</literal> classes, instead of
the legacy (copying) <literal>SimpleHash</literal> and
<literal>SimpleSequence</literal> classes. (Note that many
projects use pure <literal>BeansWrapper</literal> instead of
<literal>DefaultObjectWrapper</literal>, which has always
used the adapter approach, albeit a different implementation
of it. As the shortcomings of
<literal>DefaultObjectWrapper</literal> are fixed now, it's
always recommended over <literal>BeansWrapper</literal>, as
<literal>BeansWrapper</literal> gives quite confusing
multi-typed values and is substantially slower.)</para>
<para>While keeping backward compatibility as much as
possible was an important factor in this change, this is a
quite deep change, so you may want to <link
linkend="topic.defaultObjectWrapperSwitchToAdapters">review
the consequences and reasons here...</link> (But again, this
change is <emphasis>not</emphasis> active by default, so
merely updating FreeMarker wont risk the stability of
existing applications)</para>
</listitem>
<listitem>
<para>Added <literal>TemplateMethodModelEx
BeansWrapper.wrap(Object object, Method method)</literal>
for wrapping methods without wrapping their parent object
and without going through overloaded method selection on
invocation time.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/372/">372</link>]:
<literal>ClassCastException</literal> when a
<literal>SortedMap</literal> (typically, a
<literal>TreeMap</literal>) is wrapped with
<literal>DefaultObjectWrapper</literal> and then a 1
character long string is get from it that doesn't exist. To
fix the issue, if the wrapped <literal>Map</literal> is a
<literal>SortedMap</literal> and it's wrapped by
<literal>DefaultObjectWrapper</literal>, it won't try to
fall back to a <literal>Character</literal> key after with
the <literal>String</literal> key has got
<literal>null</literal>. (This change should be backward
compatible, because when a <literal>SortedMap</literal> has
<literal>Character</literal> keys, the initial attempt with
<literal>String</literal> key causes
<literal>ClassCastException</literal>, thus, such
<literal>SortedMap</literal>-s were never usable as FTL
hashes.)</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/368/">368</link>]:
Only with <literal>incompatible_improvements</literal> set
to 2.3.22 or with its new
<literal>useAdaptersForContainers</literal> setting set to
<literal>true</literal>: Key order and other behavioral
peculiarities of <quote>custom</quote>
<literal>Map</literal> types isn't lost anymore. The same
stands for <literal>List</literal>-s too.</para>
</listitem>
<listitem>
<para>Added new setting,
<literal>forceLegacyNonListCollections</literal>. This only
matters when <literal>useAdaptersForContainers</literal> is
<literal>true</literal>. Then, unless you set this to
<literal>true</literal>,
<literal>java.util.Collection</literal>-s that aren't
<literal>List</literal>-s (like <literal>Set</literal>-s)
will continue using <literal>SimpleSequence</literal> (i.e.,
the copying approach) instead of the adapter approach. The
default is <literal>false</literal>, at least until
<literal>incompatible_improvements</literal> 2.4.0, because
<literal>SimpleSequence</literal> gave indexed access to
these non-<literal>List</literal>-s, like in
<literal>mySet[2]</literal>, which is strange but some
existing templates may utilize this, even if only
accidentally. With
<literal>forceLegacyNonListCollections</literal> set to
<literal>false</literal>, indexed access won't be possible
for <literal>Set</literal>-s and such anymore (nor will
<literal>?first</literal> and <literal>?last</literal> work,
but <literal>?size</literal> will still do), so you may want
to retest old templates. On the other hand, you get the
advantages of the adapter approach. Hence, in new projects
it's highly recommended to set
<literal>forceLegacyNonListCollections</literal> to
<literal>false</literal>. (The adapter approach is
implemented by
<literal>DefaultNonListCollectionAdapter</literal>.)</para>
</listitem>
<listitem>
<para>Added new, <emphasis>experimental</emphasis> FTL type
interface,
<literal>freemarker.template.TemplateCollectionModelEx</literal>,
which adds the <literal>size()</literal>,
<literal>isEmpty()</literal>, and <literal>boolean
contains(TemplateModel)</literal> methods to the
<literal>TemplateCollectionModel</literal> interface. This
was added because when wrapping
<literal>java.util.Collections</literal> these extra
capabilities area available anyway, but FTL couldn't tap on
them till now. While the exact interface details are marked
as experimental, the feature itself is already utilized for
<literal>?size</literal> when setting the
<literal>forceLegacyNonListCollections</literal> property of
<literal>DefaultObjectWrapper</literal> to
<literal>false</literal> (see earlier).</para>
</listitem>
<listitem>
<para>Added new <emphasis>experimental</emphasis> interface,
<literal>freemarker.template.ObjectWrapperAndUnwrapper</literal>.
This extends <literal>ObjectWrapper</literal> with
unwrapping functionality. This functionality has already
existed for a long time in <literal>BeansWrapper</literal>
and its subclasses, like in
<literal>DefaultObjectWrapper</literal>, but it wasn't
<quote>factored out</quote> into its own published interface
that other <literal>ObjectWrapper</literal>-s could
implement. This is useful for
<literal>TemplateModel</literal> implementations that don't
want to require a <literal>BeansWrapper</literal> (or its
subclass), only the availability of the unwrapping
functionality.</para>
</listitem>
<listitem>
<para>Added new <emphasis>experimental</emphasis> interfaces
to implement <literal>?api</literal> (see it in the FTL
section): <literal>TemplateModelWithAPISupport</literal>,
<literal>ObjectAPIWrapper</literal>,
<literal>RichObjectWrapper</literal>. Note that while the
interfaces are experimental, <literal>?api</literal> itself
isn't.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><literal>FreemarkerServlet</literal> improvements:</para>
<itemizedlist>
<listitem>
<para><literal>FreemarkerServlet</literal> now supports
custom JSP EL functions (defined in TLD-s with
<literal>function</literal> XML elements). Earlier it has
ignored them. The custom EL function can be called like a
Java method, for example: <literal>&lt;#assign
u=JspTaglibs["/WEB-INF/utils.tld"]&gt; ...
${u.truncate(title, 25)}</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed: Error message was unhelpful when there was
a type mismatch between the actual and the expected type of
a custom tag parameter. This was a very frequent problem of
users who call JSP taglibs from FTL (the typical
"java.lang.IllegalArgumentException: argument type
mismatch", without any FTL context). Now it's a proper error
with explanation, solution tip, and FTL error
position/quotation.</para>
</listitem>
<listitem>
<para>RFE resolved [<link
xlink:href="https://sourceforge.net/p/freemarker/feature-requests/113/">113</link>]
[<link
xlink:href="https://sourceforge.net/p/freemarker/feature-requests/114/">114</link>]:
<literal>FreemarkerServlet</literal> can now discover
<literal>META-INF/**/*.tld</literal>-s that are visible for
the class loader but aren't in
<literal>WEB-INF/lib/*.jar</literal>-s. For this feature to
be active, you must setup the extra TLD lookup with the
<literal>MetaInfTldSources</literal> and/or
<literal>ClasspathTlds</literal>
<literal>FreemarkerServlet</literal> init-params (see the
<link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">Java
API documentation of
<literal>FreemarkerServlet</literal></link> for the
description of these). For example, if you run your
application from Eclipse with an embedded Servlet container,
and thus the tag library jar-s aren't on the standard
locations but are in the classpath like any other
dependencies, now you can just write:</para>
<programlisting role="unspecified">&lt;init-param&gt;
&lt;param-name&gt;MetaInfTldSources&lt;/param-name&gt;
&lt;param-value&gt;classpath&lt;/param-value&gt;
&lt;/init-param&gt;</programlisting>
<para>and then all the <literal>META-INF</literal>
directories that are visible for the class loader will be
searched for TLD-s.</para>
</listitem>
<listitem>
<para><literal>MetaInfTldSources</literal> and
<literal>ClasspathTlds</literal> can also be appended to or
replaced by the values of Java system properties
<literal>org.freemarker.jsp.metaInfTldSources</literal> and
<literal>org.freemarker.jsp.classpathTlds</literal>,
respectively. Thus one can adjust these in the Eclipse run
configuration without modifying the
<literal>web.xml</literal>. (See the <link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">Java
API documentation of
<literal>FreemarkerServlet</literal></link> for
more.)</para>
</listitem>
<listitem>
<para><literal>FreemarkerServlet</literal> now recognizes
the
<literal>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</literal>
servlet context attribute, and adds entries to
<literal>MetaInfTldSources</literal> (introduced above) from
it.</para>
</listitem>
<listitem>
<para>Added <literal>protected
FreemarkerServlet.createTaglibFactory()</literal> to allow
fine tuning the settings of the
<literal>TaglibFactory</literal>. It now have a few setters,
like <literal>setObjectWrapper</literal>,
<literal>setMetaInfTldSource</literal>, etc.</para>
</listitem>
<listitem>
<para>Added new servlet init-param,
<literal>BufferSize</literal>. This sets the buffer size via
<literal>HTTPServletResponse.setBufferSize()</literal> if
the response state still allows that, ignores it
otherwise.</para>
</listitem>
<listitem>
<para>The <literal>TemplatePath</literal> servlet init-param
now supports a new kind of path, that looks like
<literal>classpath:com/example/myapp/templates</literal>.
This is similar to the old
<literal>class://com/example/myapp/templates</literal>, but
it uses the Thread Context Class Loader of the thread that
initializes <literal>FreemarkerSerlvet</literal>, and thus
will work even if <literal>freemarker.jar</literal> is not
local to the web application. <literal>class://</literal>
has the problem that it uses the defining class loader of
<literal>FreemarkerSerlvet</literal> itself (or of its
subclass).</para>
</listitem>
<listitem>
<para>If <literal>incompatible_improvements</literal> is set
to 2.3.22 (or higher), the <literal>TemplatePath</literal>
servlet init-param supports specifying multiple comma
separated paths inside
<literal>[<replaceable>...</replaceable>]</literal>, like
<literal>&lt;param-value&gt;[ WEB-INF/templates,
classpath:com/example/myapp/templates
]&lt;/param-value&gt;</literal>. This internally creates a
<literal>freemarker.cache.MultiTemplateLoader</literal>.</para>
</listitem>
<listitem>
<para>Added new servlet <literal>init-param</literal>,
<literal>ExceptionOnMissingTemplate</literal>. Setting this
to <literal>true</literal> changes the behavior on
template-not-found errors to similar to what you experience
with other kind of template exceptions (a HTTP 500
<quote>Internal Server error</quote> response on most
setups). When it's <literal>false</literal> (the legacy
behavior), you only get a HTTP 404 <quote>Not found</quote>.
While that's also how JSP views work, this turns out to be a
problem, because some frameworks give 404 to the visitor too
if the MVC view gives 404. But to get to the point where you
forward to the MVC View, the visitor had to visit a valid
URL, only that page misses its View, so its broken on the
server side, so it should be a 500.</para>
</listitem>
<listitem>
<para>Added new overridable method:
<literal>FreemarkerServlet.createDefaultObjectWrapper()</literal>.
This can be used for what
<literal>createObjectWrapper()</literal> is usually
overridden for, but without unwillingly disabling the
processing of the related init-params (like of
<literal>object_wrapper</literal>).</para>
</listitem>
<listitem>
<para>Improved (or fixed) error logging: Now logs will
always get into FreeMarker's own log, not only into the
servlet container log. Also, earlier template-not-found and
template parsing error details logs were sometimes lost,
depending on the servlet container.</para>
</listitem>
<listitem>
<para>Bug fixed, only active with
<literal>incompatible_improvements</literal> set to 2.3.22
(or higher): Some kind of values, when put into the JSP
<emphasis>page</emphasis> scope (via
<literal>#global</literal> or via the JSP
<literal>PageContext</literal> API) and later read back with
the JSP <literal>PageContext</literal> API (typically in a
custom JSP tag), might come back as FreeMarker
<literal>TemplateModel</literal> objects instead of as
objects with a standard Java type. Other Servlet scopes
aren't affected. It's highly unlikely that something expects
the presence of this bug. The affected values are of the FTL
types listed below, and to trigger the bug, they either had
to be created directly in the template (like as an FTL
literal or with
<literal>?date</literal>/<literal>time</literal>/<literal>datetime</literal>),
or you had to use <literal>DefaultObjectWrapper</literal> or
<literal>SimpleObjectWrapper</literal> (or a subclass of
them):</para>
<itemizedlist>
<listitem>
<para>FTL date/time/date-time values may came back as
<literal>freemarker.template.SimpleDate</literal>-s, now
they come back as <literal>java.util.Date</literal>-s
instead.</para>
</listitem>
<listitem>
<para>FTL sequence values may came back as
<literal>SimpleSequence</literal>-s, now they come back
as <literal>java.util.List</literal>-s as expected. This
stands assuming that the
<literal>object_wrapper</literal> configuration setting
is a subclass of <literal>BeansWrapper</literal> (such
as <literal>DefaultObjectWrapper</literal>), but that's
practically always the case in applications that use
FreeMarker's JSP extension (otherwise it can still work,
but it depends on the quality and capabilities of the
<literal>ObjectWrapper</literal> implementation).</para>
</listitem>
<listitem>
<para>FTL hash values may came back as
<literal>SimpleHash</literal>-es, now they come back as
<literal>java.util.Map</literal>-s as expected (again,
assuming that the object wrapper is a subclass of
<literal>BeansWrapper</literal>).</para>
</listitem>
<listitem>
<para>FTL collection values may came back as
<literal>SimpleCollection</literal>-s, now they come
back as <literal>java.util.Collection</literal>-s as
expected (again, assuming that the object wrapper is a
subclass of <literal>BeansWrapper</literal>).</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fixed: Now <literal>*.tld</literal> files are
searched in <literal>WEB-INF/</literal> and in all its
subdirectories recursively. Earlier they were only searched
directly under <literal>WEB-INF/</literal> and
<literal>WEB-INF/lib/</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed: Leading and trailing whitespace in TLD-s
inside the <literal>name</literal> and
<literal>tag-class</literal> elements is now removed.</para>
</listitem>
<listitem>
<para>Unwanted behavior fixed: In case multiple TLD-s map to
the same tag library URI, now
<literal>WEB-INF/**/*.tld</literal>-s has priority over
<literal>META-INF/**/*.tld</literal>-s coming from jar-s or
classpath directories. Earlier, it was the other way around,
except that <literal>META-INF/lib/*.tld</literal>-s could
still take precedence randomly. While the JSP specification
(2.2) explicitly states that the order is not defined and
shouldn't be relied upon, it's just logical that if someone
puts a TLD directly under <literal>WEB-INF</literal>, he
meant that to be used in that particular web application,
rather than the TLD-s coming from the dependency jars which
are often shared by multiple web applications.</para>
</listitem>
<listitem>
<para>Bug fixed: Defaults set in an overridden
<literal>FreemarkerServlet.createConfiguration</literal>
won't be accidentally overwritten by
<literal>FreemarkerServlet</literal>'s factory defaults
anymore. This was a problem with theses settings only:
<literal>template_exception_handler</literal>,
<literal>log_template_exceptions</literal>,
<literal>object_wrapper</literal>,
<literal>template_loader</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed: If you had multiple
<literal>FreemarkerServlet</literal>-s with different
configuration settings in the same servlet context, that
could lead to malfunction. (Normally, you only have one,
just like there's only one servlet that processes
<literal>*.jsp</literal>.)</para>
</listitem>
<listitem>
<para>Removed all the <literal>xsd</literal> files
(<literal>web-app</literal> and <literal>taglib</literal>
schemas) from the FreeMarker artifact and from the XML
entity resolver, as they were unused during XML
parsing.</para>
</listitem>
<listitem>
<para>Generally improved implementation quality
(maintainability, error messages, performance bug fixes,
test coverage) and better API documentation.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Logging facility improvements:</para>
<itemizedlist>
<listitem>
<para>Just like earlier, when auto-selecting the logger
library (the default behavior), FreeMarker choses Log4j if
it's available. But now, if that turns out to be
<literal>log4j-over-slf4j</literal>, FreeMarker will use
SLF4J directly instead. (This fixes the issue where the
logged location points to FreeMarker's log adapter class
instead of the real call place.)</para>
</listitem>
<listitem>
<para>FreeMarker now recognizes the
<literal>org.freemarker.loggerLibrary</literal> system
property, which specifies which logger to use, like
<literal>java <replaceable>...</replaceable>
-Dorg.freemarker.loggerLibrary=SLF4J</literal>. This option
deprecates
<literal>Logger.selectLoggerLibrary(int)</literal> as that
was inherently unreliable (because you usually can't control
class initialization order very well). The system property
has precedence over
<literal>Logger.selectLoggerLibrary</literal>.</para>
</listitem>
<listitem>
<para>Generally improved implementation quality (more info
printed when something fails, etc.).</para>
</listitem>
<listitem>
<para>New configuration setting:
<literal>log_template_exceptions</literal>
(<literal>Configuration.setLogTemplateExceptions(boolean)</literal>).
This specifies if <literal>TemplateException</literal>-s
thrown by template processing are logged by FreeMarker or
not. The default is <literal>true</literal> for backward
compatibility, but that results in logging the exception
twice in properly written applications, because there the
<literal>TemplateException</literal> thrown by the public
FreeMarker API is also logged by the caller (even if only as
the cause exception of a higher level exception). Hence, in
modern applications it should be set to
<literal>false</literal>. (Note that this setting has no
effect on the logging of exceptions caught by
<literal>#attempt</literal>/<literal>#recover</literal>;
those are always logged.)</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><literal>Environment</literal> and custom directive
related improvements:</para>
<itemizedlist>
<listitem>
<para>Added
<literal>Environment.getCurrentDirectiveCallPlace()</literal>,
which returns a <literal>DirectiveCallPlace</literal> object
when called from a custom directive (i.e., from
<literal>TemplateDirectiveModel.execute()</literal>). The
<literal>DirectiveCallPlace</literal> objects lets you
associate an arbitrary object to the directive invocation
inside the template, which can be used for call-place-bound
caching (like the minification of non-dynamic nested
content). See <literal>DirectiveCallPlace</literal> in the
Java API documentation for more.</para>
</listitem>
<listitem>
<para>Added
<literal>Environment.getMainTemplate()</literal>. Deprecated
the ambiguous (and often broken: [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/145/">145</link>])
<literal>Environment.getTemplate()</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Template loading:</para>
<itemizedlist>
<listitem>
<para>Added new <literal>Configuration</literal> setting,
<literal>template_lookup_strategy</literal>
(<literal>Configuration.setTemplateLookupStrategy(TemplateLookupStrategy)</literal>).
This allows customizing what
<literal>TemplateLoader</literal>-level names will be tried
when a template is requested. With this you can, for
example, define a custom localized lookup sequence instead
of the default (which looks like:
<literal>foo_de_LU_MAC.ftl, foo_de_LU.ftl,
foo_de.ftl,</literal><literal> foo.ftl</literal>).</para>
</listitem>
<listitem>
<para>Added new
<literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>
parameter, <literal>Object customLookupCondition</literal>.
This parameter can be used by custom a
<literal>TemplateLookupStrategy</literal> to deduce the
actual template name(s) from the requested name (similarly
to as the default lookup strategy does that based on the
locale). For example, on a multi-domain Web site, one may
want to define some templates that are specialized to a
domain, and thus use the domain name as the custom lookup
condition. Then, when <literal>foo.ftl</literal> is
requested, a custom
<literal>TemplateLookupStrategy</literal> could first look
for <literal>@somedomain.com/foo.ftl</literal>, and then for
<literal>@default/foo.ftl</literal>. See the JavaDoc of the
relevant
<literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>
overload for more details; note there the requirements
regarding the <literal>hashCode</literal> and
<literal>equals</literal> of the
<literal>customLookupCondition</literal>.</para>
</listitem>
<listitem>
<para>Added new <literal>Configuration</literal> setting,
<literal>template_name_format</literal>
(<literal>Configuration.setTemplateNameFormat(TemplateNameFormat)</literal>).
This allows specifying the naming rules used by FreeMarker.
For now, custom implementations aren't allowed, and you can
only chose between
<literal>TemplateNameFormat.DEFAULT_2_3_0</literal> (the
default) and <literal>DEFAULT_2_4_0</literal> (recommended,
at least for new projects). <literal>DEFAULT_2_4_0</literal>
has several advantages, but isn't fully backward compatible
(though most applications won't be affected). For typical
mistakes like using backslash instead of slash, or backing
out of the root, it gives
<literal>MalformedTemplateNameFormatException</literal>
instead of <literal>TempalteNotFoundException</literal>. It
allows scheme names to be terminated with
<literal>:</literal> alone, instead of a
<literal>://</literal> (which is also supported), like in
<literal>classpath:foo/bar.ftl</literal>. It fixes numerous
legacy glitches (bugs), mostly related to the interpretation
of <literal>..</literal> after special steps like
<literal>.</literal> or <literal>*</literal>. See the full
list of differences in the <link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/cache/TemplateNameFormat.html#DEFAULT_2_4_0">Java
API documentation of
<literal>TemplateNameFormat.DEFAULT_2_4_0</literal></link>.</para>
</listitem>
<listitem>
<para><literal>ClassTemplateLoader</literal> now can be
created by specifying a <literal>ClassLoader</literal>
directly, rather than by specifying a base
<literal>Class</literal>. That is, now there's
<literal>ClassTemplateLoader(ClassLoader, String)</literal>
constructor, and also a
<literal>Configuration.setClassLoaderForTemplateLoading(ClassLoader,
String)</literal> method.</para>
</listitem>
<listitem>
<para>Added new exception,
<literal>TemplateNotFoundException</literal>, which is now
used instead of <literal>TemplateNotFoundException</literal>
when getting a template. As it extends
<literal>TemplateNotFoundException</literal>, this change is
backward compatible. The main goal was to counter the common
misunderstanding that template paths are real file paths.
However, the new exception also has the benefit that it can
give additional FreeMarker-specific information about the
error, like right now it has
<literal>getTemplateName()</literal> and
<literal>getCustomLookupCondition()</literal>
methods.</para>
</listitem>
<listitem>
<para><literal>Template</literal>-s now have a
<literal>getSourceName()</literal> method, in additionally
to <literal>getName()</literal>. These two return the same
as far as no localized lookup or acquisition
(<literal>*</literal> in the name) or other lookup strategy
was actively involved. But when it was,
<literal>getSourceName()</literal> gives the name with which
the template was actually loaded from the
<literal>TemplateLoader</literal>, while
<literal>getName()</literal> returns (and had always
returned) the name with which the template was requested (in
canonicalized form). <literal>getName()</literal> is used
for everything (like for relative inclusion resolution),
except for location information in error messages, which now
uses <literal>getSourceName()</literal>. Also,
<literal>TemplateException</literal> now has a
<literal>getSourceName()</literal> method.</para>
</listitem>
<listitem>
<para><literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>
overloads now accept <literal>null</literal> for the
<literal>locale</literal> and <literal>encoding</literal>
parameters, in which case they use the same defaults as the
overloads where the parameter is omitted.</para>
</listitem>
<listitem>
<para>Debugger SPI implementators, attention: The
<literal>DebugBreak</literal> instruction will now send the
<literal>sourceName</literal> of the template to the
<literal>suspendEnvironmentSpi</literal> callback, rather
than its <literal>name</literal>. You should also use the
<literal>sourceName</literal> in
<literal>registerTemplateSpi</literal> and such, not the
<literal>name</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Configuration:</para>
<itemizedlist>
<listitem>
<para>Added
<literal>Configuration.unset<replaceable>Xxx</replaceable></literal>
and
<literal>is<replaceable>Xxx</replaceable>ExplicitlySet</literal>
methods for several settings. Unsetting a setting makes it
behave as if
<literal>set<replaceable>Xxx</replaceable></literal> was
never called, thus the setting will use the default value
that fits the current
<literal>incompatible_improvements</literal> value and will
be adjusted as <literal>incompatible_improvements</literal>
is changed later.</para>
</listitem>
<listitem>
<para>When configuring FreeMarker from
<literal>java.util.Properties</literal> (or with
<literal>String</literal>-<literal>String</literal>
name-value pairs in general):</para>
<itemizedlist>
<listitem>
<para>The <literal>default</literal> setting value is
now recognized by
<literal>template_exception_handler</literal>,
<literal>template_storage</literal>,
<literal>template_loader</literal> (and by the new
<literal>template_lookup_strategy</literal> and
<literal>template_name_format</literal>) settings, and
it causes
<literal>Configuration.unset<replaceable>Xxx</replaceable>()</literal>
to be called.</para>
</listitem>
<listitem>
<para>Bug fixed: When setting
<literal>object_wrapper</literal> to
<literal>default</literal> (as opposed to not specifying
it), it has ignored the
<literal>incompatible_improvements</literal> and has
always used
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal>. This
fix only matters when
<literal>incompatible_improvements</literal> is exactly
2.3.21, as that's when the default object wrapper was
changed from
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal> to the
result of <literal>new
DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_21).build()</literal>,
which is a bit different singleton, as it has read-only
configuration settings and bug fixed overloaded method
selection rules. To use
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal>
regardless of the value of the
<literal>incompatible_improvements</literal> setting,
use the new <literal>default_2_3_0</literal>
value.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fixed: Changing the value of the
<literal>localized_lookup</literal> setting now empties the
template cache, so that old lookup results won't be reused.
(This of course only matters if you change this setting
under an already running service, which is very
unlikely.)</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Miscellaneous:</para>
<itemizedlist>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/145/">145</link>],
active only with
<literal>incompatible_improvements</literal> set to 2.3.22
(or higher): <literal>#include</literal> and
<literal>#nested</literal> doesn't change the parent
<literal>Template</literal> (see
<literal>Configurable.getParent()</literal>) of the
<literal>Environment</literal> anymore to the
<literal>Template</literal> that's included or where
<literal>#nested</literal> <quote>returns</quote> to. Thus,
the parent of <literal>Environment</literal> will be now
always the main <literal>Template</literal>. (The main
<literal>Template</literal> is the
<literal>Template</literal> whose <literal>process</literal>
or <literal>createProcessingEnvironment</literal> method was
called to initiate the output generation.) Note that this
only matters if you have set settings directly on
<literal>Template</literal> objects (not to be confused with
setting settings in templates via
<literal>#setting</literal>, which just modifies the
<literal>Environment</literal>, and so isn't affected by
this fix), and almost nobody does that. Also note that macro
calls have never changed the <literal>Environment</literal>
parent to the <literal>Template</literal> that contains the
macro definition, so there's no change there now.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/419/">419</link>]:
FreeMarker doesn't fail anymore when it has no permission to
read Java system properties, like when used in unsigned
applets. It just logs some warnings.</para>
</listitem>
<listitem>
<para><literal>HTML_DEBUG</literal> and
<literal>DEBUG</literal>
<literal>TemplateExceptionHandler</literal> output now
contains a warning like <quote>HTML_DEBUG mode; use RETHROW
in production!</quote>, due to frequent misuse.</para>
</listitem>
<listitem>
<para>Some fixes and improvements in template canonical form
output, and as a consequence of that, in FTL stack trace
instruction displaying.</para>
</listitem>
<listitem>
<para>Marked some historically public but otherwise internal
API-s as deprecated, so that the disclaimer is more apparent
in IDE-s.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
<section>
<title>Notes</title>
<para xml:id="topic.defaultObjectWrapperSwitchToAdapters">The
consequences and reasons of introducing adapter approach for
container types in <literal>DefaultObjectWrapper</literal> when its
incompatibleImprovements is set to 2.3.22:</para>
<itemizedlist>
<listitem>
<para>With the new approach (the adapter approach), the key
order of <literal>Map</literal>-s is never lost. The copying
approach could only keep that for <literal>HashMap</literal>
subclasses (such as <literal>LinkedHashMap</literal>) and
<literal>SortedMap</literal>-s (such as
<literal>TreeMap</literal>), but not for more exotic
<literal>Map</literal>-s, like Guava's
<literal>ImmutableMap</literal>. Also, any other behavioral
peculiarities of the original <literal>Map</literal> (e.g., case
insensitive key lookup) is kept now.</para>
</listitem>
<listitem>
<para>The exact type and identity of the
<literal>Map</literal>/<literal>List</literal> is kept when the
wrapped value is passed back to a Java method from the template.
With the legacy approach the Java methods have received a
<literal>Map</literal> or <literal>List</literal> of a special
FreeMarker specific type (that acted as an adapter for the
<literal>TemplateModel</literal>).</para>
</listitem>
<listitem>
<para>Performance characteristics change, mostly for the better,
but it depends on the application. If the template reads the
<emphasis>same(!)</emphasis> entry <emphasis>from the data
model</emphasis> roughly once or twice (or not at all), which is
typical, them the adapter approach gives better results,
otherwise the legacy copying approach is faster (as it can reuse
the wrapped entry from the previous read), though this slowdown
certainly not a concern for most applications. The performance
of the new adapter approach is more predictable, because it has
no initial <quote>spike</quote> to set up the container copy
(especially painful for huge collections), instead the
performance is linearly proportional to the number of data model
reads (and not to the number of collection entries).</para>
</listitem>
<listitem>
<para>If the
<literal>Map</literal>/<literal>List</literal>/array is changed
after it was wrapped, the change will now become visible in the
data-model. With the copying approach, the wrapped value was a
shallow-snapshot of the original
<literal>Map</literal>/<literal>List</literal>/array. While it's
unlikely that someone has deliberately utilized this, it's a
risk factor when switching to adapters.</para>
</listitem>
<listitem>
<para>It's theoretically possible that some code (mostly
<literal>TemplateDirectiveModel</literal> implementations)
mistakenly assumed that wrapped <literal>Map</literal>-s are
<literal>SimpleHash</literal>-es, and wrapped
<literal>List</literal>-s are
<literal>SimpleSequence</literal>-s, etc., instead of them just
being <literal>TemplateHashModel</literal>-s and
<literal>TemplateSequenceModel</literal>-s. Such code was always
wrong, but now it will indeed break, so it's a risk
factor.</para>
</listitem>
<listitem>
<para>As now the exact type of the wrapped original object is
used for overloaded method selection, the choice can be
different (and similar to what it would be with pure
<literal>BeansWrapper</literal>). It's difficult to find cases
where this matters. A change is most probable around arrays, as
with the copying approach they were unwrapped to
<literal>List</literal>-s, not to the original array. As the
overloaded method mechanism can convert between arrays and lists
(in both directions), it's usually not a problem. But, it
doesn't do conversion between different array types when the
overloaded method has various types on the parameter position of
the array, so that's a risk factor.</para>
</listitem>
<listitem>
<para><literal>SimpleHash</literal> and
<literal>SimpleSequence</literal> haven't become deprecated.
They are still used for hashes and sequences created in FTL, and
are recommended for values that are built specifically to be
used from templates, rather than wrapping an already existing
<literal>Map</literal> or <literal>List</literal> or
array.</para>
</listitem>
<listitem>
<para><literal>List</literal>-s and <literal>Map</literal>-s
that are exposed to templates in multiple threads are now under
greater stress regarding their correct operation under
multi-threaded read-only access. This is because the adapters
won't copy their contents into well known
<literal>List</literal> and <literal>Map</literal>
implementations (<literal>HashMap</literal>,
<literal>ArrayList</literal>, etc.) before accessing them from
multiple threads. So this is mostly a concern with custom
<literal>List</literal> and <literal>Map</literal>
implementations, which aren't as mature as the standard Java
classes. Note that this was always like so with pure
<literal>BeansWrapper</literal>, which is used by a lot of
projects/frameworks (like by Struts) for a long time, so it's
not an uncharted territory.</para>
</listitem>
<listitem>
<para>When the wrapped <literal>List</literal> is a
<literal>AbstractSequentialList</literal> (like a
<literal>LinkedList</literal>), the resulting adapter will
implement <literal>TemplateCollectionModel</literal> for more
efficient enumeration (<literal>#list</literal>-ing), in
additionally to <literal>TemplateSequenceModel</literal> of
course. <literal>TemplateCollectionModel</literal> allows FTL to
traverse the list without accessing elements by index. With the
legacy copying approach
<literal>TemplateCollectionModel</literal> wasn't implemented as
it wasn't needed for efficient enumeration there.</para>
</listitem>
<listitem>
<para>Iterators (when you put them directly into the data-model)
are wrapped into <literal>DefaultIteratorAdapter</literal>
instead of <literal>SimpleCollection</literal>. This has two
consequences:</para>
<itemizedlist>
<listitem>
<para>The wrapped <literal>Iterator</literal> is now
unwrapped properly to the original Java object when it's
passed to Java method from the template.</para>
</listitem>
<listitem>
<para>Wrapped <literal>Iterator</literal>-s (not to be
confused with <literal>Iterable</literal>) aren't
thread-safe anymore, to spare some synchronizations, after
all, exposing the same <literal>Iterator</literal> to
multiple parallel template executions doesn't make much
sense. This shouldn't be a migration concern, as even
earlier, only one of those template executions could succeed
(the <quote>content</quote> of <literal>Iterator</literal>-s
wasn't copied, so the one who first accessed it become the
exclusive owner). The change is just that earlier it was
guaranteed that the other threads will fail (that was the
thread-safe about it), while now there are no such
guarantees.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_21">
<title>2.3.21</title>
<para>Date of release: 2014-10-12</para>
<para>Note that since 2.3.21 is designed to be fully backward
compatible with the previous 2.3.x releases, <emphasis>some of the
improvements and fixes described below are only activated when you
specifically ask for 2.3.21 <quote>incompatible
improvements</quote></emphasis>, because they could, with very small
chance, break existing applications. If the dependent project is still
actively developed, allowing 2.3.21 "incompatible improvements" is
highly recommended. See <link
linkend="pgui_config_incompatible_improvements_how_to_set">how to set
<quote>incomplatible improvements</quote> here</link>.</para>
<para>Note that we have changed our proprietary BSD-style license to
Apache License, Version 2.0. See the <link linkend="app_license">new
license here</link>.</para>
<para>Note that the minimum required Java version was increased from
1.2 to 1.4.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Improved ranges:</para>
<itemizedlist>
<listitem>
<para>Added ranges with exclusive end:
<literal><replaceable>start</replaceable>..&lt;<replaceable>end</replaceable></literal>
(also can be written as
<literal><replaceable>start</replaceable>..!<replaceable>end</replaceable></literal>).
<link
linkend="dgui_template_exp_direct_ranges">More...</link></para>
</listitem>
<listitem>
<para>Added length limited ranges:
<literal><replaceable>start</replaceable>..*<replaceable>length</replaceable></literal>:
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. Thus, for example, to take the first 10 characters
from the string <literal>s</literal>, or less if
<literal>s</literal> is shorter than 10 characters, you can
use <literal>s[0..*10]</literal>. <link
linkend="dgui_template_exp_seqenceop_slice">More...</link></para>
</listitem>
<listitem>
<para>Square bracket now accepts range values from any
source, like <literal>&lt;#assign r = 1..3&gt;
${'foobar'[r]}</literal> will print
<literal>"oob"</literal>. Earlier it has only supported
ranges that were specified directly inside the square
brackets, like <literal>'foobar'[1..3]</literal>.</para>
</listitem>
<listitem>
<para>When slicing a sequence with a right-unbounded range,
it's now allowed to have a range start index that's one
higher than the last index of the sliced sequence. For
example, <literal>['x', 'y'][2..]</literal> is not an error
anymore, but an empty sequence. (Of course, <literal>['x',
'y'][3..]</literal> is still an error.)</para>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?substring(<replaceable>from</replaceable>,
<replaceable>toExclusive</replaceable>)</literal> and
<literal><replaceable>someString</replaceable>?substring(<replaceable>from</replaceable>)</literal>
are now deprecated; use this slicing expression instead:
<literal><replaceable>someString</replaceable>[<replaceable>from</replaceable>..&lt;<replaceable>toExclusive</replaceable>]</literal>
and
<literal><replaceable>someString</replaceable>[<replaceable>from</replaceable>..]</literal>.
A warning if you are processing XML: Since slicing
expressions work both for sequences and strings, and XML
nodes in FTL are typically both sequences and strings at the
same time, there the equivalent expression is
<literal><replaceable>someXmlNode</replaceable>?string[<replaceable>from</replaceable>..&lt;<replaceable>toExclusive</replaceable>]</literal>
and
<literal><replaceable>exp</replaceable>?string[<replaceable>from</replaceable>..]</literal>,
because without the <literal>?string</literal> it would
slice the node sequence instead of the text value of the
node.</para>
</listitem>
<listitem>
<para>If the <literal>incompatible_improvements</literal> in
the FreeMarker configuration is set to at least 2.3.21,
right-unbounded ranges become readable (like
<literal>#list</literal>-able). Earlier they could only be
used for slicing, and behaved like empty sequences
otherwise.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>New built-in, <literal>?url_path</literal>: This is the
same as <link linkend="ref_builtin_url">the
<literal>url</literal> built-in</link>, except that it doesn't
escape slash (<literal>/</literal>) characters. This meant to be
used for converting paths (like paths coming from the OS or some
content repository) that use slash (not backslash!) to a path
the can be inserted into the path part of an URL.</para>
</listitem>
<listitem>
<para>New built-ins for string manipulation:</para>
<itemizedlist>
<listitem>
<para><literal><replaceable>someString</replaceable>?keep_before(<replaceable>substring</replaceable>[,
<replaceable>flags</replaceable>])</literal>: <link
linkend="ref_builtin_keep_before">More...</link></para>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?keep_after(<replaceable>substring</replaceable>[,
<replaceable>flags</replaceable>])</literal>: <link
linkend="ref_builtin_keep_after">More...</link></para>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?remove_beginning(<replaceable>substring</replaceable>)</literal>:
<link
linkend="ref_builtin_remove_beginning">More...</link></para>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?remove_ending(<replaceable>substring</replaceable>)</literal>:
<link
linkend="ref_builtin_remove_ending">More...</link></para>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?ensure_starts_with(<replaceable>substring</replaceable>[,
<replaceable>substitution</replaceable>[,
<replaceable>flags</replaceable>]])</literal>: <link
linkend="ref_builtin_ensure_starts_with">More...</link></para>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?ensure_ends_with(<replaceable>substring</replaceable>)</literal>:
<link
linkend="ref_builtin_ensure_ends_with">More...</link></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><literal><replaceable>someString</replaceable>?number</literal>
now recognizes all XML Schema number formats, like
<literal>NaN</literal>, <literal>INF</literal>,
<literal>-INF</literal>, plus the Java-native formats
<literal>Infinity</literal> and
<literal>-Infinity</literal>.</para>
</listitem>
<listitem>
<para>If <literal>incompatible_improvements</literal> in the
FreeMarker configuration is set to at least 2.3.21,
<literal><replaceable>someNumber</replaceable>?c</literal> will
return <literal>"INF"</literal>, <literal>"-INF"</literal> and
<literal>"NaN"</literal> for positive/negative infinity and IEEE
floating point Not-a-Number, respectively. These are the XML
Schema compatible representations of these special values.
Earlier it has returned what
<literal>java.text.DecimalFormat</literal> did with US locale,
none of which was understood by any (common) computer
language.</para>
</listitem>
<listitem>
<para>New built-in:
<literal><replaceable>someString</replaceable>?boolean</literal>.
This is for example useful for converting "true" and "false"
strings coming from XML to real boolean values. <link
linkend="ref_builtin_boolean">More...</link></para>
</listitem>
<listitem>
<para>Date/time/date-time related changes:</para>
<itemizedlist>
<listitem>
<para>Added new kind of
<literal>date_format</literal>/<literal>datetime_format</literal>/<literal>time_format</literal>
setting values: XML Schema formats, starting with
<literal>"xs"</literal> and ISO 8601:2004 formats, starting
with <literal>"iso"</literal>. The format string can be
continued with various space (or <literal>_</literal>)
separated options, like <literal>h</literal> or
<literal>m</literal> or <literal>s</literal> or
<literal>ms</literal> for setting shown accuracy,
<literal>nz</literal> or <literal>fz</literal> for setting
time zone offset visibility, and <literal>u</literal> or,
<literal>fu</literal> for using UTC time zone . For example,
to use ISO 8601 with minute precision and without the zone
offset being shown, set the
<literal>datetime_format</literal> setting to <literal>"iso
m nz"</literal>, so then the output will be like
<literal>2014-09-03T20:56</literal>. <link
linkend="topic.dateTimeFormatSettings">More...</link></para>
</listitem>
<listitem>
<para>Because anything that's accepted as
<literal>date_format</literal>/<literal>datetime_format</literal>/<literal>time_format</literal>
setting value can also be used with the
<literal>?string</literal> and
<literal>?date</literal>/<literal>?time</literal>/<literal>?datetime</literal>
build-ins, you can use the new formats like
<literal>someDate?string.xs</literal> and
<literal>someString?date.xs</literal>. (For the
<literal>"xs"</literal> and <literal>"iso"</literal>
formats, <literal>_</literal> can be used instead of space,
which means that, for example, you can write
<literal>lastModified?string.iso_m_u</literal> instead of
the more verbose <literal>lastModified?string["iso m
u"]</literal>.)</para>
</listitem>
<listitem>
<para>That <literal>"iso"</literal> and
<literal>"xs"</literal> are now possible
<literal>date_format</literal>/<literal>datetime_format</literal>/<literal>time_format</literal>
setting values also means that such values can now be parsed
too via
<literal>?date</literal>/<literal>?time</literal>/<literal>?datetime</literal>.
The main application is with processing XML DOM-s, as there
values are coming in as strings, and now you can do
something like <literal>order.confirmDate?date.xs</literal>
to convert them to real dates.</para>
</listitem>
<listitem>
<para>The <link
linkend="ref_builtin_date_iso"><literal>?iso_...</literal>
built-ins</link> are now deprecated in favor of the new
setting values described above. They can be set as the
default date/time/date-time format, seamlessly fit into the
formatting architecture (and thus can parse strings too),
and has more/better options (<literal>ms</literal> always
shows 3 millisecond digits, <literal>fz</literal> for
forcing showing time zone offset).</para>
</listitem>
<listitem>
<para>If the <quote>incompatible improvements</quote>
configuration setting is at least 2.3.21, the
<literal>?iso_...</literal> built-ins won't show time zone
offset for <literal>java.sql.Time</literal> values anymore.
Most databases store time values that aren't in any time
zone, but just store hour, minute, second, and decimal
second field values, so showing the time zone doesn't make
sense. (Notable exceptions are PostgreSQL "time with time
zone" columns, where
<literal><replaceable>mzTime</replaceable>?string.iso_fz</literal>
could be used.)</para>
</listitem>
<listitem>
<para>Added <literal>?is_time</literal>,
<literal>?is_datetime</literal>,
<literal>?is_date_only</literal> (should be called
<literal>?is_date</literal>, but that was already taken) and
<literal>?is_unknown_date_like</literal> to check the exact
type of a date-like value.</para>
</listitem>
<listitem>
<para><literal>?is_date</literal> is now a deprecated name,
use <literal>?is_date_like</literal> instead. This is
because <literal>?is_date</literal> sounds like it checks if
the value is a date without time part, but actually it also
returns <literal>true</literal> for time, date-time, and
unknown date-like values.</para>
</listitem>
<listitem>
<para>Added <literal>?date_if_unknown</literal>,
<literal>?time_if_unknown</literal> and
<literal>?datetime_if_unknown</literal> built-ins, which
mark a date-like value with some of the sub-types: date
without time, time, or date-time, respectively. However, if
the value already holds this information, the built-in has
no effect. That is, it will never convert the sub-type of a
value, it only adds the sub-type if it was unknown.</para>
</listitem>
<listitem>
<para>Bug fixed: ISO 8601 dates (via
<literal>?iso_...</literal> and <literal>"iso"</literal>
format settings) now use proleptic Gregorian calendar for
the years before 1582, rather than Julian calendar. This is
(indirectly) required by the standard, and it's also how the
default Sun/Oracle Java XML Schema date/time/dateTime parser
works.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Error message quality improvements (targeting frequent
support requests and some error message bugs):</para>
<itemizedlist>
<listitem>
<para>Fixed glitch where if an <literal>#if</literal> had
and <literal>#else</literal> or <literal>#elseif</literal>,
the
<literal>#if</literal>/<literal>#else</literal>/<literal>#elseif</literal>
wasn't hidden in the FTL stack trace when the error was
inside its nested block.</para>
</listitem>
<listitem>
<para>Some new context sensitive hints in undefined variable
exception error messages.</para>
</listitem>
<listitem>
<para>Fixed unclosed directive error messages at end of file
where the wrong unclosed directive name was reported</para>
</listitem>
<listitem>
<para>Better type error messages when accessing XML data
(applies when wrapped with
<literal>freemarker.ext.dom</literal>):</para>
<itemizedlist>
<listitem>
<para>Trying to use
<literal>node.<replaceable>noSuchChildNodes</replaceable></literal>
on a place where scalar value is expected will explain
that the problem is that you had no matches in the
constructing XML query.</para>
</listitem>
<listitem>
<para>Trying to use
<literal>node.<replaceable>multipleSuchChildNodes</replaceable></literal>
on a place where scalar value is expected will explain
that the problem is that you had multiple matches in the
constructing XML query.</para>
</listitem>
<listitem>
<para>Trying to use
<literal>node.<replaceable>exactlyOneChildNode</replaceable></literal>
as number, date/time/date-time or boolean will explain
that values coming from XML are always strings (text),
and must be converted explicitly via
<literal>?number</literal>, <literal>?boolean</literal>,
<literal>?date.xs</literal>, etc.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Trying to use <literal>obj.someMethod</literal>
without <literal>()</literal> on a place where method value
is not expected will recommend calling the method.</para>
</listitem>
<listitem>
<para>Trying to use methods like
<literal>obj.getFoo</literal> or
<literal>obj.isFoo</literal> without <literal>()</literal>on
a place where method value is not expected will recommend
using the <literal>obj.foo</literal> form.</para>
</listitem>
<listitem>
<para>Messages are now much more readable when rendered in
environments that don't obey to line-breaks. (This often
happens in improperly implemented HTML error pages and logs
viewers.)</para>
</listitem>
<listitem>
<para>Better FTL instruction stack traces:</para>
<itemizedlist>
<listitem>
<para>Error messages now contain up to 10 lines of FTL
stack trace (unless it's on the top of a full FTL stack
trace), because the FTL stack trace wasn't printed at
all when the exception was a cause exception in a Java
stack trace, or when only the value of
<literal>getMessage()</literal> was printed instead of a
stack trace.</para>
</listitem>
<listitem>
<para>The FTL stack trace is now more self explanatory
as it contains more text labels.</para>
</listitem>
<listitem>
<para>Stack frames that belong to nestings are now
marked differently, and are filtered out when the stack
trace wouldn't fit into the error message
otherwise.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fixed: <literal>?substring</literal> has thrown
low level
<literal>java.lang.IndexOutOfBoundsException</literal>-s
instead of more descriptive
<literal>TemplateModelException</literal>-s with FTL stack
trace.</para>
</listitem>
<listitem>
<para>Bug fixed: Slicing with ranges sometimes thrown low
level
<literal>java.lang.IndexOutOfBoundsException</literal>-s
instead of more descriptive
<literal>TemplateModelException</literal>-s with FTL stack
trace.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/402/">402</link>]:
Fixed misleading parser error message when a directive
called without its required parameters (like
<literal>&lt;#list&gt;</literal>) was reported as unknown
directive.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/222/">222</link>]:
Poor quality error message when
<literal><replaceable>someString</replaceable>[<replaceable>someIndex</replaceable>]</literal>
fails with string index out of bounds.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/27/">27</link>]:
Not very good quality error messages when
<literal>#import</literal>-ing a template whose parsing
fails.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>New <literal>include</literal> directive option,
<literal>ignore_missing=<replaceable>boolean</replaceable></literal>.
When this is set to <literal>true</literal>, and the template to
include is missing, the error will be silently ignored, and
nothing will be included.</para>
</listitem>
<listitem>
<para>The <literal>setting</literal> directive can now set the
<literal>output_encoding</literal> setting.</para>
</listitem>
<listitem>
<para>New special variable: <literal>.locale_object</literal>.
This is like <literal>.locale</literal>, except that it's a
<literal>java.util.Locale</literal> object, not a string. This
is handy if you want to pass the current locale to Java
methods.</para>
</listitem>
<listitem>
<para>If <literal>incompatible_improvements</literal> in the
FreeMarker configuration is set to at least 2.3.21, hash
<emphasis>literals</emphasis> that repeat keys now only have the
key once with <literal>?keys</literal>, and only has the last
value associated to that key with <literal>?values</literal>.
This is consistent with the behavior of
<literal><replaceable>hash</replaceable>[<replaceable>key</replaceable>]</literal>
and how maps work in Java.</para>
</listitem>
<listitem>
<para>Bug fixed: <literal>?is_enumerable</literal> has returned
<literal>true</literal> for Java methods get from Java objects,
despite that those values aren't <literal>&lt;#list
...&gt;</literal>-able. (This is actually a historical quirk of
<literal>BeansWrapper</literal>, not a bug in
<literal>?is_enumerable</literal>, but now
<literal>?is_enumerable</literal> is aware of this exceptional
case.)</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/257/">257</link>]:
The result value of <literal>?matches</literal> wasn't
<quote>reentrant</quote>. For example, you couldn't list the
matches inside another listing where you are also listing
exactly the same result value (stored in a common variable), as
they would consume from the same iterator. Most importantly,
even accessing the <literal>?size</literal> of the same result
value has terminated the outer listing of the same value.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/229/">229</link>]:
If you set <literal>incompatible_improvements</literal> to
2.3.21 (or higher), unclosed comments (<literal>&lt;#--
<replaceable>...</replaceable></literal>) and
<literal>#noparse</literal>-s won't be silently closed at the
end of template anymore, but cause a parsing error
instead.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Added new <literal>Configuration</literal> constructor,
<literal>Configuration(Version
incompatibleImprovements)</literal>. This deprecates the vague
<literal>Configuration()</literal> constructor, and makes using
<literal>setIncompatibleImprovements(Version)</literal> needless
in most cases. See an example <link
linkend="pgui_quickstart_createconfiguration">here...</link></para>
</listitem>
<listitem>
<para>When setting the
<literal>incompatible_improvements</literal> setting (like with
the constructor above) to 2.3.21, two setting defaults
change:</para>
<itemizedlist>
<listitem>
<para>The default of the <literal>object_wrapper</literal>
setting
(<literal>Configuration.getObjectWrapper()</literal>)
changes from
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal> to another
almost identical <literal>DefaultObjectWrapper</literal>
singleton, returned by <literal>new
DefaultObjectWrapperBuilder(Version).build()</literal>. The
new default object wrapper's <quote>incompatible
improvements</quote> version is set to the same as of the
<literal>Configuration</literal>. (See later regarding the
2.3.21 <quote>incompatible improvements</quote> of
<literal>BeansWrapper</literal> and
<literal>DefaultObjectWrapper</literal>). Furthermore, the
new default object wrapper doesn't allow changing its
settings; setter methods will throw
<literal>IllegalStateException</literal>. (If anything tries
to call setters on the old default in your application,
that's a dangerous bug that won't remain hidden now. As the
old default is a singleton too, potentially shared by
independently developed components, most of them expects the
out-of-the-box behavior from it (and the others are
necessarily buggy). Also, then concurrency glitches can
occur (and even pollute the class introspection cache)
because the singleton is modified after publishing.)</para>
</listitem>
<listitem>
<para>The default of the <literal>template_loader</literal>
setting
(<literal>Configuration.getTemplateLoader()</literal>})
changes to <literal>null</literal>, which means that
FreeMarker will not find any templates. Earlier the default
was a <literal>FileTemplateLoader</literal> that used the
current directory as the root. This was dangerous and
fragile as you usually don't have good control over what the
current directory will be. Luckily, the old default almost
never looked for the templates at the right place anyway, so
pretty much all applications had to set
<literal>template_loader</literal>, so it's unlikely that
changing the default breaks your application.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>New <literal>BeansWrapper</literal>,
<literal>DefaultObjectWrapper</literal> and
<literal>SimpleObjectWrapper</literal> constructor that takes a
<literal>Version</literal>
<literal>incompatibleImprovements</literal> argument. This has
the same role as the
<literal>incompatible_improvements</literal> setting of the
<literal>Configuration</literal>, but it applies to the
<literal>ObjectWrapper</literal> instead. (As
<literal>ObjectWrapper</literal>-s are often shared among
multiple <literal>Configuration</literal>-s, so they can't use
that setting of the <literal>Configuration</literal>.) In new or
actively developed projects it's recommended to use
<literal>Configuration.VERSION_2_3_21</literal> now. The
constructor without the <literal>Version</literal> parameter is
now deprecated.</para>
</listitem>
<listitem>
<para>Safer and more memory-efficient way of managing singletons
of <literal>DefaultObjectWrapper</literal>-s and
<literal>BeansWrapper</literal>-s that are possibly shared by
independently developed subsystems:</para>
<itemizedlist>
<listitem>
<para>Instead of <literal>new
DefaultObjectWrapper(<replaceable>...</replaceable>)</literal>
and <literal>new
BeansWrapper(<replaceable>...</replaceable>)</literal>, from
now on you should use <literal>new
DefaultObjectWrapperBuilder(version).build()</literal> and
<literal>new BeansWrapperBuilder(version).build()</literal>.
(The builder objects have properties (configuration
settings) like <literal>BeansWrapper</literal> has, which
specify the properties of the objects created.) The created
objects are <emphasis>singletons</emphasis> (VM-wide, or at
least Web-Application-wide) and read-only (means,
non-configurable, hence safe to share). The main benefit of
using these factories instead of creating new instances is
that it allows FreeMarker to share the class introspection
caches (an internal part of
<literal>BeansWrapper</literal>-s/<literal>DefaultObjectWrapper</literal>-s
that is expensive to populate) among the returned instances.
This allow sharing the caches (and the object wrappers)
between components that aren't aware of each other and use
FreeMarker internally.</para>
</listitem>
<listitem>
<para>Deprecated the static fields
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal>,
<literal>BEANS_WRAPPER</literal> and
<literal>SIMPLE_WRAPPER</literal>, because these
<literal>ObjectWrapper</literal>-s are configurable (not
read-only), and thus dangerous to use as singletons (a badly
behaving 3rd party component can mess them up). Use the
factories described above instead. They are also more
flexible, as you can specify the desired
incompatible-improvements version for them and various other
<literal>BeansWrapper</literal> settings.</para>
</listitem>
<listitem>
<para>Deprecated all <literal>SimpleHash</literal>,
<literal>SimpleCollection</literal> and
<literal>SimpleSequence</literal> constructors that didn't
take an <literal>ObjectWrapper</literal> argument, as they
have usually used
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal> as the
default, which itself is deprecated.</para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal>,
<literal>DefaultObjectWrapper</literal> and
<literal>SimpleObjectWrapper</literal> now implements the
<literal>freemarker.template.utility.WriteProtectable</literal>
interface with which the configuration properties of the
object wrapper can be set permanently to read-only by
calling <literal>writeProtect()</literal>. An attempt to
call a setter on a such <literal>ObjectWrapper</literal>
will immediately cause
<literal>IllegalStateException</literal>. (This is what's
used for the singletons returned by the
<literal>getInstance</literal> methods too; see
earlier).</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>The value of the <literal>time_zone</literal> setting,
when you specify it with a <literal>String</literal> (in a
<literal>java.util.Properties</literal> object, or via
<literal>&lt;#setting
<replaceable>...</replaceable>&gt;</literal>) can now be
<literal>"JVM default"</literal> to use the JVM default time
zone. The JVM default is the default value of that setting
anyway, but now you can state this explicitly, or restore this
value if it was overridden earlier.</para>
</listitem>
<listitem>
<para>Added new configuration setting,
<literal>sql_date_and_time_time_zone</literal>
(<literal>Configurable.setSQLDateAndTimeTimeZone(TimeZone)</literal>).
When this is set to non-<literal>null</literal>, the time zone
used when dealing with <literal>java.sql.Date</literal> and
<literal>java.sql.Time</literal> values will be this time zone
instead of the value of the <literal>time_zone</literal>
FreeMarker configuration setting. This is useful because JDBC
will, usually, construct the Java <literal>Date</literal>
objects so that they will show the year-month-day and
hour-minute-seconds values from the database <quote>as
is</quote> if you render them using the JVM default time zone.
As time zone conversions for SQL date-only and SQL time-only
values doesn't make much sense (unlike for SQL timestamps), you
should certainly set this setting to the JVM default time zone
(<literal>TimeZone.getDefault()</literal>, or if you configure
FreeMarker via <literal>java.util.Properties</literal>, as
property value "JVM default"). The default value is
<literal>null</literal> for backward compatibility. For more
details see the JavaDoc of
<literal>Configurable.setSQLDateAndTimeTimeZone(TimeZone)</literal>.</para>
</listitem>
<listitem>
<para>When configuring FreeMarker with
<literal>java.util.Properties</literal> (typically, when the
configuration is stored in a <literal>.properties</literal>
file), for the settings where you could specify a fully
qualified class name (most notably for the
<literal>object_wrapper</literal> setting) now you can also
specify constructor arguments and JavaBean property assignments.
For example, now you can write
<literal>object_wrapper=com.example.MyObjectWrapper(1, 2,
exposeFields=true, cacheSize=5000)</literal>that's nearly
equivalent with this Java code: <literal>obj = new
com.example.MyObjectWrapper(1, 2); obj.setExposeFields(true);
obj.setCacheSize(5000); object_wrapper = obj;</literal>. If you
are using this new syntax (i.e., if you have parentheses after
the class name, even if they are empty), and there's a builder
class for the requested class, that will be automatically used.
For example,
<literal>object_wrapper=DefaultObjectWrapper(2.3.21)</literal>
will create a <literal>DefaultObjectWrapperBuilder</literal> to
build the final instance, thus the object wrapper will be a
singleton instead of a new instance. The new syntax will also
look for a public static <literal>INSTANCE</literal> field if
there are 0 arguments and property assignments. For more details
see the Java API documentation of
<literal>Configuration.setSetting</literal>.</para>
</listitem>
<listitem>
<para>Template not found exceptions now explain that the
template path is interpreted by a template loader, and show the
<literal>toString</literal> of the
<literal>TemplateLoader</literal>. The out-of-the-box
<literal>TemplateLoader</literal> implementations now have an
overridden <literal>toString</literal> to show the actual base
directory and such details. Custom
<literal>TemplateLoader</literal> implementations are encouraged
to override <literal>toString</literal>.</para>
</listitem>
<listitem>
<para>Added
<literal>Configuration.setSharedVariables(Map/*&lt;String,
Object&gt;*/)</literal> for setting the shared variables from
Spring IoC and other IoC solutions. The already existing
<literal>Configuration.setSharedVariable(String,
Object)</literal> isn't a JavaBean property so it was hard to
use for that. Furthermore, the order in which
<literal>Configuration.setObjectWrapper</literal> and
<literal>Configuration.setSharedVariables</literal> are called
doesn't mater (unlike in the case of
<literal>Configuration.setSharedVariable</literal>), which is
essential in most IoC solutions.</para>
</listitem>
<listitem>
<para>Mostly concerning tool (like IDE plugin) authors:</para>
<itemizedlist>
<listitem>
<para><literal>ParseException</literal>-s now also store the
end-location of the error, not just its start-location. This
is useful if you want to underline the error in the source
code, not just point at it.</para>
</listitem>
<listitem>
<para><literal>Configuration.getSupportedBuiltInDirectiveNames()</literal>
can be used to return the names of directives supported by
FreeMarker.</para>
</listitem>
<listitem>
<para><literal>TemplateExceptions</literal> now expose the
position of the error (template name, line, column, end
line, end column) similarly to
<literal>ParseException</literal>-s. Where applicable, they
also expose the blamed expression in its canonical FTL
source form; this is mostly useful for
<literal>InvalidReferenceException</literal>-s.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>The concurrent performance of overloaded method lookups
(from the cache) was improved under Java 5 and later.</para>
</listitem>
<listitem>
<para>The <literal>Version</literal> instances that are
<quote>incompatible improvements</quote> break points are now
available via constants like:
<literal>Configuration.VERSION_2_3_21</literal>.</para>
</listitem>
<listitem>
<para>From now on, if you try to set the <quote>incompatible
improvements</quote> to greater than the current FreeMarker
version, or less than 2.3.0, an
<literal>IllegalArgumentException</literal> will be thrown.
Thus, <literal>new
Configuration(<replaceable>someVersion</replaceable>)</literal>
not only activates the fixes up to that version, but ensures
that the application will not run in an environment with an
older FreeMarker version. (On an older FreeMarker version the
improvements that you have requested aren't implemented yet, so
you should get an exception.)</para>
</listitem>
<listitem>
<para>Added new configuration setting,
<literal>show_error_tips</literal>, defaults to
<literal>true</literal>. Sets if tips should be shown in error
messages of errors arising during template processing.</para>
</listitem>
<listitem>
<para>Instead of overriding
<literal>BeansWrapper.finetuneMethodAppearance</literal> (now
deprecated), now you can use
<literal>BeansWrapper.setMethodAppearanceFineTuner(MethodAppearanceFineTuner)</literal>,
so you don't need to extend the object wrapper class to
customize this aspect.</para>
</listitem>
<listitem>
<para>Added
<literal>Configuration.getCoreDirecticeNames()</literal> which
returns the names of all directives that are provided by
FreeMarker. This can useful for IDE-s.</para>
</listitem>
<listitem>
<para><literal>template_loader</literal> was added as possible
configuration setting <literal>Properties</literal> key.</para>
</listitem>
<listitem>
<para>The standard <literal>CacheStorage</literal>
implementations now have a <literal>getSize()</literal> method
for monitoring the cache size.
<literal>MruCacheStorage</literal> also has
<literal>getSoftSize()</literal> and
<literal>getStrongSize()</literal>.</para>
</listitem>
<listitem>
<para>Various smaller improvements in configuration setting
errors messages.</para>
</listitem>
<listitem>
<para>With incompatible improvements 2.3.21 only: Empty ranges
return <literal>Constants.EMPTY_SEQUENCE</literal> instead of an
empty <literal>SimpleSequence</literal>. This is in theory
backward compatible, as the API only promises to give something
that implements <literal>TemplateSequenceModel</literal>.</para>
</listitem>
<listitem>
<para>FreeMarker now requires Java version has changed from 1.2
to 1.4.</para>
</listitem>
<listitem>
<para>Bugs fixed and improvements in overloaded method
selection/invocation, but only if you create the
<literal>BeansWrapper</literal>/<literal>DefaultObjectWrapper</literal>
with constructor parameter
<literal>Configuration.VERSION_2_3_21</literal> (or if you are
using <literal>Properties</literal> to configure FreeMarker, you
can do that like
<literal>object_wrapper=BeansWrapper(2.3.21)</literal>), or if
you have a <literal>Configuration</literal> with similar
<literal>incompatible_improvements</literal> 2.3.21
<emphasis>and</emphasis> you leave the
<literal>object_wrapper</literal> setting on its default value.
There's a little chance that because of these changes, a
different overloaded method will be chosen than before, or even
that ambiguity errors will arise where earlier they didn't
(although the opposite is far more frequent), hence the fixes
aren't automatically activated. But the fix mostly only effect
calls that were failing or have chosen then wrong method
earlier, so it's recommended to activate it for projects that
are still actively developed. This fix includes numerous
changes:</para>
<itemizedlist>
<listitem>
<para>Earlier, <literal>null</literal> argument values has
only matched overloaded methods where the corresponding
parameter had <literal>Object</literal> type, not a subclass
of it. That's clearly a bug. Now it considers all overloads
where the parameter type is non-primitive, and just like the
Java language, it choses the one with the most specific type
among them. This is the most important fix, and also the
most risky one regarding backward-compatibility. Like if you
have <literal>m(Object o)</literal> and <literal>m(String
s)</literal> in a Java class, earlier for a
<literal>m(null)</literal> call in the template it has
chosen <literal>m(Object o)</literal>, but now it will
choose <literal>m(String s)</literal> instead (because
<literal>String</literal> is also
<literal>null</literal>-able and is more specific than
<literal>Object</literal>). Furthermore, if you also had
<literal>m(File f)</literal> in the same class, now it will
cause an ambiguity exception, since the specificity of
<literal>File</literal> and <literal>String</literal> can't
be compared (same rule as under Java language), while
earlier that wasn't a problem as only <literal>m(Object
o)</literal> was seen as applicable.</para>
</listitem>
<listitem>
<para>The behavior of numbers with overloaded method
selection was heavily reworked:</para>
<itemizedlist>
<listitem>
<para>If possible, it now always choses the overload
where overflow and truncation to integer (like 1.5 to 1)
is avoided. Among the methods where no such critical
loss occurs, it choses the overload with the least risk
of precision loss (unless other conditions with higher
priority suggest otherwise). Earlier, the method
selection was prone to do choices that led to overflow
or precision loss, especially when the parameter was a
literal with decimals.</para>
</listitem>
<listitem>
<para>Overloaded method call can now convert to
non-primitive numerical types, like a
<literal>Byte</literal> or <literal>byte</literal> value
is automatically converted to <literal>Integer</literal>
if the parameter type is <literal>Integer</literal>.
(This has always worked for non-overloaded methods.)
Earlier where such conversion was needed, the method
wasn't seen seen applicable.</para>
</listitem>
<listitem>
<para>Method selection is now not only based on the type
of the wrapped number, but also on its value. For
example, a <literal>Long</literal> with value
<literal>1</literal> is now seen as compatible with a
method with parameter type <literal>int</literal> or
<literal>short</literal> or <literal>byte</literal>, as
<literal>1</literal> can be stored in those without
loss. This is important as unlike in Java language, in
FTL you doesn't have strict control over the numerical
types (the type of the wrapped number, actually), as FTL
has no type declarations. (If multiple compatible
methods are available, it will still try to chose the
one with the same or bigger numerical type.)</para>
</listitem>
<listitem>
<para>Conversion from/to <literal>BigInteger</literal>
is now supported.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Method choice ambiguity errors now occur much less
often. Ambiguities was and are resolved by selecting the
compatible methods then choosing the one with the most
specific parameter types among them. The changes are:</para>
<itemizedlist>
<listitem>
<para>When comparing the overall specificity of two
parameter lists: Earlier the parameter list seen as more
specific was the one that had some parameters that won
in specificity, and if both had such parameters then it
was an ambiguity. Now it's enough if a method has more
such parameters where it's a better match than the other
has, or if the two methods are still equal, if it has
the first better matching parameter. This can lead to
choices that seem arbitrary (but are still
deterministic), but as there's no automated way of
discovering method selection ambiguities in templates
(unlike in Java source code, where they will be detected
during compilation), especially as overloaded selection
has to rely on the <emphasis>runtime</emphasis> type of
the values which even make proper testing hard, this was
considered to be a better compromise than throwing an
exception whenever the choice of the method is not
obvious. Also note that in fact this mechanism is more
complicated than just counting the <quote>winner</quote>
parameter positions for each methods, as certain kind of
wins are stronger than any number of the others: wins
where the other possibility is risking of substantial
mantissa precision loss are the strongest (like dropping
decimals versus not to), wins where the primitive type
wins over the boxed class is the weakest (like
<literal>int</literal> versus
<literal>Integer</literal>), subclassing wins (like
<literal>String</literal> versus
<literal>Object</literal>) are between these two.</para>
</listitem>
<listitem>
<para>When comparing the specificity of two parameters
types at the same parameter position: The algorithm now
considers a primitive type as more specific that its
corresponding boxing class (like <literal>int</literal>
is considered to be more specific than
<literal>Integer</literal>).</para>
</listitem>
<listitem>
<para>There was a bug with overloaded varargs methods of
different parameter counts, where sometimes the last
parameters of the compared methods was ignored, which is
taking away a potential deciding factor and thus can
lead to ambiguity error. Whether this happened depends
on the order in which the Java reflection API has
returned the methods, which is undocumented and known to
change at least after some Java updates, breaking the
application.</para>
</listitem>
<listitem>
<para>When comparing the specificity of two array types,
until now they were seen as equal. Now the component
types are compared, and then that with the less specific
component type is preferred. For example, among
<literal>f(String[])</literal> and
<literal>f(Object[])</literal>, the last will always
win. This might sounds controversial, but as we can't
efficiently tell the common type of all the items in a
sequence or <literal>List</literal>, and so we don't
know if both arrays are indeed valid targets, we go for
the safest choice.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>FTL sequence values (like Java
<literal>List</literal>-s or FTL
<literal>[<replaceable>x</replaceable>,
<replaceable>y</replaceable>,
<replaceable>...</replaceable>]</literal> constants) were
not seen as applicable to a parameter with array type if
there were multiple overloaded methods with the same number
of parameters but with different types on the position of
the array parameter. That is, if you had
<literal>f(String[])</literal> and
<literal>f(String)</literal> in Java, then
<literal>f(['foo', 'bar'])</literal> in the template
reported no compatible overloads. Now it will choose
<literal>f(String[])</literal>. Note that if there's also an
<literal>f(List)</literal> or even an
<literal>f(Collection)</literal>, it will prefer those over
arrays. (For consistency, this conversion will work even if
the argument is a <literal>List</literal> that come directly
from Java (as opposed to be created inside FTL), i.e., when
it was wrapped then unwrapped to the original
<literal>List</literal> object.) For a multidimensional
array parameter type, this conversion works recursively, so
you can pass in a sequence-of-sequences as the
argument.</para>
</listitem>
<listitem>
<para>FTL sequence values that wrapped a Java array (when
FreeMarker was also aware of that via
<literal>AdapterTemplateModel</literal> or
<literal>WrapperTemplateModel</literal>) were not seen as
applicable to a parameter with <literal>List</literal> type
if there were multiple overloaded methods with the same
number of parameters but with different types on the
position of the array parameter. So this is pretty much like
the issue described in the previous point, but for array to
<literal>List</literal> conversion. The array to
<literal>List</literal> conversion will be avoided if
possible, but it will be attempted if there's no other
alternative. Note that unlike with <literal>List</literal>
to array conversions, here FreeMarker can't cope with
multi-dimensional lists, that is, an array-of-arrays won't
be converted to a
<literal>List</literal>-of-<literal>List</literal>-s.</para>
</listitem>
<listitem>
<para>FTL string to Java
<literal>char</literal>/<literal>Character</literal>
conversion now works for overloaded method parameters;
earlier it has worked for non-overloaded methods only. If
the string length is 1, it will be seen as compatible with
parameters with <literal>char</literal> or
<literal>Character</literal> type.</para>
</listitem>
<listitem>
<para>Decreased the chance of choosing the wrong target Java
type when unwrapping multi-typed FTL values: When unwrapping
a parameter value that implements multiple FTL types (e.g.
string and hash) but doesn't implement
<literal>AdapterTemplateModel</literal> or
<literal>WrapperTemplateModel</literal>, a decision has to
be made if to what Java type the value should be unwrapped
to (e.g. to <literal>String</literal> or to
<literal>Map</literal>). In earlier versions that decision
was made based on the most specific common super type of the
parameters types of the given parameter position. However,
it's quite common that the common super type is too generic,
usually <literal>Object</literal>. Now
<literal>BeansWrapper</literal> stores <quote>type
flags</quote> for each parameter position of overloaded
methods, from which it can tell whether a potential target
Java type occurs in any of the overloads on the given
parameter position.</para>
</listitem>
<listitem>
<para>In many cases, less specific hint class was used for
unwrapping than that was possible within the limitations of
the applied hint generation algorithm. (The unwrapping hint
has influence when there's an ambiguity regarding how to
create a Java object form an FTL value. In the vast majority
of the cases, a too generic hint has no effect.) (This is a
highly technical topic. The way it works is that a single
common unwrapping hint class is chosen for a given argument
position shared by the overloads that has the same number of
parameters, and that hint class has to be as specific as
possible while it must fit all those parameter types. The
issue with the too generic hints had several instances: (a)
When the most specific common class/interface of two
same-position parameter types was searched, if there was
multiple common classes/interfaces that had no relationship
(this is always at most one class and one or more unrelated
interfaces), due to the ambiguity it has felt back to using
<literal>Object</literal> as the unwrapping hint. Now if
there's a non-<literal>Object</literal> class among them in
such case, it will be chosen as the hint (i.e., we ignore
the common interfaces). Otherwise if only a single interface
remains by removing <literal>Cloneable</literal>,
<literal>Serializable</literal>, and
<literal>Comparable</literal> (in that order), that will be
chosen. Only then it falls back to
<literal>Object</literal>. (b) The common most specific
class of a primitive type and the corresponding boxing class
was sometimes <literal>Object</literal> instead of the
boxing class. This has depended on Java's internal ordering
of the methods, and so were quite unpredictable, like the
result could change after upgrading Java under the
application. (c) The common superclass of a numerical
primitive value and a numerical non-primitive value was
always <literal>Object</literal>, now if they are a
primitive-boxing class pair, then it's the boxing class,
otherwise it's <literal>Number</literal>. (d) If the varags
parameter position was not the same in all the overloaded
varargs methods, sometimes some varargs arguments where
unwrapped with too generic hints. When this happened was
unpredictable as it depended on Java's internal method
ordering again.)</para>
</listitem>
<listitem>
<para>When unwrapping method call arguments before calling a
Java method, if the argument was an
<literal>AdapterTemplateModel</literal> and the target
parameter type was primitive,
<literal>AdapterTemplateModel.getAdaptedObject(Class
hint)</literal> has received the primitive type of the
target parameter (like <literal>int</literal> instead of
<literal>Integer</literal>) as the hint. This did not make
sense since <literal>getAdaptedObject</literal> can only
return <literal>Object</literal>-s, not primitive values.
Yet, <literal>BeansWrapper</literal> has expected the
returned value to be of the primitive type, otherwise it has
discarded it. Exactly the same problem occurs with
<literal>WrapperTemplateModel</literal>. Thus, ultimately,
if the target parameter type was primitive and some of these
interfaces were implemented, their return value was always
discarded and FreeMarker has felt back to other means of
unwrapping. Now <literal>BeansWrapper</literal> always
passes in and expects the boxing type (like
<literal>Integer</literal>) instead of the primitive
type.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/373/">373</link>]:
These are three bugs actually, which can cause problems when
FreeMarker re-loads a template because of a charset override
with <literal>&lt;#ftl encoding="..."&gt;</literal>: First, if
the template loader was a <literal>URLTemplateLoader</literal>,
when <literal>TemplateLoader.getReader()</literal> was called
for the second time, and the <literal>Reader</literal> returned
for the first time was already used, it might returned an empty
or corrupted template, depending on the backing URL
implementation. Secondly, when FreeMarer has decided if a
template file has to be re-loaded because its encoding specified
with <literal>&lt;#ftl encoding="..."&gt;</literal> differs from
the encoding used for loading the template first, it has used
case-sensitive comparison, thus often re-loaded needlessly (like
"UTF-8" and "utf-8" mean the same). Now this comparison is
case-insensitive. Last not least, when retrying with the second
charset, the <literal>TemplateCache</literal> has forgotten to
close the first <literal>Reader</literal>, which can be a handle
leak.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/411/">411</link>]:
Invalid and redundant execution environment names from the OSGi
bundle manifest were removed. It looks like this now:
<literal>Bundle-RequiredExecutionEnvironment: J2SE-1.5,
J2SE-1.4</literal>. That is, we prefer (and compile against)
1.5, but only require 1.4.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/409/">409</link>]:
<literal>SimpleHash</literal>'s internal <literal>Map</literal>
is concurrently modified on a non-safe way when getting length-1
<literal>String</literal> key that exists but maps to
<literal>null</literal>. This operation will accidentally add a
<literal>Character</literal> key to the internal map, which is
not a thread-safe operation.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/273/">273</link>]:
<literal>TemplateLoader</literal>-s that use
<literal>java.net.URLConnection</literal>-s should set
<literal>URLConnection.useCaches</literal> to
<literal>false</literal>, or else it won't detect template
caches on certain configurations.</para>
<itemizedlist>
<listitem>
<para><literal>URLTemplateLoader</literal> and its
subclasses and
<literal>WebApplicationTemplateLoader</literal> now has a
<literal>setURLConnectionUsesCaches(Boolean)</literal>
method. It's recommended to set this property to
<literal>false</literal> from its default backward
compatible value, <literal>null</literal>. As FreeMarker has
its own template cache with its own update delay setting
(<literal>template_update_delay</literal>,
<literal>Configuration.setTemplateUpdateDelay(int)</literal>),
it shouldn't cause performance problems. The
<literal>null</literal> value will leave the caching of the
<literal>java.net.URLConnection</literal> on its default,
which is usually <literal>true</literal>.</para>
</listitem>
<listitem>
<para>If <literal>incompatible_improvements</literal> is set
to 2.3.21 (or higher) and templates are loaded through
<literal>Configuration.getTemplate</literal>, and the
<literal>TemplateLoader</literal> in use has
<literal>URLConnectionUsesCaches</literal> left on
<literal>null</literal>, it will behave as if it was set to
<literal>false</literal>. Note that this
<literal>incompatible_improvements</literal> trick only
works if the template is loaded through
<literal>Configuration.getTemplate</literal> (or
<literal>TemplateCache</literal>).</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fixed: When changing the properties of
<literal>DefaultObjectWrapper</literal> or
<literal>BeansWrapper</literal> that influenced class
introspection results (like <literal>exposureLevel</literal> or
<literal>exposeFields</literal>), the introspection cache wasn't
cleared, and thus returned stale information for the classes
that were introspected before those properties were changed. Now
changing such properties always clears the introspection
caches.</para>
</listitem>
<listitem>
<para>Bug fixed: Constants used for empty sequence, empty hash,
empty collection and empty iterator weren't
<literal>Serializable</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/311/">300</link>]:
Logger class availability check was incorrect in that it has
checked the availability of logger libraries with the thread
context class loader, then later it tried to link to them with
the defining class loader of the FreeMarker classes. With some
class loader setups (notably under Netbeans sometimes) this led
to <literal>ClassDefNotFoundError</literal>-s that made
FreeMarker unusable. (The check itself was also not very
durable, as it didn't expected <literal>LinakeError</literal>-s,
only <literal>ClassNotFoundException</literal>.)</para>
</listitem>
<listitem>
<para>Bug fixed: <literal>ClassUtil.forName</literal>, used
inside FreeMarker everywhere to resolve class names to classes,
if the thread context class loader is <literal>null</literal>,
no longer tries to load with the bootstrap class loader before
loading with the defining class loader of FreeMarker.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="http://sourceforge.net/p/freemarker/bugs/311/">311</link>]:
<literal>TemplateBooleanModel.TRUE</literal> and
<literal>FALSE</literal> are now serializable</para>
</listitem>
<listitem>
<para>Bug fixed: Various issues in <literal>Version</literal>
class, such as wrong <literal>hashCode</literal>, possible
concurrency glitches, and acceptance of some malformed version
strings.</para>
</listitem>
<listitem>
<para>Bug fixed [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/414/">414</link>]:
Eclipse debug mode running was suspended during FreeMarker
static initialization on the JRebel availability checked if
JRebel wasn't available.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>The license has changed from our proprietary BSD-Style
license to the well know "Apache License, Version 2.0".
Furthermore, the copyright owner has changed from "Visigoth
Software Society" (which was founded by Jonathan Revusky) to the
three main FreeMarker 2 developers/contributors, "Attila
Szegedi, Daniel Dekany, and Jonathan Revusky". See the <link
linkend="app_license">new license here</link>.</para>
</listitem>
<listitem>
<para>The required minimum Java version was raised from 1.2 to
1.4. FreeMarker will not work on Java 1.2 or 1.3.</para>
</listitem>
<listitem>
<para>Many smaller improvements and fixes in the Manual and API
JavaDocs.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_20">
<title>2.3.20</title>
<para>Date of release: 2013-06-27</para>
<para>If you are IDE/tools author, <link
linkend="version_2_3_20_ide">note these changes</link>.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Error message quality improvements:</para>
<itemizedlist>
<listitem>
<para>Many error messages are now more helpful, especially
for users who are not experienced with FreeMarker. For
example, some of the most common user mistakes are
recognized and tips are shown to fix them, reducing support
costs or the time employees spend to figure them out.</para>
</listitem>
<listitem>
<para>It's now ensured that the error location in the
template is included in the message returned by
<literal>TemplateException.getMessage()</literal>. The stack
trace always showed this information anyway, but some users
only see the <quote>message</quote>, not the stack trace,
and that often didn't contained the location.</para>
</listitem>
<listitem>
<para>The template language part of the stack trace is now
more detailed, and easier to understand. This is especially
helpful in applications that use a complex library of macros
and functions.</para>
</listitem>
<listitem>
<para>Several smaller bugs were fixed that made the error
information wrong or lacking.</para>
</listitem>
<listitem>
<para>The layout of the error messages is now more
consistent, and generally easier to read.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Changes regarding boolean to string conversions and
formatting:</para>
<itemizedlist>
<listitem>
<para><literal>?c</literal> (computer-language formatting)
now works with booleans too, always giving
<literal>"true"</literal> or <literal>"false"</literal>
regardless of the <literal>boolean_format</literal>. This
way it's safe for generating JavaScript in a context where
human-readable text is also rendered.</para>
</listitem>
<listitem>
<para>If the <literal>boolean_format</literal> setting is
set to anything but the default
<literal>"true,false"</literal> value, boolean values will
be automatically converted to string where a string value is
expected by the template language, instead of giving an
error. This helps you spare
those<literal>?string</literal>-s after boolean values. This
is the same logic as with numbers and dates, which were
always automatically converted to string, according the
corresponding format setting. Except, the provided default
boolean format is useless for automatic conversion (but it's
still there for <literal>?string</literal>, for backward
compatibility), hence it must be set manually. (We certainly
couldn't come up with a sensible default anyway, as for
booleans it depends too much on the application, not to
mention the localisation issues.)</para>
<para>Exactly like with numbers and dates, automatic
conversion doesn't happen in these cases:</para>
<itemizedlist>
<listitem>
<para>Comparisons, i.e., <literal>someBoolean ==
'true'</literal> is still an error</para>
</listitem>
<listitem>
<para>Method calls where the declared type of the
parameter is <literal>String</literal> but the actual
value is a boolean; still an error</para>
</listitem>
<listitem>
<para>When the boolean value is used as key in
<literal><replaceable>expr</replaceable>[<replaceable>key</replaceable>]</literal>,
it's still an error (there was no automatic conversion
there for other types either, as numerical and string
keys have different meaning)</para>
</listitem>
<listitem>
<para>The opposite direction, i.e., string to boolean
conversion; won't happen</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>New built-ins for numbers: <link
linkend="ref_builtin_abs"><literal>abs</literal></link>, <link
linkend="ref_builtin_is_nan"><literal>is_nan</literal></link>,
<link
linkend="ref_builtin_is_infinite"><literal>is_infinite</literal></link>.
Like <literal>n?abs</literal> will give the absolute value of
<literal>n</literal>.</para>
</listitem>
<listitem>
<para>New built-in for sequences: <link
linkend="ref_builtin_join"><literal>join</literal></link>. Like
<literal>[1, 2, 3]?join(", ")</literal> will give the string
<literal>"1, 2, 3"</literal>.</para>
</listitem>
<listitem>
<para>If you set the
<literal>incompatible_improvements</literal> setting (see <link
xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setIncompatibleImprovements%28freemarker.core.Version%29">here</link>)
to <literal>2.3.20</literal> or higher, <literal>?html</literal>
will escape apostrophe-quotes just like
<literal>?xhtml</literal> does. Utilizing this is highly
recommended, because otherwise if interpolations are used inside
attribute values that use apostrophe-quotation (<literal>&lt;foo
bar='${val}'&gt;</literal>) instead of plain quotation mark
(<literal>&lt;foo bar="${val}"&gt;</literal>), they might
produce HTML/XML that's not well-formed. Note that
<literal>?html</literal> didn't do this because long ago there
was no cross-browser way of doing this, but it's not a real
concern anymore. Also note that this will be the default
behavior starting from 2.4.</para>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/390/">390</link>]
(and other improvements): <literal>?js_string</literal> and
<literal>?json_string</literal> didn't escape the
<literal>u2028</literal>-<literal>u2029</literal> line
terminators (problem for JavaScript) and the
<literal>u007F</literal>-<literal>u009F</literal> control
characters (maybe a problem in JSON, depending on
implementation). Furthermore, the escaping of
<literal>\</literal>, <literal>&lt;</literal>, and
<literal>&gt;</literal> become safer in that now they are
escaped whenever it can't be guaranteed that they won't be part
of <literal>&lt;!</literal>, <literal>]]&gt;</literal> or
<literal>&lt;/</literal>. Earlier they were only escaped when it
was known that they are part of these patterns, thus it was
possible to assemble these patterns from two adjacent
interpolations. Additionally, from now on
<literal>&lt;?</literal> and <literal>--&gt;</literal> also
count as dangerous patterns, and will trigger
<literal>&lt;</literal> and <literal>&gt;</literal>
escaping.</para>
</listitem>
<listitem>
<para>Bug fixed: The following string built-ins didn't coerce
the numerical, date (and now the boolean) left-values to string,
instead they threw a type error: contains,
<literal>index_of</literal>, <literal>last_index_of</literal>,
<literal>left_pad</literal>, <literal>right_pad</literal>,
<literal>matches</literal>, <literal>replace</literal>,
<literal>split</literal>, <literal>new</literal>. The other
string built-ins already did this conversion for a long time;
this was an accidental inconsistency.</para>
</listitem>
<listitem>
<para>Bug fixed: With the default arithmetic engine, it's now
supported to compare infinite (positive or negative) with 0, to
decide its sign.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><literal>BeansWrapper</literal> introspection cache
improvements:</para>
<itemizedlist>
<listitem>
<para>Added public API to <literal>BeansWrapper</literal>
for clearing the class cache:
<literal>clearClassIntrospecitonCache()</literal>,
<literal>removeFromClassIntrospectionCache(Class)</literal></para>
</listitem>
<listitem>
<para>Significantly improved multi-core performance:</para>
<itemizedlist>
<listitem>
<para>Uses <literal>ConcurrentHashMap</literal> when
running on Java 5 or later.</para>
</listitem>
<listitem>
<para>The cache won't block readers while introspecting
a class after a cache miss</para>
</listitem>
<listitem>
<para>If multiple threads need to introspect the same
class that's not in the cache yet, only one of them will
do it, the others will wait for its results.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/361/">361</link>]:
There was a small chance of deadlock when class-reloading
was detected. Locking was redesigned to prevent such
oversights in the future.</para>
</listitem>
<listitem>
<para>The internal package-visible
<literal>freemarker.ext.beans</literal> API was slightly
changed as the result of internal cleanup. Nobody but the
FreeMarker developers should define classes in that package,
so it shouldn't break anything. But if somebody did some
in-house hacks there, re-compile to see if it still
works.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Nameless templates (those directly created with
<literal>new Template(null,
<replaceable>...</replaceable>)</literal> instead of loaded
through <literal>Configuration</literal>) couldn't include or
import other templates, and thrown a
<literal>NullPointerException</literal> when they tried to. Now
they resolve relative paths as if they were in the template root
directory.</para>
</listitem>
<listitem>
<para>Bug fix: Regular expression built-ins and some logger
libraries (most importantly Log4J) were unavailable on the
Google App Engine platform. This fix is only present in the
GAE-compatible build, 2.3.20-gae.</para>
</listitem>
<listitem>
<para>Added new method to <literal>Configuration</literal>:
<literal>CacheStorage getCacheStorage()</literal></para>
</listitem>
<listitem>
<para>Added new methods to <literal>Environment</literal> to
make comparisons among <literal>TemplateModel</literal>-s
according the rules of the template language operators:
<literal>applyEqualsOperator</literal>,
<literal>applyEqualsOperatorLenient</literal>,
<literal>applyLessThanOperator</literal>,
<literal>applyLessThanOrEqualsOperator</literal>,
<literal>applyGreaterThanOperator</literal>,
<literal>applyWithGreaterThanOrEqualsOperator</literal></para>
</listitem>
<listitem>
<para>Added new method,
<literal>Environment.isInAttemptBlock()</literal> to check if we
are within an <literal>#attempt</literal> block. This can be
useful for <literal>TemplateExceptionHandler</literal>-s, as
then they don't need to print the error to the output since
<literal>#attempt</literal> will roll it back anyway. This is
already utilized by the built-in
<literal>TemplateExceptionHandler</literal>-s
(<literal>DEBUG_HANDLER</literal> and
<literal>HTML_DEBUG_HANDLER</literal>).</para>
</listitem>
<listitem>
<para>Added convenience constructor <literal>Template(String
name, String sourceCode, Configuration cfg)</literal>.</para>
</listitem>
<listitem>
<para><literal>TemplateException</literal>-s and
<literal>TemplateModelExcepton</literal>-s now can have
<literal>Throwable</literal> cause, not just
<literal>Exception</literal> (it was an old oversight that
somehow wasn't fixed so far).</para>
</listitem>
<listitem>
<para>Parsing error messages under the JBoss Tools FreeMarker
IDE now doesn't contain the usual location line, so that the
actual error description is immediately visible in the Eclipse
<quote>Problems</quote> view. (It's a <quote>hack</quote> in
FreeMarler itself; it tries to detect if it runs under the
plugin and then changes its behavior.)</para>
</listitem>
<listitem xml:id="version_2_3_20_ide">
<para>Mostly concerning tool (like IDE plugin) authors:</para>
<itemizedlist>
<listitem>
<para>The error message formats (what
<literal>Throwable.getMessage()</literal> returns) were
heavily changed for <literal>TemplateException</literal>-s,
and somewhat for <literal>ParseException</literal>-s. It's
unlikely that anybody depends on these, but if you tried to
parse these messages, be aware of this.</para>
</listitem>
<listitem>
<para>Fixed bug where <literal>ParseException</literal> has
contained 0 as line and column number for lexical errors.
Now it contains the correct information.</para>
</listitem>
<listitem>
<para>Added
<literal>ParseException.getEditorMessage()</literal>: As in
IDE-s the error markers show the error location to the user
already, the location should not be repeated in the error
message. So in IDE-s you should use this method instead of
<literal>getMessage()</literal>. (Under JBoss Tools:
FreeMarker now <emphasis>tries</emphasis> to detect that it
runs under the plugin, and then it already does this, except
that it still shows the column number as that's missing from
the error marker location.)</para>
</listitem>
<listitem>
<para>Added
<literal>ParseException.getTemplateName()</literal></para>
</listitem>
<listitem>
<para>Added
<literal>Configuration.getSupportedBuiltInNames()</literal>.
As new built-ins
(<literal><replaceable>expr</replaceable>?<replaceable>builtin_name</replaceable></literal>)
are very often added to new FreeMarker versions,
auto-completion or syntax highlighting should use this set
instead of a fixed set of a names.</para>
</listitem>
<listitem>
<para>The format returned by
<literal>TemplateElement.getDescription()</literal> was
heavily changed. It's what FTL stack traces and maybe some
outline views (tree-views) show. It was always for human
reading (and till now was too inconsistent for anything
else), so it's unlikely that this breaks anything.</para>
</listitem>
<listitem>
<para>There were some smaller changes in
<literal>freemarker.debug</literal>, and it's expected that
there will be more, so it was marked as experimental. As far
as we know, nobody used it, so it shouldn't break
anything.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>In <emphasis>experimental status only</emphasis>, but
<literal>freemarker.jar</literal> is now an OSGi bundle (see
<literal>freemarker.jar/META-INF/MANIFEST.MF</literal>).
Depending on user feedback, the bundle description may change in
the future. So please give feedback, especially if you are an
OSGi expert!</para>
</listitem>
<listitem>
<para>Improved the HTML generated by
<literal>HTML_DEBUG_HANDLER</literal> (the
red-on-yellow-background error message). Most importantly, now
it will word-wrap. Other changes are minor, like now it can
break out of CDATA sections, or now it has less intense
colors.</para>
</listitem>
<listitem>
<para>New <literal>Template</literal> method,
<literal>getActualTagSyntax()</literal>: Tells if the template
is using traditional or square-bracket syntax. As the syntax can
be overridden in the template, also it's possibly decided by
auto-detection, it wasn't trivial to it tell till now.</para>
</listitem>
<listitem>
<para>Added some utility methods that are useful for generating
error messages in custom directives:
<literal>ClassUtil.getFTLTypeDescription(TemplateModel)</literal>,
<literal>getShortClassName</literal>,
<literal>getShortClassNameOfObject</literal></para>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/364/">364</link>]:
<literal>freemarker.template.EmptyMap</literal> (which is passed
to <literal>TemplateDirectiveModel</literal>-s if there are no
parameters) now allows <literal>remove(key)</literal>,
<literal>clear()</literal> and
<literal>putAll(anyEmptyMap)</literal> as these do nothing
anyway.</para>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/375/">375</link>]:
<literal>NullPointerException</literal> on IBM J9 VM (not on the
Sun/Oracle implementation) in <literal>BeansWrapper</literal>
when the Java implementation legally returns
<literal>null</literal> for some <literal>BeanInfo</literal>
getters.</para>
</listitem>
<listitem>
<para>Bug fix: Cloning a <literal>Configuration</literal> didn't
deep-clone the data structures storing the
<literal>auto_imports</literal> and
<literal>auto_includes</literal> settings, hence possibly
leading to aliasing problems.</para>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/377/">377</link>]:
After a failed method call the exception handler could fail in
the rare occasion when
<literal>targetObject.toString()</literal> fails, raising a
runtime exception that not even the <literal>attempt</literal>
directive will catch.</para>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/391/">391</link>]:
If a template name has contained <literal>*</literal> that was
not the only character in the path step, it threw
<literal>NegativeArraySizeException</literal> instead of
<literal>FileNotFoundException</literal>.</para>
</listitem>
<listitem>
<para>With the default arithmetic engine, performance
optimizations of comparison operations when some of the numbers
is 0, and when the sign of the numbers differ.</para>
</listitem>
<listitem>
<para>Some smaller fixes in
<literal>TemplateElement.getCanonicalForm()</literal>, also some
quality improvements there.</para>
</listitem>
<listitem>
<para>Bug fixes in <literal>classic_compatible</literal> mode
(this mode is to help migrating from FreeMarker 1), thanks to
Information Mosaic:</para>
<itemizedlist>
<listitem>
<para>When a macro was called with a
<literal>null</literal>/missing parameter value, it has
caused error like in FreeMarker 2.3</para>
</listitem>
<listitem>
<para>When a hash literal contained reference to a
<literal>null</literal>/missing variable, like in <literal>{
'a': missingVar }</literal>, it has caused an error like in
2.3</para>
</listitem>
<listitem>
<para>When a sequence literal contained reference to a
<literal>null</literal>/missing variable, like in
<literal>[1, missingVar]</literal>, it has caused an error
like in 2.3</para>
</listitem>
<listitem>
<para>When a the left-side of the <literal>.</literal> (dot)
or <literal>[<replaceable>key</replaceable>]</literal>
operator was <literal>null</literal> or missing variable,
like in <literal>missingVar.subVar</literal>, it has caused
an error like in 2.3</para>
</listitem>
<listitem>
<para>When <literal>BeanModel</literal>-s are tried to be
treated as strings, for most subclasses it has failed with
type error, like in 2.3. In FreeMarker 1 all
<literal>BeanModel</literal>-s were
<literal>TemplateScalarModel</literal>-s, so it should
succeed. The fix for this only works where FreeMarker
<emphasis>coerces</emphasis> to string (string built-ins on
the left-side and concatenation (<literal>+</literal>) and
interpolation
(<literal>${<replaceable>...</replaceable>}</literal>) do
that), otherwise unfortunately it will still fail.</para>
</listitem>
<listitem>
<para>The <literal>classic_compatible</literal> setting now
accepts value <literal>2</literal> along
<literal>true</literal> (alias <literal>1</literal>) and
<literal>false</literal> (alias <literal>0</literal>).
<literal>2</literal> means <literal>true</literal> but with
emulating bugs in early 2.x classic-compatibility mode.
Currently this only affects how booleans are converted to
string; with <literal>1</literal> it's always
<literal>"true"</literal>/<literal>""</literal>, but with
<literal>2</literal> it's <literal>"true"/"false"</literal>
for values wrapped by <literal>BeansWrapper</literal> as
then <literal>Boolean.toString()</literal> prevails. Note
that
<literal><replaceable>someBoolean</replaceable>?string</literal>
will always consistently format the boolean according the
<literal>boolean_format</literal> setting, just like in
FreeMarker 2.3.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bug fix [<link
xlink:href="https://sourceforge.net/p/freemarker/bugs/394/">394</link>]:
When trying to access the optional Jython (or W3C DOM) classes
has failed in <literal>DefaultObjectWrapper</literal> with an
<literal>Error</literal>, rather than with an
<literal>Exception</literal>, loading the
<literal>DefaultObjectWrapper</literal> class itself has failed,
instead of the Jython (or W3C DOM) support being disabled. From
now in, it will survive any kind of <literal>Throwable</literal>
there, and if the <literal>Throwable</literal> is not an
<literal>ClassNotFoundException</literal>, it will also log the
<literal>Throwable</literal>.</para>
</listitem>
<listitem>
<para>Improved the performance of
<literal>(thisVarIsMissing.foo)!default</literal> and similar
<emphasis>parenthetical</emphasis> existence operators and
existence built-ins in the case when the
<literal>null</literal>/missing variable is not the last step
inside the parenthesis. In that case it's about 30 times faster
now, measured on Java 6. In other cases (when all variables
exists, or the the last step is missing) the performance is
about the same (relatively fast) as before.</para>
</listitem>
<listitem>
<para>Added interface
<literal>freemarker.cache.CacheStorageWithGetSize</literal>
which allows querying the current number of cache entries in a
<literal>CacheStorage</literal> that implements it. It's
implemented by all out-of-the-box
<literal>CacheStorage</literal> implementations. Also added
<literal>getStrongSize()</literal> and
<literal>getSoftSize()</literal> to
<literal>MRUCacheStorage</literal>.</para>
</listitem>
<listitem>
<para>Version and build information changes:</para>
<itemizedlist>
<listitem>
<para>The form of the nightly build version numbers has
changed to be Maven/JSR 277 compliant. What earlier was
<literal>2.3.19mod</literal> is now something like
<literal>2.3.20-nightly_20130605T130506Z</literal> (note how
the last points to the target release version instead of the
last release version).</para>
</listitem>
<listitem>
<para>The form of the Release Candidate and Preview version
numbers where changed to be Maven/JSP 277 compliant:
<literal>2.4pre2</literal> is now
<literal>2.4.0-pre02</literal>, <literal>2.4rc1</literal> is
now <literal>2.4.0-rc01</literal>.</para>
</listitem>
<listitem>
<para>Added new static method to
<literal>Configuration</literal> to query build date:
<literal>getBuildDate()</literal>. This is also printed by
the main command line class.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Various internal code cleanups.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Many JavaDoc improvements, mostly in the documentation of
the basic (most frequently used) classes.</para>
</listitem>
<listitem>
<para>FreeMarker source code has moved to GitHub (<link
xlink:href="???">https://github.com/freemarker/freemarker</link>),
other project resources has remained on sourceforge.net.</para>
</listitem>
<listitem>
<para>Project structure cleanup, Ivy-based build script.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_19">
<title>2.3.19</title>
<para>Date of release: 2012-02-29</para>
<para>Don't miss the <link linkend="v2319secfix">security related
changes</link>, they may affect your application!</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para><emphasis>Attention</emphasis>: The output of <link
linkend="ref_builtin_date_iso">ISO 8601 date/time formatting
built-ins</link>, introduced in 2.3.17, was slightly changed.
From now on, the time zone offset, when it's displayed and it
isn't <literal>Z</literal>, always includes the minutes. For
example, <literal>15:30:15+02</literal> becomes to
<literal>15:30:15+02:00</literal> in the template output. Both
formats are valid according to ISO 8601 (so anything that
expects ISO 8601 date/times should continue working), but only
the last format complies with the XML Schema date/time formats,
hence this change.</para>
</listitem>
<listitem>
<para>New built-in for escaping inside JSON string literals:
<link
linkend="ref_builtin_json_string"><literal>json_string</literal></link>.</para>
</listitem>
<listitem>
<para>Bugfix: Wrong <literal>#</literal> tags were printed as
static text instead of causing parsing error if there was no
correct <literal>#</literal> tag earlier in the same template.
Since fixing this would not be 100% backward compatible, the old
behavior has remained, unless you set the
<literal>incompatible_enhancements</literal> setting
(<literal>Configuration.setIncompatibleEnhancements(String)</literal>)
to <literal>"2.3.19"</literal> or higher.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para xml:id="v2319secfix"><emphasis>Attention</emphasis>: This
release contains two important security workarounds that
unavoidably make it obvious how some applications can be
exploited. <emphasis>FreeMarker can't solve these issues on all
configurations, so please read the details instead of just
updating FreeMarker!</emphasis> Also, these changes are not 100%
backward compatible in theory, however it's not probable that
they will break anything. The two changes are:</para>
<itemizedlist>
<listitem>
<para>The character with character code 0
(<literal>\u0000</literal>) is not allowed in template paths
anymore. When a path contains it, FreeMarker behaves as if
the template was not found.</para>
<para>This is to fix the security problem where a template
path like <literal>"secret.txt\u0000.ftl"</literal> is used
to bypass extension filtering in an application. FreeMarker
itself doesn't care about the extension, but some
applications decide based on the extension if they will
delegate a path to FreeMarker. When they do with such a
path, the C/C++ implementation behind the storage mechanism
may sees the path as <literal>"secret.txt"</literal> as the
0 terminates the string in C/C++, and thus load a non-FTL
file as a template, returning the file contents to the
attacker.</para>
<para>Note that some HTTP servers, notably Tomcat and the
Apache HTTP Server blocks URL-s where the URL contains 0
(<literal>%00</literal>) outside the query string, thus this
wasn't exploitable there through such Web URL-s. Some other
HTTP servers however, like Jetty, doesn't block such
URL-s.</para>
</listitem>
<listitem>
<para><literal>ClassTemplateLoader</literal>, when it's
created with base path <literal>"/"</literal> (like with
<literal>new ClassTemplateLoader(someClass, "/")</literal>),
will not allow template paths that contain colon earlier
than any <literal>/</literal>, and will act like if the
template was not found in such case.</para>
<para>This is to fix the security problem where a template
path like <literal>"file:/etc/secret"</literal> or
<literal>"http://example.com/malware.ftl"</literal> is
interpreted as a full URL by a
<literal>java.net.URLClassLoader</literal> in the
class-loader hierarchy, and thus allow loading files from
these URL-s as templates. This is a quirk (or bug) of
<literal>java.net.URLClassLoader</literal>, thus this
problem only exists on systems that use such
class-loaders.</para>
<para>Beware, some frameworks use their own
<literal>TemplateLoader</literal> implementations, and if
those are vulnerable, they will remain so after updating
FreeMarker too! Note that this exploit only works if the
class-loader hierarchy contains an
<literal>URLClassLoader</literal> and the class-loader is
used to load templates without adding any prefix before the
template path (other than <literal>"/"</literal>).</para>
</listitem>
</itemizedlist>
<para>These security issues mostly only affect applications
<emphasis>where the user (the visitor) can supply arbitrary
template paths to the application</emphasis>. This is not the
case with properly built MVC applications, as there only the MVC
Controller can be addressed directly, and it's the Controller
that specifies the template paths. But legacy MVC applications
based on <link linkend="pgui_misc_servlet_model2">JSP
Model-2</link> often expose the MVC Views as public URL-s ending
with <literal>.ftl</literal>, thus allowing the user to give
arbitrary paths to FreeMarker. Such applications should be
secured with a <literal>security-constratint</literal> in
<literal>web.xml</literal> as shown in the <link
linkend="pgui_misc_servlet_model2">related Manual
section</link>. This should be done regardless of the current
security fixes.</para>
<para>In general, you should not allow users to specify
arbitrary template paths, or if you do allow that, you should be
extra careful with the <literal>TemplateLoader</literal>
used.</para>
</listitem>
<listitem>
<para><literal>Configuration</literal> has new methods:
<literal>removeTemplateFromCache(...)</literal>. This will
remove the given template for the given locale from the cache,
so it will be re-loaded regardless of the template update delay
when it's next time requested.</para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal> ignores setter methods
from now when introspecting classes. They weren't used anyway,
so they unnecessarily caused
"<literal>java.beans.IntrospectionException</literal>: type
mismatch between read and write methods" errors.</para>
</listitem>
<listitem>
<para><literal>TemplateClassResolver.SAFER_RESOLVER</literal>
now disallows creating
<literal>freemarker.template.utility.JythonRuntime</literal> and
<literal>freemarker.template.utility.Execute</literal>. This
change affects the behavior of the <link
linkend="ref_builtin_new"><literal>new</literal> built-in</link>
if FreeMarker was configured to use
<literal>SAFER_RESOLVER</literal>, which is not the default
until 2.4 and is hence improbable.</para>
</listitem>
<listitem>
<para>Bug fixed: Calling varargs methods now indeed works.
(Earlier it only worked for overloaded methods.)</para>
</listitem>
<listitem>
<para>Bug fixed <link
xlink:href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=1837697&amp;group_id=794&amp;atid=100794">[1837697]</link>
<link
xlink:href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=2831150&amp;group_id=794&amp;atid=100794">[2831150]</link>
<link
xlink:href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=3039096&amp;group_id=794&amp;atid=100794">[3039096]</link>
<link
xlink:href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=3165425&amp;group_id=794&amp;atid=100794">[3165425]</link>:
Jython support now works with Jython 2.2 and 2.5.</para>
</listitem>
<listitem>
<para>Bug fixed <link
xlink:href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=3325103&amp;group_id=794&amp;atid=100794">[3325103]</link>:
<literal>TemplateException</literal>-s and
<literal>ParseException</literal>-s are now serializable.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_18">
<title>2.3.18</title>
<para>Date of release: 2011-05-21</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix <link
xlink:href="https://sourceforge.net/tracker/?func=detail&amp;aid=3304568&amp;group_id=794&amp;atid=100794">[3304568]</link>:
2.3.17 didn't find TLD-s in <literal>WEB-INF\lib\*.jar</literal>
unless they were explicitly pointed in the
<literal>web.xml</literal> with a <literal>taglib</literal>
element. This bug was introduced in 2.3.17.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Added <literal>LICENSE.txt</literal> and
<literal>NOTICE.txt</literal> to
<literal>freemarker.jar</literal> under
<literal>META-INF</literal>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_17">
<title>2.3.17</title>
<para>Date of release: 2011-05-17</para>
<para>It's possibly urgent to update to this version because of a
<link linkend="v2317secfix">security fix</link>!</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para><literal>?seq_index_of</literal> and
<literal>?seq_last_index_of</literal> now works on collections
(<literal>freemarker.template.TemplateCollectionModel</literal>-s)
too, not only on sequences
(<literal>freemarker.template.TemplateSequenceModel</literal>-s).</para>
</listitem>
<listitem>
<para><literal>?long</literal> now works for date, date-time or
time values, and returns the milliseconds since the epoch (as
<literal>java.util.Date.getTime()</literal>).</para>
</listitem>
<listitem>
<para>To convert numbers (usually Java
<literal>long</literal>-s) to date or date-time and time values,
<literal>?number_to_date</literal>,
<literal>?number_to_time</literal>,
<literal>?number_to_datetime</literal> was added. <link
linkend="ref_builtin_numToDate">See more here...</link>
(Unfortunately, <literal>?date</literal> and like can't be
extended to support this due to backward compatibility
issues.)</para>
</listitem>
<listitem>
<para>New built-ins to format numbers with ISO 8601 "extended"
format regardless of the current date/time formatting settings,
and even regardless of the current time zone setting. For
example <literal>${myTimeStamp?iso_utc}</literal> will print
something like <literal>2010-05-16T23:05:45Z</literal>. <link
linkend="ref_builtin_date_iso">See more here...</link></para>
</listitem>
<listitem>
<para>New <link linkend="ref_specvar">special variable</link>,
<literal>now</literal>. This returns the current date-time.
Usage examples: "<literal>Page generated: ${.now}</literal>",
"<literal>Today is ${.now?date}</literal>", "<literal>The
current time is ${.now?time}</literal>".</para>
</listitem>
<listitem>
<para><literal>?sort</literal> and <literal>?sort_by</literal>
now supports sorting boolean values.</para>
</listitem>
<listitem>
<para>When using unsupported or unknown <link
linkend="ref_builtin_string_flags">string built-in flags</link>,
FreeMarker will now <link linkend="pgui_misc_logging">log</link>
warnings (maximum 25 times per class-loader, to prevent flooding
the log). It's certain that starting from FreeMarker 2.4 these
will count as errors.</para>
</listitem>
<listitem>
<para>Bug fixed <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=3047201&amp;group_id=794">[3047201]</link>:
Using regular expressions (like with <literal>?match</literal>)
could cause lockup in multi-threaded environment, also memory
leakage when using dynamically generated regular
expressions.</para>
</listitem>
<listitem>
<para>Bug fixed: <literal>?seq_contains</literal>,
<literal>?seq_index_of</literal> and
<literal>?seq_last_index_of</literal> has failed with
non-<literal>java.util.List</literal>
<literal>java.util.Collection</literal>-s that are wrapped with
pure <literal>BeansWrapper</literal> (not the
<literal>DefaultObjectWrapper</literal>) as
<literal>TemplateSequenceModel</literal>. (See also:
<literal>getSupportsIndexedAccess()</literal> below)</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para xml:id="v2317secfix"><emphasis>Security fix</emphasis>:
Using carefully crafted template names (template paths) that
contain code point 0 (<literal>'\u0000'</literal>), it was
possible to load files from outside the template root directory
like if they were FreeMarker templates. The root of the problem
is that the underlying native C/C++ part (which belongs to the
Java platform or to the OS) interprets the 0 as the end of the
string, while Java (and hence FreeMarker and the Servlet
container) doesn't. Thus a path that looked safe for FreeMarker
become unsafe on the lower level. The problem is present with
all ways of loading templates by name
(<literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>,
<literal>&lt;#include
<replaceable>...</replaceable>&gt;</literal>,
<literal>&lt;#import
<replaceable>...</replaceable>&gt;</literal>).</para>
<para>You are not affected if you don't allow users to upload
templates and also at least one of these stands:</para>
<itemizedlist>
<listitem>
<para>In your system users can't provide arbitrary strings
as template names (template paths). For example, if users
are only allowed to visit the URL-s that belong to the MVC
Controller (like they can't visit <literal>*.ftl</literal>)
then they can't suggest arbitrary template names.</para>
</listitem>
<listitem>
<para>The template names are part of the path in the Web
page URL, and your webserver or Servlet container disallows
URL-s that contain <literal>%00</literal>, or terminate the
URL at it before passing it to the servlets.</para>
</listitem>
<listitem>
<para>You are using <literal>FileTemplateLoader</literal>
and linking is not allowed in it (by default it isn't
allowed).</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>FreeMarker now can log its messages directly using SLF4J
or Apache Commons Logging. However, it will not use these logger
libraries automatically, until 2.4; <link
linkend="pgui_misc_logging">see more here...</link> But it's
recommended to switch to SLF4J now.</para>
</listitem>
<listitem>
<para>New setting: <literal>"auto_flush"</literal>,
<literal>Configurable.setAutoFlush(boolean)</literal>. Sets
whether the output <literal>Writer</literal> is automatically
flushed at the end of <literal>Template.process(Object,
Writer)</literal> (and its overloads). The default is
<literal>true</literal>, which corresponds to the earlier
behavior. Using <literal>false</literal> is needed for example
when a Web page is composed from several boxes (like portlets,
GUI panels, etc.) that aren't inserted with
<literal>#include</literal> (or with similar directives) into a
master FreeMarker template, rather they are all processed with a
separate
<literal>Template.process(<replaceable>...</replaceable>)</literal>
call. In a such scenario the automatic flushes would commit the
HTTP response after each box, hence interfering with full-page
buffering, and also possibly decreasing performance with too
frequent and too early response buffer flushes.</para>
</listitem>
<listitem>
<para>Added new setting:
<literal>Configuration.setNewBuiltinClassResolver(TemplateClassResolver)</literal>,
or <literal>new_builtin_class_resolver</literal> property. This
allows you to specify how the <link
linkend="ref_builtin_new"><literal>new</literal> built-in</link>
(like in <literal>"com.example.SomeClass"?new()</literal>)
resolves classes and which classes are accessible at all. If you
are allowing not-so-much-trusted users to upload templates, you
should be definitely interested; see the Java API docs of
<literal>freemarker.core.Configurable.setSetting</literal> and
<literal>freemareker.template.Configuration.setNewBuiltinClassResolver</literal>.
Otherwise it's still recommended to set this to
<literal>TemplateClassResolver.SAFER_RESOLVER</literal> (or
<literal>safer</literal> if you are using properties), although
that's not 100% backward compatible (see Java API docs) .</para>
</listitem>
<listitem>
<para>Added
<literal>freemarker.cache.NullCacheStorage</literal>: Setting
this as the cache storage in <literal>Configuration</literal>
disables caching.</para>
</listitem>
<listitem>
<para>Added <literal>getSupportsIndexedAccess()</literal> to
<literal>freemarker.ext.beans.CollectionModel</literal>, so one
can check if <literal>TemplateSequenceModel.get(int)</literal>
will work with a particular <literal>CollectionModel</literal>
instance or not.</para>
</listitem>
<listitem>
<para>Bug fixed <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;aid=2992265&amp;group_id=794&amp;atid=100794">[2992265]</link>:
JSP <literal>FreeMarkerPageContext.include</literal> behaved
incorrectly.</para>
</listitem>
<listitem>
<para>Bug fixed: When using FreeMarker's JSP support with JSP
tags that use
<literal>javax.servlet.jsp.PageContext.pushBody</literal> (like
some Stripes tags), <literal>"ArrayIndexOutOfBoundsException:
-1"</literal> occurred inside
<literal>freemarker.ext.jsp.FreeMarkerPageContext.popWriter</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=3033015&amp;group_id=794">[3033015]</link>:
<literal>AllHttpScopesHashModel</literal> used
<literal>WrappingTemplateModel.getDefaultObjectWrapper()</literal>
for wrapping variables in the page scope, while used the
user-specified <literal>ObjectWrapper</literal> for all other
scopes (request, session, etc.). Now it uses the user-specified
wrapper in the page scope as well.</para>
</listitem>
<listitem>
<para>Bug fixed <link
xlink:href="https://sourceforge.net/tracker/?func=detail&amp;aid=3128073&amp;group_id=794&amp;atid=100794">[3128073]</link>:
<literal>HashAdapther.containsKey(...)</literal> returned
<literal>true</literal> for a key that doesn't exist when
unwrapping the key has failed. As a side effect of the fix,
<literal>BeansWrapper.CAN_NOT_UNWRAP</literal> is now private;
earlier it was public by mistake.</para>
</listitem>
<listitem>
<para>Big fixed <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;aid=3151085&amp;group_id=794&amp;atid=100794">[3151085]</link>:
<literal>freemarker.jsp.TaglibFactory</literal> didn't locate
tld files properly. This fix gives better compliance with JSP
specification for resolving and loading tld files.</para>
</listitem>
<listitem>
<para>Bug fixed: Unwrapping <literal>null</literal> with a
<literal>BeansWrapper</literal> that had a custom null-model
didn't result in <literal>null</literal>. Now both unwrapping
<literal>null</literal> and the custom null-model gives
<literal>null</literal>.</para>
</listitem>
<listitem>
<para>Log messages doesn't contain line-breaks (CR or LF)
anymore and quote paths and other arbitrary text with Java
string literal syntax that also escapes <literal>&lt;</literal>
characters as <literal>\u003C</literal>. These address security
concerns related to poor quality log appenders and buggy log
readers. This change is mostly noticeable on template processing
error entries, which will now quote the exception message. Note
that how stack traces (the <literal>Throwable</literal> objects)
are logged is still up to the logging framework you are
using.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>The DTD-s and XSD-s that are included in
<literal>freemarker.jar</literal> under
<literal>freemarker/ext/jsp</literal> are now under Apache
Software License, Version 2. This is also clarified in the
<literal>LICENSE.txt</literal>. Earlier these files had no clear
license terms.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_16">
<title>2.3.16</title>
<para>Date of release: 2009-12-07</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Fixed a bug that caused incorrect unwrapping of sequences
to Java arrays (<link
xlink:href="https://sourceforge.net/tracker/?func=detail&amp;aid=2105310&amp;group_id=794&amp;atid=100794">See
bug report</link>)</para>
</listitem>
<listitem>
<para>Fixed a bug that caused rounding of float and double
values (<link
xlink:href="https://sourceforge.net/tracker/?func=detail&amp;aid=2503124&amp;group_id=794&amp;atid=100794">See
bug report</link>)</para>
</listitem>
<listitem>
<para>Created a new
<literal>freemarker.runtime.attempt</literal> category and
exceptions caught in <literal>&lt;#attempt&gt;</literal> blocks
are logged into it at a DEBUG severity.</para>
</listitem>
<listitem>
<para>Fixing the (ages old) problem of
<literal>RhinoWrapper</literal> not working with all versions of
Rhino because of binary incompatible change of Rhino's
<literal>Undefined.instance</literal>.</para>
</listitem>
<listitem>
<para>Fixed bug where <literal>TextUtil.XMLEncNQG</literal>
didn't escape <literal>]]&gt;</literal> as
<literal>]]&amp;gt;</literal>.</para>
</listitem>
<listitem>
<para>Fixed bug where the root directory couldn't be used as the
template base directory, as
<literal>FileTemplateLoader</literal> believed that the template
is outside the base directory.</para>
</listitem>
<listitem>
<para>Macro names can no longer be changed through the
API.</para>
</listitem>
<listitem>
<para>FreemarkerServlet now cooperates with Session Fixation
Attack Protection in Spring Security, see <link
xlink:href="https://sourceforge.net/projects/freemarker/forums/forum/2345/topic/3475868">
forum discussion</link> for details.</para>
</listitem>
<listitem>
<para>Substantially improved performance of the
<literal>&lt;#return&gt;</literal> directive.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Fixed bug where
<literal><replaceable>anXMLNode</replaceable>.@@markup</literal>
and <literal>@@nested_markup</literal> didn't escape
<literal>]]&gt;</literal> as
<literal>]]&amp;gt;</literal>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_15">
<title>2.3.15</title>
<para>Date of release: 2008-12-16</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Bug fixed: Hash concatenation (like <literal>hash1 +
hash2</literal>) shuffled the order of keys/values even if both
hashes were ordered.</para>
</listitem>
<listitem>
<para>In web pages that are based on the
<literal>FreemarkerServlet</literal>, you can now use
<literal>&lt;@include_page path="..."/&gt;</literal> to use
servlet includes. See more <link
linkend="pgui_misc_servlet_include">here...</link></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>The <literal>BeansWrapper</literal> can automatically
detect that classes were reloaded by JavaRebel.</para>
</listitem>
<listitem>
<para>Fixed a bug that caused <literal>null</literal> to be
returned from
<literal>Environment.getCurrentEnvironment()</literal> while
processing autoincludes and autoimports. (<link
xlink:href="https://sourceforge.net/forum/message.php?msg_id=5531621">See
bug report</link>)</para>
</listitem>
<listitem>
<para>Fixed a bug that caused
<literal>getObject(Object)</literal> method on POJOs to not be
recognized as a general get method.</para>
</listitem>
<listitem>
<para>Substantially improved performance of the
<literal>&lt;#break&gt;</literal> directive.</para>
</listitem>
<listitem>
<para><literal>DeepUnwrap</literal> now unwraps custom null
model of the current object wrapper into a Java
<literal>null</literal>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_14">
<title>2.3.14</title>
<para>Date of release: 2008-09-01</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New built-in: <literal>xhtml</literal>. See more <link
linkend="ref_builtin_xhtml">here...</link></para>
</listitem>
<listitem>
<para>New special variable: <literal>template_name</literal>.
See more <link linkend="ref_specvar">here...</link></para>
</listitem>
<listitem>
<para>Now you can use the values of parameters as the defaults
of other parameters, for example <literal>&lt;#macro section
title label=title&gt;</literal>. In earlier versions it worked
unreliably. There are no restriction regarding the order of
parameters, like <literal>&lt;#macro section label=title
title&gt;</literal> works too.</para>
</listitem>
<listitem>
<para>Added a new <link
linkend="ref_builtin_string_for_number">number format
specifier</link>, <literal>computer</literal>. This uses the
same formatting as
<literal><replaceable>exp</replaceable>?c</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>The constructor to
<literal>freemarker.ext.servlet.AllHttpScopesHashModel</literal>
is now public, allowing it to be reused in 3rd party web
frameworks.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.ext.beans.SimpleMapModel</literal> (unlike
either <literal>freemarker.ext.beans.MapModel</literal> or
<literal>freemarker.template.SimpleHash</literal>) didn't allow
lookup by <literal>java.lang.Character</literal> key when passed
a single-character string as a key.</para>
</listitem>
<listitem>
<para>Bugfix: permissive unwrapping in
<literal>freemarker.template.utility.DeepUnwrap</literal> class
was not recursively permissive with elements of sequences and
hashes.</para>
</listitem>
<listitem>
<para>Bugfix: <literal>freemarker.ext.beans.MapModel</literal>
returns <literal>BeansWrapper.wrap(null)</literal> instead of
<literal>null</literal> for <literal>null</literal> values
explicitly bound into the map.</para>
</listitem>
<listitem>
<para>Bugfix: Fixed a subtle bug with property getters of
classes implementing a type-parametrized interface.</para>
</listitem>
<listitem>
<para>Bug fixed: A further corner case of <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1939742&amp;group_id=794&amp;atid=100794">[1939742]</link>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_13">
<title>2.3.13</title>
<para>Date of release: 2008-05-05</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New built-ins for rounding numbers:
<literal>round</literal>, <literal>floor</literal>,
<literal>ceiling</literal>. See more <link
linkend="ref_builtin_rounding">here...</link></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1898300&amp;group_id=794&amp;atid=350794">[1898300]</link>,
<link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1818742&amp;group_id=794&amp;atid=350794">[1818742]</link>,
<link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1780882&amp;group_id=794&amp;atid=350794">[1780882]</link>:
Reworked template caching mechanism for radically improved
concurrent performance, with help from Azul Systems engineers.
(Achieved 20x speedup with Struts2 webapps on a 128-CPU Azul
device compared to 2.3.12.) Also, template loading (including
parsing) errors are now cached, improving performance in
applications that often try to get missing templates.</para>
</listitem>
<listitem>
<para><link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1892546&amp;group_id=794&amp;atid=100794">[1892546]</link>
Allow for custom <literal>TemplateLoader</literal> in
<literal>FreemarkerServlet</literal>.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1725107&amp;group_id=794&amp;atid=100794">[1725107]</link>
Using the FreeMarker JSP taglib support with Servlet 2.4 may
generates XML validation warnings.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1939742&amp;group_id=794&amp;atid=100794">[1939742]</link>
<literal>ConcurrentModificationException</literal> on accessing
nonexistent <literal>SimpleHash</literal> entries in a
loop</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1902012&amp;group_id=794&amp;atid=100794">[1902012]</link>
<literal>IteratorModel</literal> eats exception causes</para>
</listitem>
<listitem>
<para>Bug fixed: <literal>&lt;#assign
x&gt;&lt;/#assign&gt;</literal> (empty nested content) has
caused <literal>NullPointerException</literal></para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1926150&amp;group_id=794&amp;atid=100794">[1926150]</link>
<literal>CachedTemplate</literal> should be serializable</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_12">
<title>2.3.12</title>
<para>Date of release: 2008-02-03</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1857161&amp;group_id=794&amp;atid=100794">[1857161]</link>
JSP <literal>SimpleTag</literal> support was broken in
2.3.11.</para>
</listitem>
<listitem>
<para>In the templates, now you can conveniently call Java
methods that use the Java 5 varargs feature (variable-length
argument lists). Also the overloaded-method chooser logic now
considers vararg methods more intelligently.</para>
</listitem>
<listitem>
<para>Enum constants are now identified by their
<literal>name()</literal> instead of by their
<literal>toString()</literal> (because the latter can be
overridden in subclasses). This doesn't affect the way enum
constants are printed; of course that still uses
<literal>toString()</literal>.</para>
</listitem>
<listitem>
<para>Messages in parser exceptions now display the name of the
template.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_11">
<title>2.3.11</title>
<para>Date of release: 2007-12-04</para>
<para>This release contains several performance and usability
improvements.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1687248&amp;group_id=794&amp;atid=100794">[1687248]</link>
<emphasis role="bold">Warning! This bugfix may breaks some
templates!</emphasis> Fixed the bugs of the <link
linkend="ref_builtin_c"><literal>c</literal> built-in</link>
(<literal>?c</literal>) that sometimes caused whole numbers to
be formatted with <quote>.0</quote> at the end (like: 1.0), and
caused numbers sometimes formatted to exponential form (like
4E-20). From now whole numbers will never use decimal dot (not
even if the wrapped number is a <literal>double</literal>;
remember, the template language knows only a single numerical
type), and exponential form will never be used either. Also, the
maximum number of digits after the decimal dot was limited to
16, so numbers smaller than 1E-16 will be shown as 0.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>FreeMarker now has much better JSP 2.0 and JSP 2.1
compliance. Most notably, the JSP 2.0
<literal>SimpleTag</literal> interface is now supported.
Additionally, even when run in an environment that doesn't have
its own JSP implementation, the FreeMarker JSP runtime will make
available its own implementation of
<literal>JspFactory</literal> and
<literal>JspEngineInfo</literal> to tags when JSP 2.0 API JAR is
available in classpath, as well as an implementation of
<literal>JspApplicationContext</literal> when JSP 2.1 API JAR is
available in classpath.</para>
</listitem>
<listitem>
<para>A new model interface,
<literal>TemplateDirectiveModel</literal> provides an easier
paradigm for implementing user-defined directives than
<literal>TemplateTransformModel</literal> did previously.
<literal>TemplateTransformModel</literal> will be
deprecated.</para>
</listitem>
<listitem>
<para>FreeMarker now finds the Xalan-based XPath support
included in Sun JRE/JDK 5 and 6, so no separate Xalan jar is
required for the XPath support to work. (However, we recommend
Jaxen over Xalan, as the FreeMarker XPath support is more
complete with that. Of course for that the Jaxen jar is still
needed.)</para>
</listitem>
<listitem>
<para>Wrapping performance of <literal>BeansWrapper</literal>
has been significantly improved by eliminating repetitive
execution of various class tests.</para>
<para><emphasis role="bold">Note for
<literal>BeansWrapper</literal> customizers:</emphasis>
subclasses of <literal>BeansWrapper</literal> that previously
overrode <literal>getInstance(Object, ModelFactory)</literal>
method should now instead override
<literal>getModelFactory(Class)</literal> to take advantage of
this improvement. Overriding the old method still works, but it
will not take advantage of the performance improvement.</para>
</listitem>
<listitem>
<para>Memory footprint of a wrapper created by
<literal>BeansWrapper</literal> has been reduced (by a size of
one default-sized <literal>HashMap</literal>) until methods or
indexed properties are accessed on it (simple properties can be
accessed without increasing memory footprint).</para>
</listitem>
<listitem>
<para>Rhino objects can be used in templates as scalars,
numbers, and booleans, following the JavaScript conversion
semantics for these types.</para>
</listitem>
<listitem>
<para><literal>.data_model</literal> is now a
<literal>TemplatHashModelEx</literal> when possible. This means
that the list of the data-model variable names usually can be
get with <literal>.data_model?keys</literal>.</para>
</listitem>
<listitem>
<para><literal>FileTemplateLoader</literal> can now optionally
allow following symlinks that point out of the base directory.
It is disabled by default for backward compatibility.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1670887&amp;group_id=794&amp;atid=100794">[1670887]</link>
<literal>TaglibFactory</literal> taglib matching did not follow
JSP 1.2 FCS.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1754320&amp;group_id=794&amp;atid=100794">[1754320]</link>
Bug in <literal>setXPathSupportClass</literal> prevented
plugging in a user-supplied <literal>XPathSupport</literal>
implementation.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1803298&amp;group_id=794&amp;atid=100794">[1803298]</link>
Parser error while parsing macro with loop variables</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1824122&amp;group_id=794&amp;atid=100794">[1824122]</link>
Loading templates from JAR files could lead to leaking of file
handles (due to a bug in the Java API implementation of
Sun).</para>
</listitem>
<listitem>
<para>Bug fixed: Cached template is now removed from the cache
if the re-loading of the modified template file fails, so no
staled template is served.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Documentation changes</title>
<itemizedlist>
<listitem>
<para>Substantial reworkings in the Template Authors's Guide
(which was previously called Designer's Guide), especially in
the Getting Started section.</para>
</listitem>
<listitem>
<para><literal>#{...}</literal> is documented as deprected
construct from now.</para>
</listitem>
<listitem>
<para>The "transform" term is now removed from the
documentation. Instead the more general "user-defined directive"
term is used, which encompasses macros,
<literal>TemplateTransformModel</literal>-s and the new
<literal>TemplateDirectiveModel</literal>-s, which are just
different ways of implementing user-defined directives.</para>
</listitem>
<listitem>
<para>Some more minor improvements in the Manual.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_10">
<title>2.3.10</title>
<para>Date of release: 2007-04-20</para>
<para>This release contains several important bugfixes.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>[1589245] <literal>MultiTemplateLoader</literal> clears
its internal cached data (used for optimizing subsequent lookups
of the same template) when
<literal>Configuration.clearTemplateCache()</literal> is
invoked.</para>
</listitem>
<listitem>
<para>[1619257] A bug that caused an exception when
<literal>strict_bean_model</literal> was used in a FreeMarker
configuration <literal>Properties</literal> object or in the
<literal>&lt;#setting .../&gt;</literal> directive has been
fixed.</para>
</listitem>
<listitem>
<para>[1685176] A bug that caused
<literal>StackOverflowError</literal> in certain interactions of
garbage collector with MRU cache under Sun's Java 6 JVM has been
fixed.</para>
</listitem>
<listitem>
<para>[1686955] When <literal>ResourceBundleModel</literal>
constructs <literal>MessageFormat</literal> objects, it passes
them its own locale. <link linkend="beanswrapper_method">More
info...</link></para>
</listitem>
<listitem>
<para>[1691432] A bug that caused
<literal>BeansWrapper.EXPOSE_SAFE</literal> to be no safer than
<literal>BeansWrapper.EXPOSE_ALL</literal> has been
fixed.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>[1628550] You can now use
<literal>dateExp?string.full</literal> for formatting dates
using Java built-in format
<literal>java.util.Date.FULL</literal> <link
linkend="ref_builtin_string_for_date">More info...</link></para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_9">
<title>2.3.9</title>
<para>Date of release: 2007-01-23</para>
<para>This release contains support for accessing JDK 1.5 enums and
public fields of classes from the templates through the
BeansWrapper.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><literal>BeansWrapper</literal> can now expose public
fields of objects to the template if you call the
<literal>setExposeFields(true)</literal> on it. <link
linkend="beanswrapper_hash">More info...</link></para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal> can now pass any sequence
model to Java methods expecting a
<literal>java.util.Collection</literal> or a native Java array
(including primitive arrays). <link
linkend="beanswrapper_hash">More info...</link></para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal> can now pass any sequence
and collection model to Java methods expecting a
<literal>java.lang.Iterable</literal>. <link
linkend="beanswrapper_hash">More info...</link></para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal> can now unwrap numeric
models into correct target types when passing to Java methods
expecting a primitive or boxed number. Use of various <link
linkend="ref_builtins_expert">expert built-ins</link> to
manually coerce the types becomes mostly unnecessary.</para>
</listitem>
<listitem>
<para>Fixed a bug where <literal>BeansWrapper</literal> would
pass a <literal>java.util.Collection</literal> to a method
expecting a <literal>java.util.Set</literal> in certain rare
cases. <link linkend="beanswrapper_hash">More
info...</link></para>
</listitem>
<listitem>
<para>Support for JDK 1.5 enums in
<literal>BeansWrapper</literal> and
<literal>DefaultObjectWrapper</literal>. By calling the
<literal>getEnumModels()</literal> method, you can retrieve a
hash model that is keyed by class names and allows access to
enumerated values. I.e. if you bind this hash model under name
<literal>enums</literal> in the data-model, you can write
expressions like
<literal>enums["java.math.RoundingMode"].UP</literal> in the
template. The enum values can be used as scalars and support
equality and inequality comparisons. <link
linkend="jdk_15_enums">More info...</link></para>
</listitem>
<listitem>
<para><literal>freemarker.ext.rhino.RhinoWrapper</literal> now
correctly translates Rhino <literal>Undefined</literal>
instance, <literal>UniqueTag.NOT_FOUND</literal>, and
<literal>UniqueTag.NULL</literal> to FreeMarker undefined
value.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_8">
<title>2.3.8</title>
<para>Date of release: 2006-07-09</para>
<para>This release substantially improves the JSP 2.0 compatibility.
(For those who have seen the same points in 2.3.7: Sorry, the version
history was incorrect... those JSP 2.0 related changes were not in the
release yet.)</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>JSP support improvement: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1326058&amp;group_id=794">[1326058]</link>
Added support for <literal>DynamicAttributes</literal> (new in
JSP 2.0)</para>
</listitem>
<listitem>
<para>JSP support improvement: Added support for
<literal>pushBody()</literal>/<literal>popBody()</literal> in
<literal>FreemarkerPageContext</literal></para>
</listitem>
<listitem>
<para>JSP support improvement: Added support for
<literal>getVariableResolver()</literal> (new in JSP
2.0).</para>
</listitem>
<listitem>
<para>JSP support improvement: Added support for
<literal>include(String, boolean)</literal> (new in JSP
2.0).</para>
</listitem>
<listitem>
<para>JSP support improvement: Added support for
<literal>getExpressionEvaluator()</literal> (new in JSP 2.0).
However, it will need Apache commons-el in the class path, or
else this method will not work (it's optional). Note that EL
support is not needed in principle, since FreeMarker has it's
own expression language. But some custom JSP 2 tags may still
want to use this method, after all it's in the JSP 2 API.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_7">
<title>2.3.7</title>
<para>Date of release: 2006-06-23</para>
<para>This release, compared to 2.3.7 RC1, contains new operators for
handling null/missing variables, , the <literal>substring</literal>
built-in, and some more bugfixes. Note that 2.3.7 RC1 has a long
change log, so you may want to <link linkend="versions_2_3_7rc1">read
that</link> too.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>The <literal>seq_contains</literal> built-in now handles
<literal>TemplateCollectionModel</literal>-s as well.</para>
</listitem>
<listitem>
<para>Bug fixed: In 2.3.7 RC1
<literal>FreemarkerServlet</literal> has always died with
<literal>NullPointerException</literal> during
initialization.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>3 new operators were added for terser missing variable
handling. These operators make the <literal>default</literal>,
<literal>exists</literal> and <literal>if_exists</literal>
built-ins deprecated. (The parser doesn't issue any warning
messages when you use deprecated built-ins, and they are still
working.):</para>
<itemizedlist>
<listitem>
<para><literal><replaceable>exp1</replaceable>!<replaceable>exp2</replaceable></literal>
is near equivalent with
<literal><replaceable>exp1</replaceable>?default(<replaceable>exp2</replaceable>)</literal>,
also
<literal>(<replaceable>exp1</replaceable>)!<replaceable>exp2</replaceable></literal>
is near equivalent with
<literal>(<replaceable>exp1</replaceable>)?default(<replaceable>exp2</replaceable>)</literal>.
The only difference is that this new operator doesn't
evaluate the
<literal><replaceable>exp2</replaceable></literal> when the
default value is not needed.</para>
</listitem>
<listitem>
<para><literal><replaceable>exp1</replaceable>!</literal> is
similar to
<literal><replaceable>exp1</replaceable>?if_exists</literal>,
also <literal>(<replaceable>exp1</replaceable>)!</literal>
is similar to
<literal>(<replaceable>exp1</replaceable>)?if_exists</literal>.
The difference is that with this new operator the default
value is an empty string and an empty list and empty hash at
the same time (multi-type variable), while with
<literal>if_exists</literal> the default value was an empty
string and an empty list and empty hash and boolean
<literal>false</literal> and a transform that does nothing
and ignores all parameters at the same time.</para>
</listitem>
<listitem>
<para><literal><replaceable>exp1</replaceable>??</literal>
is equivalent with
<literal><replaceable>exp1</replaceable>?exists</literal>,
also <literal>(<replaceable>exp1</replaceable>)??</literal>
is equivalent with with
<literal>(<replaceable>exp1</replaceable>)?exists</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>New built-in:
<literal><replaceable>exp</replaceable>?substring(<replaceable>from</replaceable>,
<replaceable>toExclusive</replaceable>)</literal>, also callable
as
<literal><replaceable>exp</replaceable>?substring(<replaceable>from</replaceable>)</literal>.
Getting substrings was possible for a long time like
<literal><replaceable>myString</replaceable>[<replaceable>from</replaceable>..<replaceable>toInclusive</replaceable>]</literal>
and
<literal><replaceable>myString</replaceable>[<replaceable>from</replaceable>..]</literal>,
but
<literal><replaceable>myString</replaceable>?substring(<replaceable>from</replaceable>,
<replaceable>toExclusive</replaceable>)</literal> and
<literal><replaceable>myString</replaceable>?substring(<replaceable>from</replaceable>)</literal>
has the advantage that it has an exclusive end, which is more
practical. (Edit: Since 2.3.21 ranges are the preferred way
again, as it has
<literal><replaceable>myString</replaceable>[<replaceable>from</replaceable>..&lt;<replaceable>toExclusive</replaceable>]</literal>.)
Sequence (list) slices still has to be get with the old syntax,
since <literal>substring</literal> only applies to strings.
Please note that the <quote>to</quote> parameter is 1 greater
with this new builtin, as it is an exclusive index. Further
difference is that the <literal>substring</literal> built-in
requires that the <quote>from</quote> index is less than or
equal to the <quote>to</quote> index. So 0 length substrings are
possible now, but not reversed substrings.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1487694&amp;group_id=794">[1487694]</link>
malfunction when the <literal>recover</literal> directive has no
nested content</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_7rc1">
<title>2.3.7 RC1</title>
<para>Date of release: 2006-04-27</para>
<para>This release contains many bugfixes and some
<literal>FreemarkerServlet</literal> related improvements. It's a
Release Candidate, which means that it shouldn't be used in production
environment yet. We recommend this release for development, however.
Please test it.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><literal>FreemarkerServlet</literal> improvement:
<literal>AllHttpScopesHashModel</literal> is now public, so you
can add unlisted variables to the data-model.</para>
</listitem>
<listitem>
<para><literal>FreemarkerServlet</literal> improvement: When it
throws a <literal>ServletException</literal>, the J2SE 1.4 cause
exception is now set under J2SE 1.4.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1469275&amp;group_id=794">[1469275]</link>
<literal>NullPointerException</literal> when using
<literal>BeansWrapper</literal> with reloaded classes</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1449467&amp;group_id=794">[1449467]</link>
<literal>HttpSessionHashModel</literal> is not
<literal>Serializable</literal></para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1435113&amp;group_id=794">[1435113]</link>
Error in <literal>BeanWrapper</literal> with indexed
properties</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1411705&amp;group_id=794">[1411705]</link>
Acquisition bug in <literal>TemplateCache</literal></para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1459699&amp;group_id=794&amp;atid=100794">[1459699]</link>
Tag syntax can't set with
<literal>Configuration.setSetting(String,
String)</literal></para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1473403&amp;group_id=794">[1473403]</link>
<literal>ReturnInstruction.Return</literal> should be
public</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1463664&amp;group_id=794">[1463664]</link>kup
<literal>[/#noparse]</literal> is printed out</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_6">
<title>2.3.6</title>
<para>Date of release: 2006-03-15</para>
<para>Quick release that fixes a serious bug of 2.3.5, days after its
release. So for the recently added new features please <link
linkend="versions_2_3_5">see the section of 2.3.5.</link></para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bug fixed: In FreeMarker 2.3.5 only, when you read a bean
property for the second time, FreeMarker will say that it's
missing (null).</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_5">
<title>2.3.5</title>
<para>Date of release: 2006-03-11</para>
<para><emphasis>This release was withdrawn because of a serious bug in
it. Please don't use it! Of course, all new features of it are
included in FreeMarker 2.3.6.</emphasis></para>
<para>A few new features and several bugfixes.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1435847&amp;group_id=794">[1435847]</link>
Alternative syntax doesn't work for comments</para>
</listitem>
<listitem>
<para>Bug fixed: With the new square bracket syntax, the tag
could be closed with <literal>&gt;</literal>. Now it can be
closed with <literal>]</literal> only.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1324020&amp;group_id=794">[1324020]</link>
<literal>ParseException</literal> with the
<literal>ftl</literal> directive if it wasn't in its own
line</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1404033&amp;group_id=794">[1404033]</link>
<literal>eval</literal> built-in fails with hash
concatenation</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>A new <literal>Configuration</literal> level setting,
<literal>tagSyntax</literal> was added. This determines the
syntax of the templates (angle bracket syntax VS <link
linkend="dgui_misc_alternativesyntax">square bracket
syntax</link>) that has no <literal>ftl</literal> directive in
it. So now you can choose to use the new square bracket syntax
by default. However, the recommended is to use auto-detection
(<literal>yourConfig.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX)</literal>),
because that will be the default starting from 2.4.
Auto-detection chooses syntax based on the syntax of the first
FreeMarker tag of the template (could be any FreeMarker tag, not
just <literal>ftl</literal>). Note that as with the previous
version, if a the template uses <literal>ftl</literal>
directive, then the syntax of the <literal>ftl</literal>
directive determines the syntax of the template, and the
<literal>tagSyntax</literal> setting is ignored.</para>
</listitem>
<listitem>
<para>Now <literal>BeansWrapper</literal>,
<literal>DefaultObjectWrapper</literal> and
<literal>SimpleObjectWrapper</literal> support lookup with 1
character long strings in <literal>Map</literal>-s (like
<literal>myHash["a"]</literal>) that use
<literal>Character</literal> keys. Simply, as a special case,
when a hash lookup fails on a string that is 1 character long,
it checks for the <literal>Character</literal> key in the
underlying map. (Bug tracker entry <link
xlink:href="http://sourceforge.net/tracker/?func=detail&amp;atid=100794&amp;aid=1299045&amp;group_id=794">[1299045]</link>
FreeMarker doesn't support map lookup with Character
keys.)</para>
</listitem>
<listitem>
<para>A new property, <literal>strict</literal> was added to
<literal>BeansWrapper</literal>,
<literal>DefaultObjectWrapper</literal> and
<literal>SimpleObjectWrapper</literal>. If this property is
<literal>true</literal> then an attempt to read a bean propertly
in the template (like <literal>myBean.aProperty</literal>) that
doesn't exist in the bean class (as opposed to just holding
<literal>null</literal> value) will cause
<literal>InvalidPropertyException</literal>, which can't be
suppressed in the template (not even with
<literal>myBean.noSuchProperty?default('something')</literal>).
This way <literal>?default('something')</literal> and
<literal>?exists</literal> and similar built-ins can be used to
handle existing properties whose value is
<literal>null</literal>, without the risk of hiding typos in the
property names. Typos will always cause error. But mind you, it
goes against the basic approach of FreeMarker, so use this
feature only if you really know what are you doing.</para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1426227&amp;group_id=794&amp;atid=100794">[1426227]</link>
<literal>NullPointerException</literal> in
<literal>printStackTrace(...)</literal></para>
</listitem>
<listitem>
<para>Bug fixed: <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1386193&amp;group_id=794&amp;atid=100794">[1386193]</link>
Division by zero in <literal>ArithmeticEngine</literal></para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_4">
<title>2.3.4</title>
<para>Date of release: 2005-10-10</para>
<para>Some new features and bugfixes.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Now you can use <literal>[</literal> and
<literal>]</literal> instead of <literal>&lt;</literal> and
<literal>&gt;</literal> for the FreeMarker tags. For example you
can write <literal>[#if
loggedIn]<replaceable>...</replaceable>[/#if]</literal> and
<literal>[@myMacro /]</literal>. <link
linkend="dgui_misc_alternativesyntax">More info...</link></para>
</listitem>
<listitem>
<para>Bugfix: the <literal>has_content</literal> built-in
returned <literal>false</literal> for number, date and boolean
values (if the value was not a multi-type value that is also a
sequence or collection or hash or string). Now it always returns
<literal>true</literal> for a number, date or boolean values
(except if the value is also a sequence or collection or hash or
string, because then it will be examined only like that).</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: the parameterless constructor of the
<literal>ClassTemplateLoader</literal> didn't worked.</para>
</listitem>
<listitem>
<para>Bugfix: The Jython wrapper didn't wrapped
<literal>java.util.Date</literal> objects well. Now it wraps
them with <literal>BeanWrapper</literal> to
<literal>TemplateDateModel</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: the <literal>include</literal> directive was
blamed when the included file had syntax error.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Minor Manual fixes.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_3">
<title>2.3.3</title>
<para>Date of release: 2005-06-23</para>
<para>Some new features and lot of bugfixes.</para>
<para>Attention:</para>
<itemizedlist>
<listitem>
<para>If you are using the Log4J logging, from now at least Log4J
1.2 is required. This is because of incompatible changes in the
Log4J API.</para>
</listitem>
<listitem>
<para>If you build FreeMarker yourself: from now at least JavaCC
3.2 (instead of JavaCC 2.1) and at least Ant 1.6.1 (instead of Ant
1.5.x) is required. This doesn't affect users who use the
<literal>freemarker.jar</literal> comes with the
distribution.</para>
</listitem>
</itemizedlist>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New built-in for formatting numbers for <quote>computer
audience</quote> as opposed to human audience: <link
linkend="ref_builtin_c"><literal>c</literal></link>. It should
be used for numbers that must use Java language formatting
regardless of the number format and locale settings, like for a
database record ID used as the part of an URL or as invisible
field value in a HTML form, or for printing CSS/JavaScript
numerical literals.</para>
</listitem>
<listitem>
<para>New built-in for the columnar/tabular displaying of
sequences: <link
linkend="ref_builtin_chunk"><literal>chunk</literal></link>.</para>
</listitem>
<listitem>
<para>The <link
linkend="dgui_template_exp_seqenceop_slice">sequence
slice</link> and substring operators now allow the omitting of
the last index, in which case it defaults to the index of the
last sequence item or character. Example:
<literal>products[2..]</literal>. (Also, <link
linkend="dgui_template_exp_direct_seuqence">numerical range
literals</link> now allow the omitting of the final number, in
which case it defaults to infinity. Example:
<literal>5..</literal>.)</para>
</listitem>
<listitem>
<para>Bugfix: <literal>?replace</literal> has worked forever if
the string to replace was <literal>""</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>New template loader:
<literal>freemarker.cache.StringTemplateLoader</literal>. It
uses a <literal>Map</literal> with <literal>Strings</literal> as
its source of templates. See more in the JavaDoc.</para>
</listitem>
<listitem>
<para>Experimental Rhino support: FreeMarker now comes with an
experimental object wrapper for Rhino (Java ECMAScript
implementation):
<literal>freemarker.ext.rhino.RhinoWrapper</literal></para>
</listitem>
<listitem>
<para>Some new utility methods for
<literal>Simple<replaceable>Xxx</replaceable></literal> classes:
<literal>SimpleHash.toMap()</literal>,
<literal>SimpleSequence.toList()</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: FTL literals and any other
<literal>SimpleSequnce</literal>-s, and
<literal>SimpleHash</literal>-es now can be used as parameters
to the FreeMarker-unaware Java methods that are exposed by
<literal>DefaultWrapper</literal> or
<literal>BeansWrapper</literal>. That is, the method parameters
are automatically converted from
<literal>Template<replaceable>Type</replaceable>Model</literal>-s
to <literal>java.util.Map</literal> and
<literal>java.util.List</literal> respectively.</para>
</listitem>
<listitem>
<para>Bugfix: The JSP support now works in JSP 2 compliant
containers as well. No, it doesn't support the new features of
JSP 2 yet, it's just that the JSP 1.2 taglib support has not
worked in JSP 2 containers.</para>
</listitem>
<listitem>
<para>Bugfix: The
<literal>Configuration.setOutputEncoding</literal> and
<literal>setURLEscapingCharset</literal> methods died with
<literal>NullPointerException</literal> when you tried to set
the setting value to <literal>null</literal>, which is legal for
these settings.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.template.utility.StringUtil.replace(...)</literal>
has worked forever if the string to replace was
<literal>""</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: The Log4J logging was updated to be compatible
with the upcoming Log4J 1.3. Note that now FreeMarker will need
at least Log4J 1.2.</para>
</listitem>
<listitem>
<para>Bugfix: FreeMarker didn't built from the source code on
J2SE 1.5, because of the introduction of the
<literal>enum</literal> keyword.</para>
</listitem>
<listitem>
<para>Bugfix: The return value of
<literal>SimpleSequence.synchronizedWrapper()</literal> was not
properly synchronized. Same with
<literal>SimpleHash.synchronizedWrapper()</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: Problem with <literal>BeansWrapper</literal> and
overridden bean methods/properties. (Details: bug-tracker entry
<link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1217661&amp;group_id=794&amp;atid=100794">#1217661</link>
and <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1166533&amp;group_id=794&amp;atid=100794">#1166533</link>)</para>
</listitem>
<listitem>
<para>Bugfix: Can't access JSP taglibs if
<literal>Request</literal> attribute is defined in the
data-model (Details: bug-tracker entry <link
xlink:href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1202918&amp;group_id=794&amp;atid=100794">#1202918</link>).</para>
</listitem>
<listitem>
<para>Bugfix: Various minor parser glitches were fixed.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Manual improvements, especially in the FAQ.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_2">
<title>2.3.2</title>
<para>Date of release: 2005-01-22</para>
<para>Bugfix release.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: If you use JSP taglibs in FreeMarker templates,
FreeMarker possibly tried to get DTD-s from the Sun Web site
because of a bug introduced with FreeMarker 2.3.1. This was a
serious problem since if your server is offline or the Sun Web
site becomes temporarily inaccessible the templates that are
using JSP taglibs will possibly die with error.</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>DefaultObjectWrapper</literal> has
ignored the value of the <literal>nullModel</literal> property.
(Note that it's discouraged to use a <quote>null
model</quote>.)</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_3_1">
<title>2.3.1</title>
<para>Date of release: 2005-01-04</para>
<para>Maintenance (with some important new features) and bugfix
release.</para>
<section>
<title>Possible backward compatibility issue</title>
<para>There is a bugfix that may affect the behavior of you Web
application if you use JSP tags in FreeMarker templates:
FreeMarker's implementation of
<literal>javax.servlet.jsp.PageContext.getSession()</literal> was
incorrect. The <literal>getSession()</literal> method is a
convenience method by which the custom tag can get the current
<literal>HttpSession</literal> object (possibly
<literal>null</literal> if there is no session). Till now, if the
session didn't existed then it has created it automatically, so it
never returned <literal>null</literal>. This was a bug, so starting
from 2.3.1 it never creates the session, just returns
<literal>null</literal> if it doesn't exist. The old incorrect
behavior could cause page rendering to fail if the method is called
after the page is partially flushed. But beware, the old behavior
has possibly hidden some bugs of the Web application, where it
forgot to create the session, so with the new correct behavior you
may face malfunction caused by previously cloaked bugs of the Web
application. (It's the task of the MVC Controller to create the
session, except if the JSP tag that needs a session is written so it
creates it automatically, but then it doesn't expects that
<literal>getSession()</literal> will do it.)</para>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New built-in: <link
linkend="ref_builtin_url"><literal>url</literal></link>. This
built-in can be used for URL escaping. Note, however, that to
use this built-in conveniently, the software that encapsulates
FreeMarker has to be 2.3.1 aware (programmers will find more
info bellow...).</para>
</listitem>
<listitem>
<para>New <link linkend="ref_specvar">special variables</link>:
<literal>output_encoding</literal> and
<literal>url_escaping_charset</literal>. Note, however, that to
use these, the software that encapsulates FreeMarker has to be
2.3.1 aware (programmers will find more info bellow...).</para>
</listitem>
<listitem>
<para>New built-ins for sequences: <link
linkend="ref_builtin_seq_contains"><literal>seq_contains</literal></link>,
<link
linkend="ref_builtin_seq_index_of"><literal>seq_index_of</literal></link>,
<link
linkend="ref_builtin_seq_last_index_of"><literal>seq_last_index_of</literal></link>.</para>
</listitem>
<listitem>
<para>New built-ins for strings: <link
linkend="ref_builtin_left_pad"><literal>left_pad</literal></link>,
<link
linkend="ref_builtin_right_pad"><literal>right_pad</literal></link>
and <link
linkend="ref_builtin_contains"><literal>contains</literal></link>.</para>
</listitem>
<listitem>
<para>New directive: <link
linkend="ref.directive.attempt"><literal>attempt</literal>/<literal>recover</literal></link></para>
</listitem>
<listitem>
<para>The <link
linkend="ref_builtin_js_string"><literal>js_string</literal>
built-in</link> now escapes <literal>&gt;</literal> as
<literal>\&gt;</literal> (to avoid
<literal>&lt;/script&gt;</literal>).</para>
</listitem>
<listitem>
<para>The <literal>sort</literal> and <literal>sort_by</literal>
built-ins now can sort by date values. Also,
<literal>sort_by</literal> built-in now can sort by the
subvarible of a subvariable of a subvariable... etc. for any
level depth. (<link
linkend="ref_builtin_sort_by">Details...</link>)</para>
</listitem>
<listitem>
<para><literal>freemarker.template.TemplateExceptionHandler.HTML_DEBUG_HANDLER</literal>
now prints more HTML-context-proof messages.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>New setting: <literal>output_encoding</literal>. This
setting is used for informing FreeMarker about the charset that
the enclosing software (as a Web application framework) uses for
the output of FreeMarker. It's undefined by default, and
although it is not strictly required to set it, the enclosing
software should do so. This setting must be set if templates
want to use the new <literal>output_encoding</literal> special
variable, and possibly if they want to use the new
<literal>url</literal> built-in. Note that the FreeMarker API
allows you to set settings for each template execution
individually (look at
<literal>Template.createProcessingEnvironment(...)</literal>).</para>
</listitem>
<listitem>
<para>New setting: <literal>url_escaping_charset</literal>. This
is the charset used for calculating the escaped parts
(<literal>%<replaceable>XX</replaceable></literal>) when you do
URL escaping with the new <literal>url</literal> built-in. If it
is not set, then the <literal>url</literal> built-in uses the
value of the <literal>output_encoding</literal> setting, and if
that's not set either, then the parameterless version of
<literal>url</literal> built-in (<literal>${foo?url}</literal>)
can't be used.</para>
</listitem>
<listitem>
<para>Using the singleton (static)
<literal>Configuration</literal> instance is clearly a bad
practice, so related methods are now deprecated, and the Manual
was adjusted, and the <literal>FreemarkerXmlTask</literal> was
updated as well.</para>
</listitem>
<listitem>
<para>The
<literal>freemarker.template.utility.Constants</literal> class
was added that contains various static final fields that store
frequently used constant <literal>TemplateModel</literal>
values, as <literal>EMPTY_SEQUENCE</literal>,
<literal>ZERO</literal>, ...etc.</para>
</listitem>
<listitem>
<para>When using <literal>SecurityManager</literal> with
FreeMarker, accessing system properties may caused
AccessControlException. Now such exceptions are catched and
logged with warning level, and the default value of the property
is returned.</para>
</listitem>
<listitem>
<para>The needles <literal>InvocationTargetException</literal>
is now removed from the exception cause trace in certain
cases.</para>
</listitem>
<listitem>
<para>Added a dirty hack that prints
<literal>ServletException</literal> root cause in
<literal>TemplateException</literal>'s stack trace if that's the
direct cause exception of the
<literal>TemplateException</literal>, despite the poorly written
<literal>ServletException</literal> class.</para>
</listitem>
<listitem>
<para>Bugfix: FreeMarker's implementation of
<literal>javax.servlet.jsp.PageContext.getSession()</literal>
was incorrect. The <literal>getSession()</literal> method is a
convenience method by which the custom tag can get the current
<literal>HttpSession</literal> object (possibly
<literal>null</literal> if there is no session). Till now, if
the session didn't existed then it has created it automatically,
so it never returned <literal>null</literal>. This was a bug, so
starting from 2.3.1 it never creates the session, just returns
<literal>null</literal> if it doesn't exist. The old incorrect
behavior could cause page rendering to fail if the method is
called after the page is partially flushed. But beware, the old
behavior has possibly hidden some bugs of the Web application,
where it forgot to create the session, so with the new correct
behavior you may face malfunction caused by previously cloaked
bugs of the Web application. (It's the task of the MVC
Controller to create the session, except if the JSP tag that
needs a session is written so it creates it automatically, but
then it doesn't expects that <literal>getSession()</literal>
will do it.)</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>BeansWrapper</literal> didn't always
handled properly the case of a Java class having both a public
static field and a public static method with the same
name.</para>
</listitem>
<listitem>
<para>Bugfix: <literal>SimpleMethodModel</literal> had
incorrectly propagate exceptions sometimes, causing null pointer
exception.</para>
</listitem>
<listitem>
<para>Bugfix: The template execution may used outdated cached
values when you have processed the same
<literal>Environment</literal> for multiple times, and changed
settings between the two processings. Note that this could
happen only in single-thread environment, where such setting
modifications are allowed.</para>
</listitem>
<listitem>
<para>Bugfix: Some of the string built-ins has died with
<literal>IndexOutOfBounds</literal> exception if the template
author has forgotten to specify required parameters. Now they
die with more helpful error messages.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.ext.dom.NodeModel.equals(...)</literal> has
died with null pointer exception if its argument was
<literal>null</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: The cause exception of
<literal>TemplateException</literal>-s was sometimes printed
twice in stack traces with J2SE 1.4 or later.</para>
</listitem>
<listitem>
<para>Bugfix: The
<literal>StringUtil.FTLStringLiteralEnc(String)</literal> method
was finished.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Fixes and improvements in the Manual and in the API
JavaDoc.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>The history of the releases before the final version</title>
<section>
<title>Differences between the preview release and final
release</title>
<itemizedlist>
<listitem>
<para>Added a dirty hack that prints
<literal>ServletException</literal> root cause in
<literal>TemplateException</literal>'s stack trace if that's
the direct cause exception of the
<literal>TemplateException</literal>, despite the poorly
written <literal>ServletException</literal> class.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.ext.dom.NodeModel.equals(...)</literal>
has died with null pointer exception if its argument was
<literal>null</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: The cause exception of
<literal>TemplateException</literal>-s was sometimes printed
twice in stack traces with J2SE 1.4 or later.</para>
</listitem>
<listitem>
<para>More minor improvements in the Manual.</para>
</listitem>
</itemizedlist>
</section>
</section>
</section>
<section xml:id="versions_2_3">
<title>2.3</title>
<para>Date of release: 2004-June-15</para>
<para>FreeMarker 2.3 introduces numerous little new features and
quality improvements compared to the 2.2.x series. The most notable
improvements are the ability to define functions (methods) in
templates, the ability to interpolate variables in string literals,
the support for a variable number of macro parameters, and the more
intelligent default object wrapper. Although none of the improvements
is a drastic change, the 2.3.x series is not backward compatible with
the 2.2.x series (see the list below), so you may choose to use it for
new projects only.</para>
<para>Probably the most <quote>loudly promoted</quote> new feature is
the totally redesigned XML wrapper. With the new XML wrapper
FreeMarker targets a new application domain, which is similar to the
application domain of XSLT: transforming complex XML to whatever
textual output. Although this subproject is young, it is definitely
usable in practice. See the <link linkend="xgui">XML Processing
Guide</link> for more details.</para>
<section>
<title>Non backward-compatible changes!</title>
<itemizedlist>
<listitem>
<para>Since interpolations (<literal>${...}</literal> and
<literal>#{...}</literal>) now work inside string literals, the
character sequence <literal>${</literal> and
<literal>#{</literal> in string literals are reserved for that.
So if you have something like <literal>&lt;#set x =
"${foo}"&gt;</literal>, then you have to replace it with
<literal>&lt;#set x = r"${foo}"&gt;</literal> -- beware, escapes
such as <literal>\n</literal> will not work in raw
(<literal>r</literal>) strings.</para>
</listitem>
<listitem>
<para>The default (initial) value of the
<literal>strict_syntax</literal> setting has been changed from
<literal>false</literal> to <literal>true</literal>. When
<literal>strict_syntax</literal> is <literal>true</literal>,
tags with old syntax as <literal>&lt;include
"foo.ftl"&gt;</literal> will be considered as static text (so
they go to the output as-is, like HTML tags do), and not as FTL
tags. Such tags have to be rewritten to <literal>&lt;#include
"foo.ftl"&gt;</literal>, since only parts that starts with
<literal>&lt;#</literal>, <literal>&lt;/#</literal>,
<literal>&lt;@</literal>, or <literal>&lt;/@</literal> count as
FTL tags. Or, to recover the old transitional behavior, where
both legacy and new tag syntax was recognized, you have to
explicitly set <literal>strict_syntax</literal> to
<literal>false</literal>:
<literal>cfg.setStrictSyntaxMode(false)</literal>. Also, for
individual templates you can force the old behavior by starting
the template with <literal>&lt;#ftl
strict_syntax=false&gt;</literal>. (For more information about
why strict syntax is better than old syntax <link
linkend="ref_depr_oldsyntax">read this...</link>)</para>
</listitem>
<listitem>
<para>Several classes were moved from the
<literal>freemarker.template</literal> package, to the new
<literal>freemarker.core</literal> package:</para>
<itemizedlist spacing="compact">
<listitem>
<para>"Normal" classes: <literal>ArithmeticEngine</literal>,
<literal>Configurable</literal>,
<emphasis><literal>Environment</literal></emphasis></para>
</listitem>
<listitem>
<para>Exceptions:
<literal>InvalidReferenceException</literal>,
<literal>NonBooleanException</literal>,
<literal>NonNumericalException</literal>,
<literal>NonStringException</literal>,
<literal>ParseException</literal>,
<literal>StopException</literal></para>
</listitem>
<listitem>
<para>Errors: <literal>TokenMgrError</literal></para>
</listitem>
</itemizedlist>
<para>The main reason of the splitting of
<literal>freemarker.template</literal> package was that the
amount of "expert" public classes and interfaces grows too much,
as we introduce API-s for third-party tools, such as debugging
API.</para>
</listitem>
<listitem>
<para><literal>freemarker.template.TemplateMethodModel.exec</literal>
now returns <literal>Object</literal> instead of
<literal>TemplateModel</literal>.</para>
</listitem>
<listitem>
<para>White-space stripping is now more aggressive as before: it
always removes leading and trailing white-space if the line only
contains FTL tags. (Earlier the white-space was not removed if
the tag was <literal>&lt;#include
<replaceable>...</replaceable>&gt;</literal> or user-defined
directive tag with empty directive syntax as
<literal>&lt;@myMacro/&gt;</literal> (or its equivalents:
<literal>&lt;@myMacro&gt;&lt;/@myMacro&gt;</literal> and
<literal>&lt;@myMacro&gt;&lt;/@&gt;</literal>). Now white-space
is removed in these cases as well.) Also, white-space sandwiched
between two non-outputting elements, such as macro definitions,
assignments, imports, or property settings, is now ignored. More
information: <xref
linkend="dgui_misc_whitespace_stripping"/></para>
</listitem>
<listitem>
<para>The <literal>function</literal> directive is now used for
defining methods. You should replace <literal>function</literal>
with <literal>macro</literal> in your old templates. Note,
however, that old <literal>function</literal>-s will still work
if you don't use the <literal>return</literal> directive in
them, and you invoke them with the deprecated the
<literal>call</literal> directive.</para>
</listitem>
<listitem>
<para>The expressions <literal>as</literal>,
<literal>in</literal>, and <literal>using</literal> are now
keywords in the template language and cannot be used as
top-level variable names without square-bracket syntax. If, by
some chance, you have top-level variables that use one of these
names, you will have to rename them, or use the square-bracket
syntax with the <literal>.vars</literal> special variable:
<literal>.vars["in"]</literal>.</para>
</listitem>
<listitem>
<para>The <literal>?new</literal> built-in, as it was
implemented, was a security hole. Now, it only allows you to
instantiate a java object that implements the
<literal>freemarker.template.TemplateModel</literal> interface.
If you want the functionality of the <literal>?new</literal>
built-in as it existed in prior versions, make available an
instance of the
<literal>freemarker.template.utility.ObjectConstructor</literal>
class to your template. (For example:
<literal>myDataModel.put("objConstructor", new
ObjectConstructor());</literal>, and then in the template you
can do this: <literal>&lt;#assign aList =
objConstructor("java.util.ArrayList", 100)&gt;</literal>)</para>
</listitem>
<listitem>
<para>Changes to the
<literal>FreemarkerServlet</literal>:</para>
<itemizedlist>
<listitem>
<para>The <literal>FreemarkerServlet</literal> uses
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal> by default
instead of <literal>ObjectWrapper.BEANS_WRAPPER</literal>.
What this means is that, by default, objects of type
<literal>java.lang.String</literal>,
<literal>java.lang.Number</literal>,
<literal>java.util.List</literal>, and
<literal>java.util.Map</literal> will be wrapped as
<literal>TemplateModels</literal> via the classes
<literal>SimpleScalar</literal>,
<literal>SimpleNumber</literal>,
<literal>SimpleSequence</literal>, and
<literal>SimpleHash</literal> respectively. Thus, the java
methods on those objects will not be available. The default
wrapper implementation in FreeMarker 2.3 automatically knows
how to wrap Jython objects, and also wraps
<literal>org.w3c.dom.Node</literal> objects into instances
of <literal>freemarker.ext.dom.NodeModel</literal>.</para>
</listitem>
<listitem>
<para>The <literal>FreemarkerServlet</literal> base
implementation no longer deduces the locale used for
templates with <literal>HttpRequest.getLocale()</literal>.
Rather, it simply delegates to the new protected method,
<literal>deduceLocale</literal>. The default implementation
of this method simply returns the value of configuration the
<literal>locale</literal> setting.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Interpolation in string literals. For convenience,
interpolations are now supported in string literals. For
example: <literal>&lt;@message "Hello ${user}!" /&gt;</literal>
is the same as <literal>&lt;@message "Hello " + user + "!"
/&gt;</literal></para>
</listitem>
<listitem>
<para>Raw string literals: In string literals prefixed with
<literal>r</literal>, interpolations and escape sequences will
not be interpreted as special tokens. For example:
<literal>r"\n${x}"</literal> will be simply interpreted as the
character sequence <literal>'\'</literal>,
<literal>'n'</literal>, <literal>'$'</literal>,
<literal>'{'</literal>, <literal>'x'</literal>,
<literal>'}'</literal>, and not as line-feed and the value of
the <literal>x</literal> variable.</para>
</listitem>
<listitem>
<para>Method variables can be defined in FTL, with the <link
linkend="ref.directive.function"><literal>function</literal></link>
directive.</para>
</listitem>
<listitem>
<para>Support for a variable number of macro parameters. If the
last parameter in a macro declaration ends with
<literal>...</literal>, all extra parameters passed to the macro
will be available via that parameter. For macros called with
positional parameters, the parameter will be a sequence. For
named parameters, the parameter will be a hash. Note that it all
works with the new <literal>function</literal> directive as
well.</para>
</listitem>
<listitem>
<para>A new header parameter, <literal>strip_text</literal>,
that removes all top-level text from a template. This is useful
for <quote>include files</quote> to suppress newlines that
separate the macro definitions. See <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link></para>
</listitem>
<listitem>
<para>New <link linkend="ref_specvar">special variable</link>:
<literal>.vars</literal>. This is useful to read top-level
variables with square bracket syntax, for example
<literal>.vars["name-with-hyphens"]</literal> and
<literal>.vars[dynamicName]</literal>.</para>
</listitem>
<listitem>
<para><literal>macro</literal> and assignment directives now
accept arbitrary destination variable name with quoted syntax.
For example: <literal>&lt;#macro
"name-with-hyphens"&gt;<replaceable>...</replaceable></literal>
or <literal>&lt;#assign "foo bar" = 123&gt;</literal>.</para>
</listitem>
<listitem>
<para>The <literal>?keys</literal> and
<literal>?values</literal> hash built-ins now return sequences.
In practical terms this means you can access their sizes or
retrieve their sub variables by index, and use all of the <link
linkend="ref_builtins_sequence">sequence built-ins</link>. (Note
for the programmers: The <literal>TemplateHashModelEx</literal>
interface has not been changed. Your old code will work. See the
API documentation to see why.)</para>
</listitem>
<listitem>
<para>Existence built-ins (<literal>?default</literal>,
<literal>?exists</literal>, etc.) are now working with sequence
sub variables as well. Read the documentation of the
<literal>default</literal> built-in for more information.</para>
</listitem>
<listitem>
<para>White-space stripping is now more aggressive as before: it
always removes leading and trailing white-space if the line only
contains FTL tags. (Earlier the white-space was not removed if
the tag was <literal>&lt;#include
<replaceable>...</replaceable>&gt;</literal> or user-defined
directive tag with empty directive syntax as
<literal>&lt;@myMacro/&gt;</literal> (or its equivalents:
<literal>&lt;@myMacro&gt;&lt;/@myMacro&gt;</literal> and
<literal>&lt;@myMacro&gt;&lt;/@&gt;</literal>). Now white-space
is removed in these cases as well.) Also, top-level white-space
that separates macro definitions and/or assignments is now
ignored. More information: <xref
linkend="dgui_misc_whitespace_stripping"/></para>
</listitem>
<listitem>
<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>
</listitem>
<listitem>
<para>Hashes can be concatenated using the <literal>+</literal>
operator. The keys in the hash on the right-hand side take
precedence.</para>
</listitem>
<listitem>
<para>New built-ins for Java and JavaScript string escaping:
<link linkend="ref_builtin_j_string">j_string</link> and <link
linkend="ref_builtin_js_string">js_string</link></para>
</listitem>
<listitem>
<para>The <literal>replace</literal> and
<literal>split</literal> built-ins now support case-insensitive
comparsion and regular expressions (J2SE 1.4+ only), and some
other new options. More information can be found <link
linkend="ref_builtin_string_flags">here</link>.</para>
</listitem>
<listitem>
<para>New built-in for regular expression matching (J2SE 1.4+
only): <link
linkend="ref_builtin_matches"><literal>matches</literal></link></para>
</listitem>
<listitem>
<para>New built-in, <literal>eval</literal>, to evaluate a
string as FTL expression. For example
<literal>"1+2"?eval</literal> returns the number 3.</para>
</listitem>
<listitem>
<para>New built-ins for Java and JavaScript string escaping:
<link linkend="ref_builtin_j_string">j_string</link> and <link
linkend="ref_builtin_js_string">js_string</link></para>
</listitem>
<listitem>
<para>New special variables to read the value of the locale
setting: <literal>locale</literal>, <literal>lang</literal>. See
more <link linkend="ref_specvar">in the
reference...</link></para>
</listitem>
<listitem>
<para>New special variable to read the FreeMarker version
number: <literal>version</literal>. See more <link
linkend="ref_specvar">in the reference...</link></para>
</listitem>
<listitem>
<para>Tree new directives, <literal>recurse</literal>,
<literal>visit</literal> and <literal>fallback</literal>, were
introduced to support declarative node-tree processing. These
are meant to be used typically (though not exclusively) for
processing XML input. Together with this, a new variable type
has been introduced, the node type. See the <link
linkend="xgui_declarative">chapter on declarative XML
processing</link> for more details.</para>
</listitem>
<listitem>
<para>The <literal>?new</literal> built-in, as it was
implemented, was a security hole. Now, it only allows you to
instantiate a java object that implements the
<literal>freemarker.template.TemplateModel</literal> interface.
<phrase role="forProgrammers">If you want the functionality of
the <literal>?new</literal> built-in as it existed in prior
versions, make available an instance of the
<literal>freemarker.template.utility.ObjectConstructor</literal>
class to your template. (For example:
<literal>myDataModel.put("objConstructor", new
ObjectConstructor());</literal>, and then in the template you
can do this: <literal>&lt;#assign aList =
objConstructor("java.util.ArrayList",
100)&gt;</literal>)</phrase></para>
</listitem>
<listitem>
<para>Variable names can contain <literal>@</literal> anywhere
(without using quote-bracket syntax). For example:
<literal>&lt;#assign x@@@ = 123&gt;</literal> is valid.</para>
</listitem>
<listitem>
<para>The expressions <literal>as</literal>,
<literal>in</literal>, and <literal>using</literal> are now
keywords in the template language and cannot be used as
top-level variable names without square-bracket syntax (as
<literal>.vars["in"]</literal>).</para>
</listitem>
<listitem>
<para>New parameter to the <link
linkend="ref_directive_ftl"><literal>ftl</literal>
directive</link>: <literal>attributes</literal>. The value of
this attribute is a hash that associates arbitrary attributes
(name-value pairs) to the template. The values of the attributes
can be of any type (string, number, sequence... etc.).
FreeMarker doesn't try to understand the meaning of the
attributes. It's up to the application that encapsulates
FreeMarker (as a Web application framework). Thus, the set of
allowed attributes and their semantic is application (Web
application framework) dependent.</para>
</listitem>
<listitem>
<para>Other minor quality improvements...</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Smarter default object wrapping: The default object
wrapper is now
<literal>freemarker.template.DefaultObjectWrapper</literal>,
which falls back on wrapping arbitrary objects as beans using
the <literal>freemarker.ext.beans.BeansWrapper</literal>. Also,
it will wrap <literal>org.w3c.dom.Node</literal> objects with
the new DOM wrapper. Also, it is aware of Jython objects, and
will use <literal>freemarker.ext.jython.JythonWrapper</literal>
if the object passed in is a Jython object. (We count it as a
backward compatible change, since this new object wrapper wraps
differently only those objects that the old wrapper was not able
to wrap, so it has thrown exception.)</para>
</listitem>
<listitem>
<para><literal>freemarker.template.TemplateMethodModel.exec</literal>
now returns <literal>Object</literal> instead of
<literal>TemplateModel</literal>.</para>
</listitem>
<listitem>
<para>The default (initial) value of the
<literal>strict_syntax</literal> setting has been changed from
<literal>false</literal> to <literal>true</literal>. When
<literal>strict_syntax</literal> is <literal>true</literal>,
tags with old syntax as <literal>&lt;include
"foo.ftl"&gt;</literal> will be considered as static text (so
they go to the output as-is, like HTML tags do), and not as FTL
tags. Such tags have to be rewritten to <literal>&lt;#include
"foo.ftl"&gt;</literal>, since only parts that starts with
<literal>&lt;#</literal>, <literal>&lt;/#</literal>,
<literal>&lt;@</literal>, or <literal>&lt;/@</literal> count as
FTL tags. Or, to recover the old transitional behavior, where
both legacy and new tag syntax was recognized, you have to
explicitly set <literal>strict_syntax</literal> to
<literal>false</literal>:
<literal>cfg.setStrictSyntaxMode(false)</literal>. Also, for
individual templates you can force the old behavior by starting
the template with <literal>&lt;#ftl
strict_syntax=false&gt;</literal>. (For more information about
why strict syntax is better than old syntax <link
linkend="ref_depr_oldsyntax">read this...</link>)</para>
</listitem>
<listitem>
<para>New <literal>CacheStorage</literal> implementation:
<literal>freemarker.cache.MruCacheStorage</literal>. This cache
storage implements a two-level Most Recently Used cache. In the
first level, items are strongly referenced up to the specified
maximum. 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.
<literal>freemarker.cache.SoftCachseStorage</literal> and
<literal>StrongCachseStorage</literal> are deprected,
<literal>MruCachseStorage</literal> is used everywhere instead.
The default cache storage is now an
<literal>MruCachseStorage</literal> object with 0 strong size,
and infinite soft size.
<literal>Configuration.setSetting</literal> for
<literal>cache_storage</literal> now understands string values
as <literal>"strong:200, soft:2000"</literal>.</para>
</listitem>
<listitem>
<para>For <literal>BeansWrapper</literal> generated models, you
can now use the <literal>${obj.method(args)}</literal> syntax to
invoke methods whose return type is <literal>void</literal>.
<literal>void</literal> methods now return
<literal>TemplateModel.NOTHING</literal> as their return
value.</para>
</listitem>
<listitem>
<para><literal>freemarker.template.SimpleHash</literal> now can
wrap read-only <literal>Map</literal>-s, such as the map of HTTP
request parameters in Servlet API.</para>
</listitem>
<listitem>
<para>The <literal>TemplateNodeModel</literal> interface was
introduced to support recursive processing of trees of nodes.
Typically, this will be used in relation to XML.</para>
</listitem>
<listitem>
<para>New package: <literal>freemarker.ext.dom</literal>. This
contains the new XML wrapper, that supports the processing of
XML documents using the visitor pattern (i.e. with
<literal>&lt;#visit <replaceable>...</replaceable>&gt;</literal>
and similar directives), and to provide more convenient XML
traversing as the legacy wrapper. See the <link
linkend="xgui">XML processing guide</link> for more
details.</para>
</listitem>
<listitem>
<para>New package: <literal>freemarker.core</literal>. Classes
used by mostly power-users was moved here from the
<literal>freemarker.template</literal> package. The main reason
of the splitting of <literal>freemarker.template</literal>
package was that the amount of "expert" public classes and
interfaces grows too much, as we introduce API-s for third-party
tools, such as debugging API.</para>
</listitem>
<listitem>
<para>New package: <literal>freemarker.debug</literal>. This
provides a debugging API, by which you can debug executing
templates through network (RMI). You have to write the front-end
(client), as the API is just the server side. For more
information please read the JavaDoc of the
<literal>freemarker.debug</literal> package.</para>
</listitem>
<listitem>
<para>You can query the FreeMarker version number with static
method <literal>Configuration.getVersionNumber()</literal>.
Also, the <literal>Manifest.mf</literal> included in
<literal>freemarker.jar</literal> now contains the FreeMarker
version number, furthermore, executing it with <literal>java
-jar freemarker.jar</literal> will print the version number to
the stdout.</para>
</listitem>
<listitem>
<para>Added a new protected <literal>FreemarkerServlet</literal>
method: <literal>Configuration
getConfiguration()</literal>.</para>
</listitem>
<listitem>
<para>Date support is now labeled as final. (It was experimental
earlier.)</para>
</listitem>
<listitem>
<para>The <literal>BeansWrapper</literal> has been improved to
prevent some security exceptions when introspecting.</para>
</listitem>
<listitem>
<para>Other minor quality improvements and extensions...</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Fixes and improvements in the Manual and in the API
JavaDoc.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>The history of the releases before the final version</title>
<section>
<title>Differences between the final release and Release Candidate
4</title>
<itemizedlist>
<listitem>
<para>Added a new special variable to print the FreeMarker
version number: <literal>version</literal>. See more <link
linkend="ref_specvar">in the reference...</link></para>
</listitem>
<listitem>
<para>Minor documentation fixes and improvements.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Release Candidate 4 and Release
Candidate 3</title>
<itemizedlist>
<listitem>
<para>The <literal>BeansWrapper</literal> has been improved to
prevent some security exceptions when introspecting.</para>
</listitem>
<listitem>
<para>The <literal>FreemarkerXmlTask</literal> has two new
sub-tasks that can be used to prepare template execution with
Jython scripts: <literal>prepareModel</literal> and
<literal>prepareEnvironment</literal>. The
<literal>jython</literal> sub-task is now deprecated, and does
the same as <literal>prepareEnvironment</literal>. See the
Java API documentation for more details.</para>
</listitem>
<listitem>
<para>New special variable to read the FreeMarker version
number: <literal>version</literal>. See more <link
linkend="ref_specvar">in the reference...</link></para>
</listitem>
<listitem>
<para>Bugfix: Greater-than sign doesn't confuse the
<literal>eval</literal> built-in anymore.</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>BeansWrapper</literal> now wrapps
the <literal>null</literal> return values of methods
appropriately.</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>FreemarkerXmlTask</literal> doesn't
need Jython classes anymore, unless you really use Jython
scripts. Several other bugfixes in the Jython related
features.</para>
</listitem>
<listitem>
<para>Bugfix: If the template exception handler has ignored
the exception, errors occurring in interpolations inside FTL
tags (e.g. <literal>&lt;#if "foo${badVar}" !=
"foobar"&gt;</literal>) were handled in the same way as errors
occuring in interpolations outside FTL tags. Thus, the
directive call was not skipped, and the problematic
interpolation was replaced with an empty string. (This was
inconsistent with the behavior of <literal>&lt;#if
"foo"+badVar != "foobar"&gt;</literal>, which should be 100%
equivalent with the previous example.)</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>FileTemplateLoader</literal> is now
more robust when it receives paths that are malformed
according the native file system. In the earlier version such
paths sometimes caused unexpected
<literal>IOException</literal> that aborted the searching for
the template in further
<literal>FileTemplateLoader</literal>-s when you use the
<literal>MultiTemplateLoader</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Release Candidate 3 and Release
Candidate 2</title>
<itemizedlist>
<listitem>
<para>Bugfix: Fixing a fatal bug in the template cache that
was introduced with the latest cache bugfix. The template
cache has always reloaded the unchanged template when the
update delay has been elapsed, until the template has been
actually changed, in which case it has never reloaded the
template anymore.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Release Candidate 2 and Release
Candidate 1</title>
<itemizedlist>
<listitem>
<para>Bugfix: The template cache didn't reload the template
when it was replaced with an older version.</para>
</listitem>
<listitem>
<para>API JavaDoc fix: date/time related classes/interfaces
were marked as experimental. They are not experimental.</para>
</listitem>
<listitem>
<para>Minor site improvements.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Release Candidate 1 and Preview 16
releases</title>
<itemizedlist>
<listitem>
<para><emphasis>Warning! Non-backward-compatible
change!</emphasis> The default (initial) value of the
<literal>strict_syntax</literal> setting has been changed from
<literal>false</literal> to <literal>true</literal>. When
<literal>strict_syntax</literal> is <literal>true</literal>,
tags with old syntax as <literal>&lt;include
"foo.ftl"&gt;</literal> will be considered as static text (so
they go to the output as-is, like HTML tags do), and not as
FTL tags. Such tags have to be rewritten to
<literal>&lt;#include "foo.ftl"&gt;</literal>, since only
parts that starts with <literal>&lt;#</literal>,
<literal>&lt;/#</literal>, <literal>&lt;@</literal>, or
<literal>&lt;/@</literal> count as FTL tags. Or, to recover
the old transitional behavior, where both legacy and new tag
syntax was recognized, you have to explicitly set
<literal>strict_syntax</literal> to <literal>false</literal>:
<literal>cfg.setStrictSyntaxMode(false)</literal>. Also, for
individual templates you can force the old behavior by
starting the template with <literal>&lt;#ftl
strict_syntax=false&gt;</literal>. (For more information about
why strict syntax is better than old syntax <link
linkend="ref_depr_oldsyntax">read this...</link>)</para>
</listitem>
<listitem>
<para>New parameter to the <link
linkend="ref_directive_ftl"><literal>ftl</literal>
directive</link>: <literal>attributes</literal>. The value of
this attribute is a hash that associates arbitrary attributes
(name-value pairs) to the template. The values of the
attributes can be of any type (string, number, sequence...
etc.). FreeMarker doesn't try to understand the meaning of the
attributes. It's up to the application that encapsulates
FreeMarker (as a Web application framework). Thus, the set of
allowed attributes and their semantic is application (Web
application framework) dependent.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.template.utility.DeepUnwrap</literal>
unwrapped sequences to empty
<literal>ArrayList</literal>-s.</para>
</listitem>
<listitem>
<para>Bugfix: If you included/imported a template with
<literal>*/</literal> in path (acquisition), and that template
in turn itself included/imported another template with
<literal>*/</literal> in path, it may failed.</para>
</listitem>
<listitem>
<para>New methods to the
<literal>freemarker.core.Environment</literal>:
<literal>importLib(Template loadedTemplate, java.lang.String
namespace)</literal>,
<literal>getTemplateForImporting(...)</literal>,
<literal>getTemplateForInclusion(...)</literal>.</para>
</listitem>
<listitem>
<para>Improvements in the
<literal>java.io.IOException</literal> related error messages
of the <literal>include</literal> and
<literal>import</literal> directives.</para>
</listitem>
<listitem>
<para>Minor improvements in the documentation.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 16 and Preview 15
releases</title>
<itemizedlist>
<listitem>
<para>New package: <literal>freemarker.debug</literal>. This
provides a debugging API, by which you can debug executing
templates through network (RMI). You have to write the
front-end (client), as the API is just the server side. For
more information please read the JavaDoc of the
<literal>freemarker.debug</literal> package. (The debugging
API is present for a while, just I forgot to announce it in
the version history. Sorry for that.)</para>
</listitem>
<listitem>
<para>Bugfix: With the new XML wrapper,
<literal>@@markup</literal> and similar special keys:</para>
<itemizedlist>
<listitem>
<para>have returned
<literal>&lt;foo&gt;&lt;/foo&gt;</literal> for empty
elements instead of <literal>&lt;foo /&gt;</literal>.
Other than it was needlessly verbose, it has confused
browsers if you generate HTML.</para>
</listitem>
<listitem>
<para>have showed the attributes that have no explicitly
given value in the original document, just a default value
coming form the DTD.</para>
</listitem>
<listitem>
<para>have forgot to put space before the system
identifier in the <literal>&lt;!DOCTYPE
<replaceable>...</replaceable>&gt;</literal>.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bugfix: XPath with Jaxen has died with
<literal>NullPointerException</literal> if the context was an
empty node set.</para>
</listitem>
<listitem>
<para>A bit more intelligent Xalan XPath error
messages.</para>
</listitem>
<listitem>
<para>Revoked fallback-to-classloader logic from the template
cache.</para>
</listitem>
<listitem>
<para>From now on, if no XPath engine is available, and the
hash key in an XML query can't be interpreted without XPath,
an error will tell this clearly, rather than silently
returning undefined variable (null).</para>
</listitem>
<listitem>
<para>Bugfix: Some templates have caused the parser to
die.</para>
</listitem>
<listitem>
<para>Some other minor improvements here and there...</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 15 and Preview 14
releases</title>
<itemizedlist>
<listitem>
<para>Bugfix: The new default template cache storage
(<literal>MruCacheStorage</literal>) has started to
continually fail with <literal>NullPointerException</literal>
from a random point of time, usually when the memory usage was
high in the JVM.</para>
</listitem>
<listitem>
<para>Bugfix: In error messages, when the quoted FTL directive
had nested content, that was quoted as well, so the quotation
could be very long and expose nested lines needlessly.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 14 and Preview 13
releases</title>
<itemizedlist>
<listitem>
<para><literal>freemarker.template.TemplateMethodModel.exec</literal>
now returns <literal>Object</literal> instead of
<literal>TemplateModel</literal>.</para>
</listitem>
<listitem>
<para>Fixes and improvements for XPath with Jaxen (not Xalan).
Non-node-set XPath expressions are now working. FreeMarker
variables are accessible in XPath expressions with XPath
variable references (e.g.
<literal>doc["book/chapter[title=$currentTitle]"]</literal>).</para>
</listitem>
<listitem>
<para><literal>freemarker.cache.SoftCachseStorage</literal>
and <literal>StrongCachseStorage</literal> is deprected. The
more flexible <literal>MruCachseStorage</literal> is used
instead everywhere. The default cache storage is now an
<literal>MruCachseStorage</literal> object with 0 strong size,
and infinite soft size.
<literal>Configuration.setSetting</literal> for
<literal>cache_storage</literal> now understands string values
as <literal>"strong:200, soft:2000"</literal>.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.cache.MruCachseStorage</literal> has died
with <literal>ClassCastException</literal> sometimes.</para>
</listitem>
<listitem>
<para>New built-ins for Java and JavaScript string escaping:
<link linkend="ref_builtin_j_string">j_string</link> and <link
linkend="ref_builtin_js_string">js_string</link></para>
</listitem>
<listitem>
<para><literal>freemarker.template.TemplateExceptionHandler.HTML_DEBUG_HANDLER</literal>
now prints more HTML-context-proof messages.</para>
</listitem>
<listitem>
<para>You can query the FreeMarker version number with static
method <literal>Configuration.getVersionNumber()</literal>.
Also, the <literal>Manifest.mf</literal> included in
<literal>freemarker.jar</literal> now contains the FreeMarker
version number, furthermore, executing it with <literal>java
-jar freemarker.jar</literal> will print the version number to
the stdout.</para>
</listitem>
<listitem>
<para>Added a new protected
<literal>FreemarkerServlet</literal> method:
<literal>Configuration getConfiguration()</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: FreeMarker has frozen on empty conditional
blocks in certain contexts.</para>
</listitem>
<listitem>
<para>Bugfix: Methods called twice on an object using the
<literal>list</literal> directive, as
<literal>parent.getChildren()</literal> with
<literal>&lt;#list parent.children as child&gt;
...&lt;/#list&gt;</literal></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 13 and Preview 12
releases</title>
<itemizedlist>
<listitem>
<para>White-space stripping is now more aggressive as before:
it always removes leading and trailing white-space if the line
only contains FTL tags. (Earlier the white-space was not
removed if the tag was <literal>&lt;#include
<replaceable>...</replaceable>&gt;</literal> or user-defined
directive tag with empty directive syntax as
<literal>&lt;@myMacro/&gt;</literal> (or its equivalents:
<literal>&lt;@myMacro&gt;&lt;/@myMacro&gt;</literal> and
<literal>&lt;@myMacro&gt;&lt;/@&gt;</literal>). Now
white-space is removed in these cases as well.) Also,
top-level white-space that separates macro definitions and/or
assignments is now ignored. More information: <xref
linkend="dgui_misc_whitespace_stripping"/></para>
</listitem>
<listitem>
<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>
</listitem>
<listitem>
<para>A new directive for the declarative XML processing:
<link
linkend="ref.directive.fallback"><literal>fallback</literal></link></para>
</listitem>
<listitem>
<para><literal>freemarker.template.SimpleHash</literal> now
can wrap read-only <literal>Map</literal>-s, such as the map
of HTTP request parameters in Servlet API.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 12 and Preview 11
releases</title>
<para>The only change between this and the previous preview
release is that Preview 11 had a bug where DOM trees would
<emphasis>never</emphasis> be garbage-collected.</para>
</section>
<section>
<title>Differences between the Preview 11 and Preview 10
releases</title>
<itemizedlist>
<listitem>
<para>Many XML related changes. Some of them are incompatible
with the previous preview releases! For a more detailed
explanation of how XML related features now work, see: <xref
linkend="xgui"/></para>
<itemizedlist>
<listitem>
<para>Attention! Attribute queries such as
<literal>foo.@bar</literal> now return sequences
(similarly to child element queries and XPath queries),
not single nodes. Because of the rule with node sequences
of size 1, it is still good to write
<literal>${foo.@bar}</literal>, but built-ins such as
<literal>?exists</literal>, <literal>?if_exists</literal>
or <literal>?default</literal> don't work as before. For
example, instead of
<literal>foo.@bar?default('black')</literal>, you now have
to write <literal>foo.@bar[0]?default('black')</literal>.
So if you have used existence built-ins with attributes,
you have to find those occurrences in the templates and
add that <literal>[0]</literal>.</para>
</listitem>
<listitem>
<para>Attention! XML name-space handling has been totally
reworked and is absolutely incompatible with pre 10. Don't
worry about this if none of your XML input documents use
you use <literal>xmlns</literal> attributes. Worry,
though, if you have utilized the <quote>loose
mode</quote>, where only the local name of elements were
compared, because that's now gone. Sorry...</para>
</listitem>
<listitem>
<para>Attention! Special-keys <literal>@@</literal> and
<literal>@*</literal> now return a sequence of attribute
nodes instead of the hash of them.</para>
</listitem>
<listitem>
<para>Several hash keys are now working for node sequences
that store multiple nodes. For example, to get the list of
all <literal>para</literal> elements of all
<literal>chapter</literal>-s, just write
<literal>doc.book.chapter.para</literal>. Or, to get list
of title attributes of all <literal>chapter</literal>-s
write <literal>doc.book.chapter.@title</literal>.</para>
</listitem>
<listitem>
<para>New special hash keys: <literal>**</literal>,
<literal>@@start_tag</literal>,
<literal>@@end_tag</literal>,
<literal>@@attribute_markup</literal>,
<literal>@@text</literal>,
<literal>@@qname</literal>.</para>
</listitem>
<listitem>
<para><literal>?parent</literal> for attribute nodes now
returns the element node the attribute node belongs
to.</para>
</listitem>
<listitem>
<para>You can use Jaxen instead of Xalan for XPath
expressions, if you call the static
<literal>freemarker.ext.dom.NodeModel.useJaxenXPathSupport()</literal>
method once. We plan to use Jaxen automatically instead of
Xalan if it is available, just the Jaxen support is not
fully functional yet.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>New special variable: <literal>.vars</literal>. This is
useful to read top-level variables with square bracket syntax,
for example <literal>.vars["name-with-hyphens"]</literal> and
<literal>.vars[dynamicName]</literal>.</para>
</listitem>
<listitem>
<para>New built-in, <literal>eval</literal>, to evaluate a
string as FTL expression. For example
<literal>"1+2"?eval</literal> returns the number 3.</para>
</listitem>
<listitem>
<para><literal>FreemarkerServlet</literal> now uses the
configuration's <literal>locale</literal> setting, rather than
<literal>Locale.getDefault()</literal>, to set the locale of
the templates. Also, the signature of the
<literal>deduceLocale</literal> method has been
changed.</para>
</listitem>
<listitem>
<para>We have a new (beta status)
<literal>CacheStorage</literal> implementation:
<literal>freemarker.cache.MruCacheStorage</literal>. This
cache storage implements a two-level Most Recently Used cache.
In the first level, items are strongly referenced up to the
specified maximum. 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.
You can plug to try it with <literal>cfg.setCacheStorage(new
freemarker.cache.MruCacheStorage(maxStrongSize,
maxSoftSize))</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 10 and Preview 9
releases</title>
<itemizedlist>
<listitem>
<para>The special key <literal>@@xmlns</literal> was removed
in favor of a new FTL directive for the same purpose,
<literal>&lt;#xmlns...&gt;</literal>.</para>
</listitem>
<listitem>
<para>By default, the system is stricter about the use of
namespace prefixes. In general, you must use a prefix to
qualify subelements that are associated with an XML
nampespace. You can do this with the new
<literal>&lt;#xmlns...&gt;</literal> directive, but prefixes
declared in the input XML doc will actually work with no
declaration.</para>
</listitem>
<listitem>
<para>Introduced a new special key called
<literal>@@text</literal> that returns all the text nodes
contained (recursively) in an element all concatenated
together.</para>
</listitem>
<listitem>
<para>Either Jaxen or Xalan can be used to provide XPath
functionality. Prior versions only worked with Xalan.</para>
</listitem>
<listitem>
<para>The <literal>FreemarkerServlet</literal> uses
<literal>ObjectWrapper.DEFAULT_WRAPPER</literal> by default
instead of <literal>ObjectWrapper.BEANS_WRAPPER</literal>.
What this means is that, by default, objects of type
<literal>java.lang.String</literal>,
<literal>java.lang.Number</literal>,
<literal>java.util.List</literal>, and
<literal>java.util.Map</literal> will be wrapped as
<literal>TemplateModels</literal> via the classes
<literal>SimpleScalar</literal>,
<literal>SimpleNumber</literal>,
<literal>SimpleSequence</literal>, and
<literal>SimpleHash</literal> respectively. Thus, the java
methods on those objects will not be available. The default
wrapper implementation in FreeMarker 2.3 automatically knows
how to wrap Jython objects, and also wraps
<literal>org.w3c.dom.Node</literal> objects into instances of
<literal>freemarker.ext.dom.NodeModel</literal>.</para>
</listitem>
<listitem>
<para>The <literal>FreemarkerServlet</literal> base
implementation no longer deduces the locale to use from the
HttpRequest.getLocale() hook. Rather, it simply delegates to a
<literal>deduceLocale()</literal> hook that is overridable in
subclasses. The base implementation simply uses
<literal>Locale.getDefault()</literal></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 9 and Preview 8
releases</title>
<itemizedlist>
<listitem>
<para>Fixed bugs introduced with Preview 8: XPath,
<literal>@@markup</literal> and
<literal>@@nested_markup</literal> now works with the document
node.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 8 and Preview 7
releases</title>
<itemizedlist>
<listitem>
<para><literal>macro</literal> and assignment directives now
accept arbitrary destination variable name with quoted syntax.
For example: <literal>&lt;#macro
"foo-bar"&gt;<replaceable>...</replaceable></literal> or
<literal>&lt;#assign "this+that" = 123&gt;</literal>. This is
important, because XML element names can contain hyphen, and
it was not possible to define a handler macro for those
elements, till now.</para>
</listitem>
<listitem>
<para>Special key <literal>@@content</literal> was renamed to
<literal>@@nested_markup</literal>.</para>
</listitem>
<listitem>
<para>Fixed outdated XML related Manual parts (that were
outdated even in Preview 7).</para>
</listitem>
<listitem>
<para>Better parse-error messages.</para>
</listitem>
<listitem>
<para>Minor bugfixes here and there...</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 7 and Preview 6
releases</title>
<itemizedlist>
<listitem>
<para>Caching of XPath queries should lead to significant
performance improvements for XML processing, at least when
XPath is heavily used.</para>
</listitem>
<listitem>
<para>Refinements in handling of XML namespaces in the XML
processing functionality. The new
<literal>strict_namespace_handling</literal> setting
introduced in 2.3pre6 was removed. A general-purpose solution
was arrived at that should make that configuration setting
unnecessary.</para>
</listitem>
<listitem>
<para>Special key <literal>@xmlns</literal> was renamed to
@@xmlns. Reserved namespace prefix <literal>default</literal>
was renamed to <literal>@@default</literal>.</para>
</listitem>
<listitem>
<para>The <literal>ftl</literal> directive now accepts
non-string types.</para>
</listitem>
<listitem>
<para>New special keys were introduced for XML node wrappers
in the freemarker.ext.dom package. The
<literal>@@markup</literal> key returns the literal markup
that make up that element and the <literal>@@content</literal>
key returns all the element's markup excluding the opening and
closing tags.</para>
</listitem>
<listitem>
<para>Minor bugfixes here and there...</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 6 and Preview 5
releases</title>
<itemizedlist>
<listitem>
<para>Existence built-ins (<literal>?default</literal>,
<literal>?exists</literal>, etc.) now work with sequence sub
variables as well. Read the <link
linkend="ref.directive.default">documentation of the
<literal>default</literal> built-in</link> for more
information.</para>
</listitem>
<listitem>
<para>The <literal>matches</literal> built-in now returns a
sequence instead of a collection.</para>
</listitem>
<listitem>
<para>Refinements in handling of XML namespaces in the XML
processing functionality. A new setting,
<literal>strict_namespace_handling</literal> was introduced.
If this is set (it is off by default) any node-handling macro
used in with the visit/recurse machinery must be from a macro
library that declares in its ftl header that it handles the
namespace in question.</para>
</listitem>
<listitem>
<para>Minor bugfixes here and there...</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 5 and Preview 4
releases</title>
<itemizedlist>
<listitem>
<para>The <literal>replace</literal> and
<literal>split</literal> built-ins now support
case-insensitive comparison and regular expressions (J2SE 1.4+
only), and some other new options. More information can be
found <link
linkend="ref_builtin_string_flags">here</link>.</para>
</listitem>
<listitem>
<para>New butilt-in for regular expression matching (J2SE 1.4+
only): <link
linkend="ref_builtin_matches"><literal>matches</literal></link></para>
</listitem>
<listitem>
<para>Minor bugfixes here and there...</para>
</listitem>
<listitem>
<para>Manual: More browser-safe HTML-s. More updated
content.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 4 and Preview 3
releases</title>
<itemizedlist>
<listitem>
<para>Bugfix: with multi-type variables, <literal>+</literal>
operator overload for hash type had higher precedence than the
precedence of some older overloads.</para>
</listitem>
<listitem>
<para>The API documentation was missing from the distribution
<literal>tar.gz</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 3 and Preview 2
releases</title>
<itemizedlist>
<listitem>
<para>XML processing: Many various bugfixes, especially with
the declarative processing.</para>
</listitem>
<listitem>
<para>XML processing: the <literal>namespace_uri</literal>
built-in, the <literal>xmlnsuri</literal> header parameter,
and the <literal>TemplateNodeModel.getNodeNamespace</literal>
method were renamed to <literal>node_namespace</literal> and
<literal>getNodeNamespace</literal> respectively.</para>
</listitem>
<listitem>
<para>XML processing: Better documentation. Especially, note:
<xref linkend="xgui"/></para>
</listitem>
<listitem>
<para>A new header parameter, <literal>strip_text</literal>,
that removes all top-level text from a template. See <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link></para>
</listitem>
<listitem>
<para>Support for a variable number of macro parameters. If
the last parameter in a macro declaration ends with
<literal>...</literal>, all extra parameters passed to the
macro will be available via that parameter. For macros called
with positional parameters, the parameter will be a sequence.
For named parameters, the parameter will be a hash.</para>
</listitem>
<listitem>
<para>For <literal>BeansWrapper</literal> generated models,
you can now use the <literal>${obj.method(args)}</literal>
syntax to invoke methods whose return type is
<literal>void</literal>. <literal>void</literal> methods now
return <literal>TemplateModel.NOTHING</literal> as their
return value.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 2 and Preview 1
releases</title>
<itemizedlist>
<listitem>
<para>The <literal>freemarker.ext.dom.NodeModel</literal> API
changed slightly. The <literal>setDocumentBuilder()</literal>
method was changed to
<literal>setDocumentBuilderFactory()</literal> because the
older scheme was not thread-safe. The
<literal>stripComments</literal> and
<literal>stripPIs</literal> methods are renamed to The
<literal>removeComments</literal> and
<literal>removePIs</literal>, and are fixed now. A new method,
<literal>simplify</literal> has been added.</para>
</listitem>
<listitem>
<para>The expressions <literal>as</literal>,
<literal>in</literal>, and <literal>using</literal> are now
keywords in the template language and cannot be used as
top-level variable names without square-bracket syntax (as
<literal>.vars["in"]</literal>). If, by some chance, you have
top-level variables that use one of these names, you will have
to rename them (or use the square-bracket syntax). Sorry for
the inconvenience.</para>
</listitem>
<listitem>
<para>The <literal>?new</literal> built-in, as it was
implemented, was a security hole. Now, it only allows you to
instantiate a java object that implements the
<literal>freemarker.template.TemplateModel</literal>
interface. If you want the functionality of the
<literal>?new</literal> built-in as it existed in prior
versions, make available an instance of the new
<literal>freemarker.template.utility.ObjectConstructor</literal>
class to your template.</para>
</listitem>
<listitem>
<para>The <literal>&lt;#recurse&gt;</literal> directive was
broken. It did not work with a <literal>using</literal>
clause. This is now fixed.</para>
</listitem>
</itemizedlist>
</section>
</section>
</section>
<section xml:id="versions_2_2_8">
<title>2.2.8</title>
<para>Date of release: 2004-June-15</para>
<para>Bugfix and maintenance release.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Added a new special variable to print the FreeMarker
version number: <literal>version</literal>. See more <link
linkend="ref_specvar">in the reference...</link></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>The <literal>BeansWrapper</literal> has been improved to
prevent some security exceptions when introspecting.</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>FileTemplateLoader</literal> is now
more robust when it receives paths that are malformed according
the native file system. In the earlier version such paths
sometimes caused unexpected <literal>IOException</literal> that
aborted the searching for the template in further
<literal>FileTemplateLoader</literal>-s when you use the
<literal>MultiTemplateLoader</literal>.</para>
</listitem>
<listitem>
<para>Some parts of the FreeMarker code has been marked as
privileged code section, so you can grant extra privileges to
FreeMarker when you use a security manager (this is a
backporting from 2.3). See more <link
linkend="pgui_misc_secureenv">here...</link></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Minor documentation fixes and improvements.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_7">
<title>2.2.7</title>
<para>Date of release: 2004-March-17</para>
<para>Important bugfix release.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: Fixing a fatal bug in the template cache that was
introduced with the latest cache <quote>bugfix</quote>. The
template cache has always reloaded the unchanged template when
the update delay has been elapsed, until the template has been
actually changed, in which case it has never reloaded the
template anymore.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_6">
<title>2.2.6</title>
<para>Date of release: 2004-March-13</para>
<para>Maintenance and bugfix release. Some of improvements are
back-portings from FreeMarker 2.3rc1.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New <link linkend="ref_specvar">special variable</link>:
<literal>.vars</literal>. This is useful to read top-level
variables with square bracket syntax, for example
<literal>.vars["name-with-hyphens"]</literal> and
<literal>.vars[dynamicName]</literal>.</para>
</listitem>
<listitem>
<para>New built-ins for Java and JavaScript string escaping:
<link linkend="ref_builtin_j_string">j_string</link> and <link
linkend="ref_builtin_js_string">js_string</link></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: The template cache didn't reload the template when
it was replaced with an older version.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>freemarker.template.utility.DeepUnwrap</literal>
unwrapped sequences to empty
<literal>ArrayList</literal>-s.</para>
</listitem>
<listitem>
<para>Bugfix: In error messages, when the quoted FTL directive
had nested content, that was quoted as well, so the quotation
could be very long and expose nested lines needlessly.</para>
</listitem>
<listitem>
<para><literal>freemarker.template.TemplateExceptionHandler.HTML_DEBUG_HANDLER</literal>
now prints more HTML-context-proof messages.</para>
</listitem>
<listitem>
<para>You can query the FreeMarker version number with static
method <literal>Configuration.getVersionNumber()</literal>.
Also, the <literal>Manifest.mf</literal> included in
<literal>freemarker.jar</literal> now contains the FreeMarker
version number, furthermore, executing it with <literal>java
-jar freemarker.jar</literal> will print the version number to
the stdout.</para>
</listitem>
<listitem>
<para>Date support is now labeled as final. (It was experimental
earlier.) There was no change since FreeMarker 2.2.1.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Fixes and improvements in the Manual and in the API
JavaDoc. The documentation now works with the Eclipse help
plugin (accessible in the <quote>Editor/IDE plugins</quote>
section of the FreeMarker Web page).</para>
</listitem>
<listitem>
<para>Minor site improvements.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_5">
<title>2.2.5</title>
<para>Date of release: 2003-09-19</para>
<para>Maintenance and bugfix release.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Creating a <literal>Configuration</literal> instance using
the default constructor no longer fails if the current directory
is unreadable due to I/O problems, lack of security permissions,
or any other exception.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_4">
<title>2.2.4</title>
<para>Date of release: 2003-09-03</para>
<para>Maintenance and bugfix release.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Improvements to JSP taglib support. If some third party
taglib didn't work for you with FreeMarker, maybe now it
will.</para>
<itemizedlist>
<listitem>
<para>The JSP <literal>PageContext</literal> now implements
<literal>forward</literal> and <literal>include</literal>
methods.</para>
</listitem>
<listitem>
<para>Accepting <literal>EVAL_PAGE</literal> as an alias to
<literal>SKIP_BODY</literal> in return values from
<literal>doStartTag</literal>. It's a common bug in some
widespread tag libraries, and now FreeMarker is less strict
and accepts it.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Fixes for some rare problems regarding namespaces of
macros.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Minor improvements to the documentation.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_3">
<title>2.2.3</title>
<para>Date of release: 2003-07-19</para>
<para>Bugfix release.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Added the <literal>is_date</literal> built-in.</para>
</listitem>
<listitem>
<para>Bugfix: Various <literal>is_xxx</literal> built-ins were
returning <literal>false</literal> when applied to undefined
expressions. Now they correctly fail on them.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: The JSP taglib support can now read JSP 1.2
compliant TLD XML files.</para>
</listitem>
<listitem>
<para>Bugfix: The JSP taglib support now emits more helpful
exception messages when the specified TLD XML file is not found
(previously it threw a
<literal>NullPointerException</literal>).</para>
</listitem>
<listitem>
<para>Bugfix: The JSP taglib support now initializes a custom
tag after its parent and page context is set as some tags expect
them to be set when attribute setters are called.</para>
</listitem>
<listitem>
<para>Bugfix: The <literal>BeansWrapper</literal> could fail to
analyze classes under very rare circumstances due to a premature
storage optimization.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_2">
<title>2.2.2</title>
<para>Date of release: 2003-05-02</para>
<para>Bugfix release.</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: The <literal>_text</literal> key of the
<literal>freemarker.ext.xml.NodeListModel</literal> was not
returning the text of the element when used with W3C DOM
trees.</para>
</listitem>
<listitem>
<para>The classes are now built against JDK 1.2.2 classes,
ensuring the binary compatibility of FreeMarker distribution
with JDK 1.2.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2_1">
<title>2.2.1</title>
<para>Date of release: 2003-04-11</para>
<para>This version introduces important new features, such as the
native FTL date/time type, and the auto-include and auto-import
settings.</para>
<para>The date/time support is experimental, but we hope it will not
substantially change. We would like to label it as final ASAP, so we
urge everybody to send feedback on this topic to the mailing
lists.</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>New scalar type: date. For more information read: <xref
linkend="dgui_datamodel_scalar"/>, <xref
linkend="dgui_datamodel_scalar"/>, <link
linkend="dgui_template_valueinserion_universal_date">interpolation</link>,
<link linkend="ref_builtin_string_for_date">?string built-in for
dates</link></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>New <literal>TemplateModel</literal> subinterface:
<literal>TemplateDateModel</literal>. For more information read
<xref linkend="pgui_datamodel_scalar"/></para>
</listitem>
<listitem>
<para>auto-include and auto-import: With these new configuration
level settings, you can include and import commonly used
templates (usually collection of macro definitions) at the top
of all templates, without actually typing <literal>&lt;#include
<replaceable>...</replaceable>&gt;</literal> or
<literal>&lt;#import
<replaceable>...</replaceable>&gt;</literal> into the templates
again and again. For more information please read the Java API
documentation of <literal>Configuration</literal></para>
</listitem>
<listitem>
<para>New template method:
<literal>createProcessingEnvironment</literal>. This method
makes it possible for you to do some special initialization on
the <link
linkend="gloss.environment"><literal>Environment</literal></link>
before template processing, or to read the environment after
template processing. For more information please read the Java
API documentation.</para>
</listitem>
<listitem>
<para>Changes to <literal>freemarker.ext.beans</literal>
package: <literal>BeanModel</literal>,
<literal>MapModel</literal>, and
<literal>ResourceModel</literal> now implement
<literal>TemplateHashModelEx</literal>.</para>
</listitem>
<listitem>
<para>Bugfix:
<literal>Configurable.setSettings(Properties)</literal> didn't
removed redundant spaces/tabs at the end of property
values.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_2">
<title>2.2</title>
<para>Date of release: 2003-03-27</para>
<para>This release introduces some really important new features.
Unfortunately, evolution was painful again; we have a few non-backward
compatible changes (see below). Also, for those of you awaiting
desired native date/time type, sorry, it is still not here (because of
some internal chaos in the team... stand by, it's coming).</para>
<section>
<title>Non backward-compatible changes!</title>
<itemizedlist>
<listitem>
<para>Macros are now plain variables. This means that if you are
unlucky and you have both a macro and another variable with the
same name, now the variable will overwrite the macro, so your
old template will malfunction. If you have a collection of
common macros, you should use the new <link
linkend="dgui_misc_namespace">namespace feature</link> to
prevent accidental clashes with the variables used in the
templates.</para>
</listitem>
<listitem>
<para>With the introduction of the new <link
linkend="dgui_misc_namespace">namespace support</link>,
<literal>global</literal> and <literal>assign</literal>
directives are no longer synonyms. <literal>assign</literal>
creates a variable in the current <literal>namespace</literal>,
while <literal>global</literal> creates variable that is visible
from all namespaces (as if the variable would be in the
data-model). Thus, the variable created with
<literal>assign</literal> is more specific, and hides the
variable of the same name created with
<literal>global</literal>. As a result, if you use both
<literal>global</literal> and <literal>assign</literal> mixed
for the same variable in your templates, now they will
malfunction. The solution is to search-and-replace all
<literal>global</literal>s in your old templates with
<literal>assign</literal>.</para>
</listitem>
<listitem>
<para>The reserved hash <literal>root</literal> no longer exists
as a predefined variable (we no longer have reserved variables).
Use <link linkend="dgui_template_exp_var_special">special
variable expressions</link> to achieve similar effects. However,
we have no equivalent replacement for <literal>root</literal>
because of the changes in the variable scopes caused by the
introduction of namespaces. You may should use
<literal>.globals</literal> or
<literal>.namespace</literal>.</para>
</listitem>
<listitem>
<para>The <literal>BeansWrapper</literal> no longer exposes
native Java arrays, booleans, numbers, enumerations, iterators,
and resource bundles as <literal>TemplateScalarModel</literal>.
This way, number objects wrapped through
<literal>BeansWrapper</literal> are subject to FreeMarker's
number formatting machinery. Also, booleans can be formatted
using the <literal>?string</literal> built-in.</para>
</listitem>
<listitem>
<para>The signature of
<literal>Configuration.setServletContextForTemplateLoading</literal>
has been changed: the first parameter is now
<literal>Object</literal> instead of
<literal>javax.servlet.ServletContext</literal>. Thus, you have
to recompile your classes that call this method. The change was
required to prevent class-loading failure when
<literal>javax.servlet</literal> classes are not available and
you would not call this method.</para>
</listitem>
<listitem>
<para>This release introduces a <link
linkend="dgui_misc_whitespace">parse-time white-space
remover</link> that strips some of the typical superfluous
white-space around FreeMarker tags and comments. <emphasis>This
feature is on by default!</emphasis> Most probably this will not
cause problems if you generate white-space neutral output like
HTML. But if it does cause undesirable reformatting in output
you generate, you can disable it with
<literal>config.setWhitespaceStripping(false)</literal>. Also,
you can enable/disable it on a per-template basis with the new
<link linkend="ref.directive.ftl"><literal>ftl</literal></link>
directive.</para>
</listitem>
<listitem>
<para>Some new directives were introduced:
<literal>nested</literal>, <literal>import</literal>,
<literal>escape</literal>, <literal>noescape</literal>,
<literal>t</literal>, <literal>rt</literal>,
<literal>lt</literal>. This means that if you are unlucky and
the text of your template contains something like
<literal>&lt;nested&gt;</literal>, then that will be
misinterpreted as a directive. To prevent this kind of problem
in the future, we recommend everybody to switch from the old
syntax to the new syntax (<quote>strict syntax</quote>). The
strict syntax will be the the default syntax starting from some
of the later releases anyway. We plan to release a conversion
tool for converting old templates. For more information please
read: <xref linkend="ref_depr_oldsyntax"/></para>
</listitem>
<listitem>
<para>The data-model created by the
<literal>FreemarkerServlet</literal> now uses automatic scope
discovery, so writing
<literal>Application.<replaceable>attrName</replaceable></literal>,
<literal>Session.<replaceable>attrName</replaceable></literal>,
<literal>Request.<replaceable>attrName</replaceable></literal>
is no longer mandatory; it's enough to write
<literal><replaceable>attrName</replaceable></literal> (for more
information <link linkend="topic.servlet.scopeAttr">read
this</link>). This may break an old template if that rely on the
non-existence of certain top-level variables.</para>
</listitem>
<listitem>
<para><literal>FreemarkerServlet</literal> now uses the encoding
of the template file for the output, unless you specify the
encoding in the <literal>ContentType</literal> init-param, such
as <literal>text/html; charset=UTF-8</literal>.</para>
</listitem>
<listitem>
<para>The format of template paths is now more restricted than
before. The path must not use <literal>/</literal>,
<literal>./</literal> and <literal>../</literal> and
<literal>://</literal> with other meaning as they have in URL
paths (or in UN*X paths). The characters <literal>*</literal>
and <literal>?</literal> are reserved. Also, the template loader
must not want paths starting with <literal>/</literal>. For more
information please read: <xref
linkend="pgui_config_templateloading"/></para>
</listitem>
<listitem>
<para>Till now
<literal>TemplateTransformModel.getWriter</literal> has received
null as parameter map if the transform was called without
parameters. From now, it will receive an empty Map instead. Note
that the previous API documentation didn't state that it always
receives null if there are no parameters, so hopelessly only
very few classes exploit this design mistake.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes in FTL (FreeMarker Template Language)</title>
<itemizedlist>
<listitem>
<para>User-defined directives: Transform and macro call syntax
has been unified; they can be called in the same way, as
user-defined directives. This also means that macros support
named parameters and nested content (like the -- now deprecated
-- <literal>transform</literal> directive did). For example, if
you have a macro called <literal>sect</literal>, you may call it
via <literal>&lt;@sect title="Blah" style="modern"&gt;Blah
blah...&lt;/@sect&gt;</literal>. For more information read:
<xref linkend="dgui_misc_userdefdir"/></para>
</listitem>
<listitem>
<para>Macros are now plain variables. This significantly
simplifies FreeMarker semantics, while providing more
flexibility; for example you can pass macros as parameters to
other macros and transforms. As for the problem of clashing
commonly-used-macro and variable names, we provide a more
powerful solution: namespaces.</para>
</listitem>
<listitem>
<para>Namespaces: Names-spaces are invaluable if you want to
assemble collections (<quote>libraries</quote>) of macros and
transforms (and other variables), and then use them in any
template without worrying about accidental name clashes with the
application specific and temporary variables, or with the
variables of other collections you want to use in the same
template. This is extremely important if FreeMarker users want
to share their macro/transform collections. For more information
read: <xref linkend="dgui_misc_namespace"/></para>
</listitem>
<listitem>
<para>With the introduction of namespaces our variable related
terminology changed. As a result, <literal>assign</literal> is
no longer synonymous with <literal>global</literal>. The
<literal>assign</literal> directive has been undeprecated, and
should be used instead of <literal>global</literal> almost
everywhere. In the new approach <literal>assign</literal>
creates variables in the current namespace, while
<literal>global</literal> creates a variable that is visible
from all namespaces (as if the variable were in the root of the
data-model). A variable created with <literal>assign</literal>
in the current namespace hides the variable of the same name
that was created with <literal>global</literal>.</para>
</listitem>
<listitem>
<para><literal>ftl</literal> directive: With this directive you
can give information about the template for FreeMarker, like the
encoding (charset) of the template, the used FTL syntax variant,
etc. Also, this directive helps you to write templates that are
less dependent on FreeMarker configuration settings, also it
helps third-party tools to identify and correctly parse
FreeMarker templates. For more information see: <link
linkend="ref.directive.ftl"><literal>ftl</literal>
directive</link></para>
</listitem>
<listitem>
<para>White-space stripping: FreeMarker now automatically
removes some of the typical superfluous white-spaces around
FreeMarker tags and comments, like the indentation spaces
before- and line-break after <literal>&lt;#if ...&gt;</literal>
tags. For more information read: <xref
linkend="dgui_misc_whitespace_stripping"/></para>
</listitem>
<listitem>
<para>New directive to apply a common ("escaping") expression to
all interpolations in a block: <link
linkend="ref.directive.escape"><literal>escape</literal></link>.
The name comes from the common usage of this directive for
automatic HTML-escaping of interpolations.</para>
</listitem>
<listitem>
<para>The new and preferred way of number formatting with
<literal>string</literal> built-in is
<literal>foo?string(format)</literal>, instead of the less
natural <literal>foo?string[format]</literal>.</para>
</listitem>
<listitem>
<para>The <literal>string</literal> built-in works for boolean
values. For example: <literal>${spamFilter?string("enabled",
"disabled")}</literal>. For more information <link
linkend="ref_builtin_string_for_boolean">read the
reference</link>.</para>
</listitem>
<listitem>
<para>The default strings for outputting boolean value using the
<literal>string</literal> built-in can be set using the
<literal>boolean_format</literal> setting.</para>
</listitem>
<listitem>
<para>Comments can be placed inside FTL tags and interpolations.
For example: <literal>&lt;#assign &lt;#-- a comment --&gt; x =
3&gt;</literal></para>
</listitem>
<listitem>
<para>All letters and numbers are enabled in variable names,
also <literal>$</literal> is allowed (as in Java programming
language). Thus you can use accents, Arabic letters, Chinese
letters, etc.</para>
</listitem>
<listitem>
<para>String literals can be quoted with apostrophe-quote.
<literal>"foo"</literal> and <literal>'foo'</literal> are
equivalent.</para>
</listitem>
<listitem>
<para>New <link linkend="ref_builtins_string">string
built-ins</link>: <literal>index_of</literal>,
<literal>last_index_of</literal>,
<literal>starts_with</literal>, <literal>ends_with</literal>,
<literal>replace</literal>, <literal>split</literal>,
<literal>chop_linebreak</literal>,
<literal>uncap_first</literal>.</para>
</listitem>
<listitem>
<para>New <link linkend="ref_builtins_sequence">sequence
built-ins</link>: <literal>sort</literal>,
<literal>sort_by</literal>.</para>
</listitem>
<listitem>
<para>New built-ins for experts to check the type of a variable.
See: <link
linkend="ref_builtin_isType"><literal>is_<replaceable>...</replaceable></literal>
built-ins</link></para>
</listitem>
<listitem>
<para>New built-in for experts to create a variable of certain
Java <literal>TemplateModel</literal> implementation. See: <link
linkend="ref_builtin_new"><literal>new</literal>
built-in</link></para>
</listitem>
<listitem>
<para>New built-in, <link
linkend="ref_builtin_namespace"><literal>namespace</literal></link>,
to get the namespace of a macro.</para>
</listitem>
<listitem>
<para>New expression type: special variable expression. To
prevent backward compatibility problems when we introduce new
predefined variables, from now <link
linkend="dgui_template_exp_var_special">special variable
expressions</link> are used to access them.</para>
</listitem>
<listitem>
<para>New directives: <literal>t</literal>,
<literal>rt</literal> and <literal>lt</literal> directives allow
you to do explicit white-space removal in extreme FTL
applications. For more information read <link
linkend="ref.directive.t">the reference</link>.</para>
</listitem>
<listitem>
<para><literal>assign</literal>, <literal>local</literal> and
<literal>global</literal> now can capture the output generated
be the nested template fragment into the variable. This
deprecates <literal>capture_output</literal> transform. More
information: <link linkend="ref.directive.assign">assign
directive reference</link></para>
</listitem>
<listitem>
<para>Bulk assignments (as <literal>&lt;#assign x=1, y=2,
z=3&gt;</literal>) no longer need colon to separate the
assignments (as <literal>&lt;#assign x=1 y=2 z=3&gt;</literal>),
although it is still allowed to preserve backward
compatibility.</para>
</listitem>
<listitem>
<para>Path that contains <literal>//:</literal> is considered as
absolute path.</para>
</listitem>
<listitem>
<para><literal>include</literal> and
<literal>transform</literal> directives no longer need a
semicolon to separate the template or transform name from the
parameter list, although it is still allowed to preserve
backward compatibility.</para>
</listitem>
<listitem>
<para><literal>#</literal>-less tag syntax is deprecated (but
still working). That is, you should write
<literal>&lt;#<replaceable>directive
...</replaceable>&gt;</literal> instead of
<literal>&lt;<replaceable>directive
...</replaceable>&gt;</literal>, and
<literal>&lt;/#<replaceable>directive
...</replaceable>&gt;</literal> instead of
<literal>&lt;/<replaceable>directive
...</replaceable>&gt;</literal>. For more info read: <xref
linkend="ref_depr_oldsyntax"/></para>
</listitem>
<listitem>
<para><literal>foreach</literal> is depreciated (but still
working). Use <link
linkend="ref.directive.list"><literal>list</literal></link>
instead.</para>
</listitem>
<listitem>
<para>Bugfix: Undefined variables in hash and sequence
constructors (as <literal>[a, b, c]</literal>) didn't caused
errors.</para>
</listitem>
<listitem>
<para>Bugfix: String concatenation had performance problem if
there was multiple concatenations chained, as:
<literal>"a"+x+"a"+x+"a"+x+"a"+x+"a"+x</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Arbitrary JSP custom tags can be used as FreeMarker
transforms in <literal>FreemarkerServlet</literal>-driven
templates. More information: <xref
linkend="pgui_misc_servlet"/></para>
</listitem>
<listitem>
<para>Various improvements for
<literal>BeansWrapper</literal>:</para>
<itemizedlist>
<listitem>
<para>The <literal>BeansWrapper</literal> no longer exposes
arbitrary objects as
<literal>TemplateScalarModel</literal>s, only
<literal>java.lang.String</literal> and
<literal>Character</literal> objects. This way, number
objects wrapped through <literal>BeansWrapper</literal> are
subject to FreeMarker's number formatting machinery. As a
side effect, non-string and non-number objects that were
previously accepted in equality and inequality operations
(because they had a string representation) will now cause
the engine to throw exception on comparison attempt.</para>
</listitem>
<listitem>
<para><literal>java.lang.Character</literal> objects are
exposed as scalars through
<literal>BeansWrapper</literal>.</para>
</listitem>
<listitem>
<para>Experimental feature: With the
<literal>setSimpleMapWrapper</literal> method of
<literal>BeansWrapper</literal> you can configure it to wrap
<literal>java.util.Map</literal>-s as
<literal>TemplateHashModelEx</literal>-s, and do not expose
the methods of the object.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para><literal>TransformControl</literal> interface (was
experimental earlier): If the <literal>Writer</literal> returned
by <literal>TemplateTransformModel.getWriter</literal>
implements this interface, it can instruct the engine to skip or
to repeat evaluation of the nested content, and gets notified
about exceptions that are thrown during the nested content
evaluation. Note that the <literal>onStart</literal> and
<literal>afterBody</literal> methods now are allowed to throw
<literal>IOException</literal>. For more information please read
the API documentation.</para>
</listitem>
<listitem>
<para>Localized lookup can be disabled with the new
<literal>Configuration</literal> methods:
<literal>set/getLocalizedLookup</literal>,
<literal>clearTemplateCache</literal></para>
</listitem>
<listitem>
<para>The new interface
<literal>freemarker.cache.CacheStorage</literal> allows users to
plug custom template caching strategies with the
<literal>cache_storage</literal> setting. The core package now
ships with two implementations:
<literal>SoftCacheStorage</literal> and
<literal>StrongCacheStorage</literal>. For more information
read: <xref linkend="pgui_config_templateloading"/></para>
</listitem>
<listitem>
<para>You can set settings with string name and string value
with the new <literal>setSetting(String key, String
value)</literal> method of <literal>Configurable</literal>
super-classes (as <literal>Configuration</literal>). Also you
can load settings from <literal>.properties</literal> file with
the <literal>setSettings</literal> method.</para>
</listitem>
<listitem>
<para>Other new <literal>Configuration</literal> methods:
<literal>clearTemplateCache</literal>,
<literal>clearSharedVariables</literal>,
<literal>getTemplateLoader</literal>, and
<literal>clone</literal>.</para>
</listitem>
<listitem>
<para>Changes to <literal>TemplateTransformModel</literal>
interface: <literal>getWriter</literal> can throw
<literal>IOException</literal>, and can return
<literal>null</literal> if the transform does not support body
content.</para>
</listitem>
<listitem>
<para>Till now
<literal>TemplateTransformModel.getWriter</literal> has received
null as parameter map if the transform was called without
parameters. From now, it will receive an empty Map instead. Note
that the previous API documentation didn't state that it always
receives null if there are no parameters, so hopelessly only
very few classes exploit this design mistake.</para>
</listitem>
<listitem>
<para>Various improvements for
<literal>FreemarkerServlet</literal>:</para>
<itemizedlist>
<listitem>
<para>The data-model now uses automatic scope discovery, so
writing
<literal>Application.<replaceable>attrName</replaceable></literal>,
<literal>Session.<replaceable>attrName</replaceable></literal>,
<literal>Request.<replaceable>attrName</replaceable></literal>
is no longer mandatory; it's enough to write
<literal><replaceable>attrName</replaceable></literal>. For
more information <link
linkend="topic.servlet.scopeAttr">read this</link>.</para>
</listitem>
<listitem>
<para><literal>FreemarkerServlet</literal> now uses the
encoding of the template file for the output, unless you
specify the encoding in the <literal>ContentType</literal>
init-param, such as <literal>text/html;
charset=UTF-8</literal>.</para>
</listitem>
<listitem>
<para>All <literal>Configuration</literal> level settings
can by set with Servlet init-params
(<literal>template_exception_handler</literal>,
<literal>locale</literal>, <literal>number_format</literal>,
etc.).</para>
</listitem>
<listitem>
<para>The object wrapper the servlet internally uses is now
set as the default object wrapper for its
<literal>Configuration</literal> instance.</para>
</listitem>
<listitem>
<para>It no longer forces session creation for requests that
don't belong to an existing session, improving
scalability.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>JDOM independent XML-wrapping:
<literal>freemarker.ext.xml.NodeListModel</literal> is a
re-implementation of
<literal>freemarker.ext.jdom.NodeListModel</literal> that does
not rely on JDOM; you don't need JDOM .jar anymore. The new
<literal>NodeListModel</literal> automatically uses W3C DOM,
dom4j, or JDOM, depending on which library is available (that
is, depending on what object do you pass to its
constructor).</para>
</listitem>
<listitem>
<para>Bugfix: <literal>WebappTemplateLoader</literal>: Template
updating didn't worked correctly with Tomcat due the caching of
resources. Now <literal>WebappTemplateLoader</literal> tries to
access the resources directly as <literal>File</literal>, if it
is possible, thus bypasses the caching.</para>
</listitem>
<listitem>
<para>Various bug-fixes for
<literal>FreemarkerServlet</literal>:</para>
<itemizedlist>
<listitem>
<para>The servlet now loads the correct template if it was
called through
<literal>RequestDispatcher.include</literal>.</para>
</listitem>
<listitem>
<para>The caching of <literal>HttpServletRequest</literal>
objects is now compliant with the servlet
specification.</para>
</listitem>
<listitem>
<para><literal>TemplateException</literal>s was suppressed
in certain situations resulting in half-rendered pages
without error message.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Bugfix: FreeMarker didn't work if the
<literal>javax.servlet</literal> classes was not available,
because <literal>Configuration</literal> explicitly referred to
<literal>javax.servlet.ServletContext</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: classes may were not found if they was available
only in the <literal>WEB-INF</literal>, and FreeMarker tried to
load the class dynamically.</para>
</listitem>
<listitem>
<para>Bugfix: the <literal>Template</literal> constructor (and
thus <literal>Configuration.getTemplate</literal>) sometimes
threw <literal>TokenMgrError</literal> (a non-checked exception)
instead of <literal>ParseException</literal>.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>The Web application related examples has been
replaced.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>The history of the releases before the final version</title>
<section>
<title>Differences between the final and RC2 releases</title>
<itemizedlist>
<listitem>
<para>You can load settings from
<literal>.properties</literal> file with the
<literal>setSettings</literal> method of
<literal>Configuration</literal> and other
<literal>Configurable</literal> subclasses.</para>
</listitem>
<listitem>
<para>New string built-in:
<literal>uncap_first</literal></para>
</listitem>
<listitem>
<para>Bugfix: When exposing an XML document to a template and
accessing it with XPath using Jaxen a
<literal>ClassCastException</literal> has occurred.</para>
</listitem>
<listitem>
<para>Bugfix: The template cache has loaded templates with bad
<literal>Configuration</literal> instance in certain
situations if you use not the static default
<literal>Configuration</literal> instance.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the RC2 and RC1 releases</title>
<itemizedlist>
<listitem>
<para>Non backward compatible change!:
<literal>FreemarkerServlet</literal> now uses the encoding of
the template file for the output, unless you specify the
encoding in the <literal>ContentType</literal> init-param,
such as <literal>text/html; charset=UTF-8</literal>.</para>
</listitem>
<listitem>
<para>Non backward compatible change compared to RC1!: The
<literal>capture_output</literal> transform creates variable
in the current namespace (as <literal>assign</literal>
directive) with the <literal>var</literal> parameter, not a
global variable.</para>
</listitem>
<listitem>
<para>The new and preferred way of number formatting with
<literal>string</literal> built-in is
<literal>foo?string(format)</literal>, instead of the less
natural <literal>foo?string[format]</literal>.</para>
</listitem>
<listitem>
<para>The <literal>string</literal> built-in works for boolean
values. For example: <literal>${spamFilter?string("enabled",
"disabled")}</literal>. For more information <link
linkend="ref_builtin_string_for_boolean">read the
reference</link>.</para>
</listitem>
<listitem>
<para>The default strings for outputting boolean value using
the <literal>string</literal> built-in can be set using the
<literal>boolean_format</literal> setting.</para>
</listitem>
<listitem>
<para>String literals can be quoted with apostrophe-quote.
<literal>"foo"</literal> and <literal>'foo'</literal> are
equivalent.</para>
</listitem>
<listitem>
<para>The new interface
<literal>freemarker.cache.CacheStorage</literal> allows users
to plug custom template caching strategies with the
<literal>cache_storage</literal> setting. The core package now
ships with two implementations:
<literal>SoftCacheStorage</literal> and
<literal>StrongCacheStorage</literal>. For more information
read: <xref linkend="pgui_config_templateloading"/></para>
</listitem>
<listitem>
<para>You can set settings with string name and string value
with the new <literal>setSetting(String key, String
value)</literal> method of <literal>Configurable</literal>
super-classes (as <literal>Configuration</literal>).</para>
</listitem>
<listitem>
<para>Other new <literal>Configuration</literal> methods:
<literal>getTemplateLoader</literal>,
<literal>clone</literal>.</para>
</listitem>
<listitem>
<para><literal>assign</literal>, <literal>local</literal> and
<literal>global</literal> now can capture the output generated
be the nested template fragment into the variable. This
deprecates <literal>capture_output</literal> transform. More
information: <link linkend="ref.directive.assign">assign
directive reference</link></para>
</listitem>
<listitem>
<para>Other new <literal>Configuration</literal> methods:
<literal>getTemplateLoader</literal>,
<literal>clone</literal>.</para>
</listitem>
<listitem>
<para>Changes to <literal>TemplateTransformModel</literal>
interface: <literal>getWriter</literal> can throw
<literal>IOException</literal>, and can return
<literal>null</literal> if the transform does not support body
content.</para>
</listitem>
<listitem>
<para>Till now
<literal>TemplateTransformModel.getWriter</literal> has
received null as parameter map if the transform was called
without parameters. From now, it will receive an empty Map
instead. Note that the previous API documentation didn't state
that it always receives null if there are no parameters, so
hopelessly only very few classes exploit this design
mistake.</para>
</listitem>
<listitem>
<para>Changes to <literal>TemplateControl</literal> interface:
<literal>onStart</literal> and <literal>afterBody</literal>
methods are now allowed to throw
<literal>IOException</literal>.</para>
</listitem>
<listitem>
<para>Path that contains <literal>//:</literal> is considered
as absolute path.</para>
</listitem>
<listitem>
<para>New <link linkend="ref_builtins_string">string
built-ins</link>: <literal>index_of</literal>,
<literal>last_index_of</literal>,
<literal>starts_with</literal>, <literal>ends_with</literal>,
<literal>replace</literal>, <literal>split</literal>,
<literal>chop_linebreak</literal>.</para>
</listitem>
<listitem>
<para>New <link linkend="ref_builtins_sequence">sequence
built-ins</link>: <literal>sort</literal>,
<literal>sort_by</literal>.</para>
</listitem>
<listitem>
<para>All <literal>Configuration</literal> level settings can
by set with Servlet init-params
(<literal>template_exception_handler</literal>,
<literal>locale</literal>, <literal>number_format</literal>,
etc.).</para>
</listitem>
<listitem>
<para>Bugfix: classes may were not found if they was available
only in the <literal>WEB-INF</literal>, and FreeMarker tried
to load the class dynamically.</para>
</listitem>
<listitem>
<para>Bugfix: <literal>setLocalizedLookup(false)</literal> of
<literal>Configuration</literal> was overridden when you have
called <literal>setTemplateLoader</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: String concatenation had performance problem if
there was multiple concatenations chained, as:
<literal>"a"+x+"a"+x+"a"+x+"a"+x+"a"+x</literal>.</para>
</listitem>
<listitem>
<para>Bugfix: white-space stripping was not worked with tags
spanning over multiple lines.</para>
</listitem>
<listitem>
<para>Bugfix: Removing several dependencies on JDK 1.3, so
FreeMarker can be build for JDK 1.2.2.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 2 and RC1 releases</title>
<itemizedlist>
<listitem>
<para><literal>ftl</literal> is now stricter, and does not
allow custom parameters. To associate custom attributes to
templates, we may add a new directive later, if there is a
demand for it.</para>
</listitem>
<listitem>
<para><literal>escape</literal> directive does not affect
numerical interpolations
(<literal>#{<replaceable>...</replaceable>}</literal>)
anymore, as it has caused errors with string escapes as
<literal>?html</literal>.</para>
</listitem>
<listitem>
<para>The <literal>normalizeName</literal> method of
<literal>freemarker.cache.TemplateLoader</literal> has been
removed, because it has caused too many complications.
Instead, normalization happens on a single point in the
<literal>TempateCache</literal>. In consequence, FreeMarker is
now stricter about the format of template paths, as things
like <literal>/../</literal> are interpreted by the
core.</para>
</listitem>
<listitem>
<para>Experimental feature: With the
<literal>setSimpleMapWrapper</literal> method of
<literal>BeansWrapper</literal> you can configure it to wrap
<literal>java.util.Map</literal>-s as
<literal>TemplateHashModelEx</literal>-s, and do not expose
the methods of the object.</para>
</listitem>
<listitem>
<para>New <literal>Configuration</literal> methods:
<literal>set/getLocalizedLookup</literal>,
<literal>clearTemplateCache</literal>,
<literal>clearSharedVariables</literal>.</para>
</listitem>
<listitem>
<para>More cleanups in the <literal>Environment</literal>
API.</para>
</listitem>
<listitem>
<para>Better JSP standard compliance: JSP page-scope variables
are the global variables that were created in the template
(not the variables of the data-model).</para>
</listitem>
<listitem>
<para>JDOM independent XML-wrapping:
<literal>freemarker.ext.xml.NodeListModel</literal> is a
re-implementation of
<literal>freemarker.ext.jdom.NodeListModel</literal> that does
not rely on JDOM; you don't need JDOM .jar anymore. The new
<literal>NodeListModel</literal> automatically uses W3C DOM,
dom4j, or JDOM, depending on which library is available (that
is, depending on what object do you pass to its
constructor).</para>
</listitem>
<listitem>
<para>Bugfix: <literal>WebappTemplateLoader</literal>:
Template updating didn't worked correctly with Tomcat due the
caching of resources. Now
<literal>WebappTemplateLoader</literal> tries to access the
resources directly as <literal>File</literal>, if it is
possible, thus bypasses the caching.</para>
</listitem>
<listitem>
<para>Bugfix: Templates loaded with
<literal>MultiTemplateLoader</literal> subclasses was removed
from the template cache after the template update delay has
elapsed (5 seconds by default) even if the template file was
unchanged. This can cause lot of extra load for a high-traffic
server if you have many templates or if the template update
delay was set to 0 second.</para>
</listitem>
<listitem>
<para>Bugfix: Undefined variables in hash and sequence
constructors (as <literal>[a, b, c]</literal>) didn't caused
errors.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the Preview 1 and Preview 2
releases</title>
<itemizedlist>
<listitem>
<para>All 16-bit Unicode letters and numbers are allowed in
identifiers, as well as the <literal>$</literal> character (as
in Java programming language). Thus you can use accented
letters, Arabic letters, Chinese letters, etc. as identifiers
in templates</para>
</listitem>
<listitem>
<para>Macros now can create loop variables for the nested
content. For more information <link
linkend="dgui_misc_userdefdir_loopvar">read
this</link>.</para>
</listitem>
<listitem>
<para>New directives: <literal>t</literal>,
<literal>rt</literal> and <literal>lt</literal> directives
allow you to do explicit white-space removal in extreme FTL
applications. For more information read <link
linkend="ref.directive.t">the reference</link>.</para>
</listitem>
<listitem>
<para>The syntax of assignment-with-namespace has changed from
<literal>&lt;#assign foo=123 namespace=myLib&gt;</literal>) to
<literal>&lt;#assign foo=123 in myLib&gt;</literal>, since the
previous syntax was confusing because its similarity to a
bulk-assignment.</para>
</listitem>
<listitem>
<para>Bulk assignments (as <literal>&lt;#assign x=1, y=2,
z=3&gt;</literal>) no longer need colon to separate the
assignments (as <literal>&lt;#assign x=1 y=2
z=3&gt;</literal>), although it is still allowed to preserve
backward compatibility.</para>
</listitem>
<listitem>
<para>Positional parameter passing is supported for macro
calls as shorthand form of normal named parameter passing. For
more details read <link
linkend="ref_directive_userDefined_positionalParam">read the
reference</link>.</para>
</listitem>
<listitem>
<para>New built-in, <literal>namespace</literal>, to get the
namespace of the currently executing macro.</para>
</listitem>
<listitem>
<para><literal>TransformControl</literal> interface (was
experimental earlier): If the <literal>Writer</literal>
returned by
<literal>TemplateTransformModel.getWriter</literal> implements
this interface, it can instruct the engine to skip or to
repeat evaluation of the nested content, and gets notified
about exceptions that are thrown during the nested content
evaluation. For more information please read the API
documentation.</para>
</listitem>
<listitem>
<para>Jython wrapper can now wrap arbitrary Java objects, not
only <literal>PyObject</literal>-s. If an object is passed to
the wrapper that is neither a
<literal>TemplateModel</literal>, nor a
<literal>PyObject</literal>, it is first coerced into a
<literal>PyObject</literal> using Jython's own wrapping
machinery, and then wrapped into a
<literal>TemplateModel</literal> as any other
<literal>PyObject</literal>.</para>
</listitem>
<listitem>
<para>Some cleanups in the <literal>Environment</literal>
API.</para>
</listitem>
<listitem>
<para>The Web application related examples has been
replaced.</para>
</listitem>
<listitem>
<para>Bugfix: Templates loaded with
<literal>URLTemplateLoader</literal> subclasses was removed
from the template cache after the template update delay has
elapsed (5 seconds by default) even if the template file was
unchanged. This can cause lot of extra load for a high-traffic
server if you have many templates or if the template update
delay was set to 0 second.</para>
</listitem>
<listitem>
<para>Bugfix: <literal>FreeMarkerServlet</literal> has thrown
<literal>ServletException</literal> even if a debug
<literal>TemplateException</literal> handler was in use (so
you may got Error 500 page instead of debug
information).</para>
</listitem>
</itemizedlist>
</section>
</section>
</section>
<section xml:id="versions_2_1_5">
<title>2.1.5</title>
<para>Date of release: 2003-02-08</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: Fixed a bug that forced the cache to frequently
reload templates accessed through URL and multi template
loaders: Templates loaded with
<literal>URLTemplateLoader</literal> subclasses and
<literal>MultiTemplateLoader</literal> was removed from the
template cache after the template update delay has elapsed (5
seconds by default) even if the template file was unchanged.
This can cause lot of extra load for a high-traffic server if
you have many templates or if the template update delay was set
to 0 second.)</para>
</listitem>
<listitem>
<para>Bugfix: Many anomalies in the
<literal>JythonWrapper</literal> were resolved, making the
integration with Jython much smoother: Jython wrapper can now
wrap arbitrary Java objects, not only
<literal>PyObject</literal>-s. If an object is passed to the
wrapper that is neither a <literal>TemplateModel</literal>, nor
a <literal>PyObject</literal>, it is first coerced into a
<literal>PyObject</literal> using Jython's own wrapping
machinery, and then wrapped into a
<literal>TemplateModel</literal> as any other
<literal>PyObject</literal>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_1_4">
<title>2.1.4</title>
<para>Date of release: 2002-12-26</para>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: Log4J is now found when automatically discovering
the logging library to use.</para>
</listitem>
<listitem>
<para>Bugfix: An exception is no longer thrown in the static
initializer of the <literal>Configuration</literal> if the
directory specified in the <literal>"user.dir"</literal> system
property is not readable.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_1_3">
<title>2.1.3</title>
<para>Date of release: 2002-12-09</para>
<section>
<title>Changes on the FTL side</title>
<itemizedlist>
<listitem>
<para>Bugfix: <literal>cap_first</literal> built-in did what
<literal>double</literal> built-in does.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>The official extension of FreeMarker template files is
<literal>ftl</literal> from now, not <literal>fm</literal>.
(This is the name of the template language; FTL, for FreeMarker
Template Language.) Of course you can use any extensions, since
FreeMarker does not deal with the file extension. But we
recommend <literal>ftl</literal> extension as default.</para>
</listitem>
<listitem>
<para>Web application examples got tweaked again, as under JDK
1.4 a class in an explicit (named) package can no longer import
classes from the default (unnamed) package. Our webapp example
was using classes in the default package, they are now moved
into named packages.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_1_2">
<title>2.1.2</title>
<para>Date of release: 2002-11-28</para>
<section>
<title>Changes in FTL (FreeMarker Template Language)</title>
<itemizedlist>
<listitem>
<para><literal>FreeMarkerServlet</literal> now has a setting for
the <literal>Content-Type</literal> header of the response,
defaulting to <literal>text/html</literal>. Previously it set no
content type, which made it not play nicely when integrated with
software that expected it (i.e. OpenSymphony SiteMesh).</para>
</listitem>
<listitem>
<para><literal>FreeMarkerServlet</literal> now works correctly
when mapped to an URL extension instead of URL path
prefix.</para>
</listitem>
<listitem>
<para>You can emulate <literal>include</literal> directive call
within Java code by calling
<literal>Environment.include(<replaceable>templateName</replaceable>,
<replaceable>charset</replaceable>,
<replaceable>parse</replaceable>)</literal>.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Bugfix: When <literal>Template.process()</literal> was
called from another template processing, it set
<literal>currentEnvironment</literal> to null when it returned,
thus crashed the parent template processing.</para>
</listitem>
<listitem>
<para>Bugfix: the <literal>_descendant</literal> key in JDOM
support incorrectly left the document root element out of the
result when applied to a Document node.</para>
</listitem>
<listitem>
<para>Bugfix: because we incorrectly assumed certain behavior of
JDK 1.4 Beans introspector, calls to public interface methods on
non-public classes that implement the interface were causing
exceptions on JDK 1.4</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Various minor supplements to the manual.</para>
</listitem>
<listitem>
<para>Documentation HTML pages don't try to load the SourceForge
logo from the Internet anymore.</para>
</listitem>
<listitem>
<para>The default ant target is <literal>jar</literal>, not
<literal>dist</literal>.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_1_1">
<title>2.1.1</title>
<para>Date of release: 2002-11-04</para>
<section>
<title>Changes in FTL (FreeMarker Template Language)</title>
<itemizedlist>
<listitem>
<para>Multi-type variables that are both string and number or
string and date are now output using their number or date value
instead of the string value when used in the
<literal>${...}</literal> interpolation. This practically makes
the string part of a string/number or a string/date variables
useless.</para>
</listitem>
<listitem>
<para>Bugfix: operator <quote>or</quote> (<literal>||</literal>)
worked wrongly when its left operand was a composite expression
(e.g., the second <literal>||</literal> in <literal>false ||
true || false</literal>; this was evaluated to
<literal>false</literal>, but it should be
<literal>true</literal>)</para>
</listitem>
<listitem>
<para>Bugfix: Less-than sign inside comments confused the FTL
parser (e.g. <literal>&lt;#-- blah &lt; blah --&gt;</literal>);
it commented out everything after the problematic
comment.</para>
</listitem>
<listitem>
<para>Bugfix: Comparing two numerical constants (e.g. <literal>3
== 3</literal>) caused internal error in the FTL parser, and
aborted template processing with error.</para>
</listitem>
<listitem>
<para>Experimental date/time type support was removed, since it
seems that this initial implementation was misguided. FreeMarker
2.2 will certainly support data/time.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para>Bugfix: <literal>Number</literal>s wrapped with
<literal>BEANS_WRAPPER</literal> was displayed with the
<literal>toString()</literal> method of wrapped object. Now they
are rendered according to the <literal>number_format</literal>
setting, because multi-type variables that are both string and
number are now output using their number value instead of the
string value.</para>
</listitem>
<listitem>
<para>Experimental date/time type support was removed, since it
seems that this initial implementation was misguided. FreeMarker
2.2 will certainly support data/time.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_1">
<title>2.1</title>
<para>Date of release: 2002-10-17</para>
<para>Templates and the Java API are <emphasis>not</emphasis> fully
compatible with 2.0 releases. You will need to revisit existing code
and templates, or use 2.1 for new projects only. Sorry for this
inconvenience; FreeMarker has undergone some revolutionary changes
since the 1.x series. We hope things will soon be sufficiently mature
for us to offer (almost) backward-compatible releases. Note that there
is a backward-compatibility flag that can be set via
<literal>Configuration.setClassicCompatible(true)</literal> that
causes the new FreeMarker to emulate most of FreeMarker 1.x's
quirks.</para>
<section>
<title>Changes in FTL (FreeMarker Template Language)</title>
<itemizedlist>
<listitem>
<para>More strict, reveals accidental mistakes in the templates,
prevents showing incorrect information when something went
wrong:</para>
<itemizedlist>
<listitem>
<para>An attempt to access an undefined variable causes an
error and aborts template processing (by default at least;
see later). In earlier versions undefined variables were
silently treated as empty (zero-length) strings. However,
you can handle undefined variables in the template with some
new built-ins. For example,
<literal>${foo?if_exists}</literal> is equivalent with the
<literal>${foo}</literal> of earlier versions. Another way
of looking at this is that null values no longer exist from
the viewpoint of a template designer. Anything referenced
must be a defined variable.</para>
<para>Note however that the programmer can configure
FreeMarker so that it ignores certain errors (say, undefined
variables), and continues template processing by skipping
the problematic part. This <quote>loose</quote> policy
should be used only for sites that don't show critical
information.</para>
</listitem>
<listitem>
<para>New variable type: <link
linkend="gloss.boolean">boolean</link>. Conditions in
<literal>if</literal>/<literal>elseif</literal> and operands
of logical operators (<literal>&amp;&amp;</literal>,
<literal>||</literal>, <literal>!</literal>) must be
booleans. Empty strings are no longer treated as a logical
false.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Local and global variables. More info: <xref
linkend="dgui_misc_var"/></para>
<itemizedlist>
<listitem>
<para>Local variables for macros. You can create/replace
local variables in macro definition bodies with the <link
linkend="ref.directive.local"><literal>local</literal>
directive</link></para>
</listitem>
<listitem>
<para>You can create/replace global (non-local) variables
with the <link
linkend="ref.directive.global"><literal>global</literal>
directive</link></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>The <link
linkend="ref.directive.include"><literal>include</literal></link>
directive now by default treats the passed filename as being
relative to the including template's path. To specify absolute
template paths, you now have to prepend them with a
slash.</para>
</listitem>
<listitem>
<para>The <link
linkend="ref.directive.include"><literal>include</literal></link>
directive can now use the <emphasis>acquisition
algorithm</emphasis> (familiar from the Zope system) to look up
the template to include. Basically, if a template is not found
where it is looked up first, it is looked up in parent
directories. This is however not a default behavior, rather it
is triggered by a new syntactic element.</para>
</listitem>
<listitem>
<para>Strict syntax mode: Allows you to generate arbitrary SGML
(XML) without worrying about clashes with FreeMarker directives.
For more information read: <xref
linkend="ref_depr_oldsyntax"/></para>
</listitem>
<listitem>
<para>Terse comments: you can use <literal>&lt;#--
<replaceable>...</replaceable> --&gt;</literal> instead of
<literal>&lt;comment&gt;<replaceable>...</replaceable>&lt;/comment&gt;</literal></para>
</listitem>
<listitem>
<para>Directive that you can use to change the locale (and other
settings) inside the template: <link
linkend="ref.directive.setting"><literal>setting</literal></link></para>
</listitem>
<listitem>
<para>Directive to explicitly flush the output buffer: <link
linkend="ref.directive.flush"><literal>flush</literal></link></para>
</listitem>
<listitem>
<para>The top-level (root) hash is available via the variable
<literal>root</literal>, which is now a reserved name.</para>
</listitem>
<listitem>
<para>The misnamed <literal>function</literal> directive has
been renamed to <literal>macro</literal>.</para>
</listitem>
<listitem>
<para>String literals support various new <link
linkend="topic.escapeSequence">escape sequences</link>,
including UNICODE escapes
(<literal>\x<replaceable>CODE</replaceable></literal>)</para>
</listitem>
<listitem>
<para>The <link
linkend="ref.directive.compress"><literal>compress</literal></link>
directive is now more conservative in removing line
breaks.</para>
</listitem>
<listitem>
<para>Built-in to capitalize the first word: <link
linkend="ref_builtin_cap_first"><literal>cap_first</literal></link></para>
</listitem>
<listitem>
<para>Built-in to generate on-the-fly templates: <link
linkend="ref_builtin_interpret"><literal>interpret</literal></link></para>
</listitem>
<listitem>
<para><link
linkend="ref.directive.stop"><literal>stop</literal></link>
directive has an optional parameter to describe the reason of
termination</para>
</listitem>
<listitem>
<para>Better error messages.</para>
</listitem>
<listitem>
<para>New variable type: date. <emphasis>Date support is
experimental. It can change substantially in the future. Keep
this in mind if you use it.</emphasis></para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes on the Java side</title>
<itemizedlist>
<listitem>
<para><literal>ObjectWrapper</literal>: You can put
non-<literal>TemplateModel</literal> objects directly into
hashes, sequences and collections, and they will be
automatically wrapped with the appropriate
<literal>TemplateModel</literal> implementation. The API of
objects that are exposed to templates
(<literal>Simple<replaceable>XXX</replaceable></literal>) has
been changed according to this, for example in
<literal>SimpleHash</literal> the old <literal>put(String key,
TemplateModel value)</literal> is now <literal>put(String key,
Object object)</literal>. Also, you can pass any kind of object
as data-model to <literal>Template.process</literal>. The
alternative reflection based <literal>ObjectWrapper</literal>
can expose the members of any Java object automatically for the
designer. More information: <link
linkend="pgui_datamodel_objectWrapper">Object wrapping</link>,
<link linkend="pgui_misc_beanwrapper">Bean wrapper</link>, <link
linkend="pgui_misc_jythonwrapper">Jython wrapper</link>.</para>
</listitem>
<listitem>
<para>The <literal>Configuration</literal> object was introduced
as a central point to hold all your FreeMarker-related global
settings, as well as commonly used variables that you want to
have available from any template. Also it encapsulates the
template cache and can be used to load templates. For more
information read <xref linkend="pgui_config"/>.</para>
</listitem>
<listitem>
<para><literal>TemplateLoader</literal>: pluggable template
loader, separates caching from template loading</para>
</listitem>
<listitem>
<para><literal>TemplateNumberModel</literal>-s do not control
their formatting anymore. They just store the data (i.e. a
number). Number formatting is done by the FreeMarker core based
on the <literal>locale</literal> and
<literal>number_format</literal> settings. This logic applies to
the new experimental date type as well.</para>
</listitem>
<listitem>
<para><literal>TemplateBooleanModel</literal> introduced: Only
objects that implements this interface can be used as a boolean
in true/false conditions. More info: <xref
linkend="pgui_datamodel_scalar"/></para>
</listitem>
<listitem>
<para><literal>TemplateDateModel</literal> introduced: objects
that implements this interface are recognized as dates and can
be locale-sensitively formatted. <emphasis>Date support is
experimental in FreeMarker 2.1. It can change substantially in
the future. Keep this in mind if you use it.</emphasis></para>
</listitem>
<listitem>
<para>The <literal>TemplateModelRoot</literal> interface was
deprecated. As of FreeMarker 2.1, you can simply use any
instance of <literal>TemplateHashModel</literal> instead. This
actually is due to a significant architectural change. Variables
set or defined in a template are stored in a separate
<literal>Environment</literal> object that only exists while the
template is being rendered. Thus, the template doesn't modify
the root hash.</para>
</listitem>
<listitem>
<para>Changes to transformations</para>
<itemizedlist>
<listitem>
<para>Completely rewritten
<literal>TemplateTransformModel</literal> interface. More
flexible, and does not impose output holding. More
information: <xref
linkend="pgui_datamodel_directive"/></para>
</listitem>
<listitem>
<para>The <literal>transform</literal> directive now takes
an optional set of key/value pairs. <literal>&lt;transform
myTransform;
<replaceable>key1</replaceable>=<replaceable>value1</replaceable>,
<replaceable>key2</replaceable>=<replaceable>value2</replaceable>
<replaceable>...</replaceable>&gt;</literal>. More
information: <link
linkend="ref.directive.transform"><literal>transform</literal>
directive</link></para>
</listitem>
<listitem>
<para>The transforms that ship with the FreeMarker core are
now available by default to all templates - i.e.
<literal>&lt;transform html_escape&gt;</literal> will invoke
the
<literal>freemarker.template.utility.HtmlEscape</literal>
transform. More information: <xref
linkend="pgui_config_sharedvariables"/></para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>User-defined <literal>TemplateModel</literal> objects now
can access the runtime environment (read and set variables, get
the current locale, etc.) using an
<literal>Environment</literal> instance, which can be obtained
by the static
<literal>Environment.getCurrentEnvironment()</literal> method.
As a result, <literal>TemplateScalarModel.getAsString</literal>
has been changed: it has no locale parameter.</para>
</listitem>
<listitem>
<para><literal>TemplateExceptionHandler</literal>-s make it
possible to define your own rules on what to do when a runtime
error occurs (e.g. accessing a non existing variable) during
template processing. For example, you can abort template
processing (recommended for most sites), or skip the problematic
statement and continue template processing (similar to old
behavior). DebugMode has been removed, use
<literal>TemplateExceptionHandler.DEBUG_HANDLER</literal> or
<literal>HTML_DEBUG_HANDLER</literal> instead.</para>
</listitem>
<listitem>
<para>Logging: FreeMarker logs certain events (runtime errors
for example). For more information read <xref
linkend="pgui_misc_logging"/>.</para>
</listitem>
<listitem>
<para><literal>SimpleIterator</literal> was removed, but we
provide a <literal>TemplateCollectionModel</literal>
implementation: <literal>SimpleCollection</literal>.</para>
</listitem>
<listitem>
<para>Arithmetic engine is pluggable
(<literal>Configuration.setArithmeticEngine</literal>). The core
distribution comes with two engines:
<literal>ArithmeticEngine.BIGDECIMAL_ENGINE</literal> (the
default) that converts all numbers to
<literal>BigDecimal</literal> and then operates on them, and
<literal>ArithmeticEngine.CONSERVATIVE_ENGINE</literal> that
uses (more-or-less) the widening conversions of Java language,
instead of converting everything to
<literal>BigDecimal</literal>.</para>
</listitem>
<listitem>
<para>Changes to <literal>freemarker.ext.beans</literal>
package: The JavaBeans adapter layer has suffered several major
changes. First, <literal>BeansWrapper</literal> is no longer a
static utility class - you can now create instances of it, and
every instance can have its own instance caching policy and
security settings. These security settings are also new - you
can now create JavaBeans wrappers that hide methods that are
considered unsafe or inappropriate in a templating environment.
By default, you can no longer call methods like
<literal>System.exit()</literal> from the template (although you
can manually turn off these safeguards). The
<literal>StaticModel</literal> and
<literal>StaticModels</literal> classes are gone; their
functionality is now replaced with the
<literal>BeansWrapper.getStaticModels()</literal> method.</para>
</listitem>
<listitem>
<para><literal>freemarker.ext.jython</literal> package:
FreeMarker can now directly use Jython objects as data-models
using the <link linkend="pgui_misc_jythonwrapper">Jython
wrapper</link>.</para>
</listitem>
<listitem>
<para>Changes to <literal>freemarker.ext.jdom</literal> package:
The package now uses the <emphasis>Jaxen</emphasis> package
instead of its predecessor, the
<emphasis>werken.xpath</emphasis> package to evaluate XPath
expressions. Since <emphasis>Jaxen</emphasis> is a successor to
<emphasis>werken.xpath</emphasis>, this can be considered to be
an upgrade. As a consequence, namespace prefixes are now
recognized in XPath expressions and the overall XPath
conformance is better.</para>
</listitem>
<listitem>
<para>Better error reporting: If the processing of a template is
aborted by a <literal>TemplateException</literal> being thrown,
or using a <literal>&lt;#stop&gt;</literal> directive,
FreeMarker will now output an execution trace with line and
column numbers relative to the template source.</para>
</listitem>
<listitem>
<para>The output is written to a simple
<literal>Writer</literal>; no more
<literal>PrintWriter</literal>. This redesign causes FreeMarker
to no longer swallow <literal>IOException</literal>s during
template processing.</para>
</listitem>
<listitem>
<para>Various API cleanups, primarily the removing of
superfluous constructor and method overloads.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Other changes</title>
<itemizedlist>
<listitem>
<para>Documentation has been rewritten from scratch</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Differences between the RC1 and final release</title>
<itemizedlist>
<listitem>
<para>Added the support for date models and locale-sensitive
date formatting. <emphasis>Date support is experimental in
FreeMarker 2.1. It can change substantially in the future. Keep
this in mind if you use it.</emphasis></para>
</listitem>
<listitem>
<para>Added the <literal>default</literal> built-in which makes
it possible to specify default values for undefined
expressions.</para>
</listitem>
<listitem>
<para><literal>SimpleIterator</literal> has been removed,
<literal>SimpleCollection</literal> has been introduced</para>
</listitem>
<listitem>
<para>Arithmetic engine is pluggable. The core now contains two
arithmetic engines:
<literal>ArithmeticEngine.BIGDECIMAL_ENGINE</literal> and
<literal>ArithmeticEngine.CONSERVATIVE_ENGINE</literal>.</para>
</listitem>
<listitem>
<para><literal>BeansWrapper</literal> supports a new exposure
level: <literal>EXPOSE_NOTHING</literal></para>
</listitem>
<listitem>
<para><literal>Constants</literal> interface was removed.
<literal><replaceable>...</replaceable>_WRAPPER</literal>
constants have been moved from <literal>Constants</literal> to
<literal>ObjectWrapper</literal>,
<literal>EMPTY_STRING</literal> constant was moved to
<literal>TemplateScalarModel</literal>,
<literal>NOTHING</literal> constant was moved to
<literal>TemplateModel</literal>, <literal>TRUE</literal> and
<literal>FALSE</literal> constants were moved to
<literal>TemplateBooleanModel</literal>.</para>
</listitem>
<listitem>
<para><literal>JAVABEANS_WRAPPER</literal> was renamed to
<literal>BEANS_WRAPPER</literal></para>
</listitem>
<listitem>
<para><literal>Configuration.get</literal> and
<literal>put</literal>, <literal>putAll</literal> were renamed
to <literal>getSharedVariable</literal> and
<literal>setSharedVariable</literal>,
<literal>setAllSharedVariables</literal></para>
</listitem>
<listitem>
<para><literal>Configuration.getClassicCompatibility</literal>,
<literal>setClassicCompatibility</literal> were renamed to
<literal>isClassicCompatible</literal>,
<literal>setClassicCompatible</literal></para>
</listitem>
<listitem>
<para><literal>Template.process</literal> method overloads with
<literal>useReflection</literal> parameter was removed. But now
we have <literal>setObjectWrapper</literal> method in the
<literal>Configuration</literal>, so you can set the preferred
root-object wrapper there.</para>
</listitem>
<listitem>
<para>Some superfluous method overloads were removed; these
changes are backward compatible with RC1</para>
</listitem>
<listitem>
<para>Various minor JavaDoc and Manual improvements</para>
</listitem>
<listitem>
<para>Bugfix: <literal>include</literal> directive has
calculated the base path of relative paths wrongly</para>
</listitem>
<listitem>
<para>Bugfix: We have accidentally used a J2SE 1.3 class, but
FreeMarker 2.1 must able to run on J2SE 1.2</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_01">
<title>2.01</title>
<para>The main improvement is in error reporting. Now exceptions are
much more informative since they come with complete line number and
column information.</para>
<para>The only API change between 2.0 and 2.01 was the elimination of
the CacheListener/CacheEvent API. Now, if the updating of a template
file fails, the exception is thrown back to the caller to handle. If
you want logging to occur when a template file is updated
successfully, you can override the logFileUpdate() method in
FileTemplateCache.</para>
</section>
<section xml:id="versions_2_0">
<title>2.0</title>
<para>FreeMarker 2.0 final was released on 18 April 2002. The changes
with respect to the previous release, 2.0 RC3 are fairly minor.</para>
<section>
<title>Bugfixes</title>
<itemizedlist>
<listitem>
<para>There were a couple of bugs in handling null values, where
Lazarus did not do the same thing as FreeMarker Classic.
Traditionally, in FreeMarker, nulls were treated as being
equivalent to an empty string in the appropriate context. At
this point, to the best of our knowledge, there is backward
compatibility with FreeMarker Classic in this respect.</para>
</listitem>
<listitem>
<para>Literal strings can now include line breaks. This was a
backward compatibility issue with FreeMarker Classic that has
been fixed.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes to the Template language</title>
<itemizedlist>
<listitem>
<para>You can use the extra built-in of
<literal>myString?web_safe</literal> to convert a string to its
"web-safe" equivalent, where problematic characters such as
'&lt;' are converted to &amp;lt;.</para>
</listitem>
<listitem>
<para>In displaying numbers with a fractional part, the
rendering apparatus now respects the decimal separator of the
template's locale, so that, for example, in continental Europe,
you would see 1,1 and in the U.S. locale, 1.1.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes to the API</title>
<itemizedlist>
<listitem>
<para>The <literal>getAsString()</literal> method in the
<literal>TemplateScalarModel</literal> interface now takes a
<literal>java.util.Locale</literal> as a parameter. For the most
part, this is a hook for later use. In the default
implementation, <literal>SimpleScalar</literal>, this parameter
is unused. If you are implementing this interface yourself, your
implementation may ignore the parameter. However, it will be
appealing for certain implementations.</para>
</listitem>
<listitem>
<para>The constructors of <literal>FileTemplateCache</literal>
have changed. If you are using an absolute directory on the file
system as the location of your templates, you need to pass in an
instance of <literal>java.io.File</literal> to indicate the
location. If you use the constructors that take a string, this
is taken to mean relative to the classloader classpath.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Miscellany</title>
<para>The ant build script build.xml now contains a target that
builds a .war file containing the Hello, World and Guestbook
examples. It builds a fmexamples.war. For example, if you are using
Tomcat in its out-of-the-box configuration, you would place this
under &lt;TOMCAT_HOME&gt;/webapps and then you would use
http://localhost:8080/fmexamples/servlet/hello and
http://localhost:8080/fmexamples/servlet/guestbook for the Hello,
World and Guestbook examples respectively.</para>
</section>
</section>
<section xml:id="versions_2_0RC3">
<title>2.0 RC3</title>
<para>FreeMarker 2.0 RC3 was released on 11 April 2002. This release
was primarily devoted to fixing bugs that were reported in RC2.</para>
<section>
<title>Bug Fixes</title>
<itemizedlist>
<listitem>
<para>Variables defined in an &lt;include...&gt; were not
available in the enclosing page. This has been fixed.</para>
</listitem>
<listitem>
<para>The JavaCC parser was not configured to handle Unicode
input correctly. Now, Unicode support is working.</para>
</listitem>
<listitem>
<para>There was a bug when comparing a number with null. It
should have returned false, but threw an exception instead. This
has been fixed.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Changes to the Template Language</title>
<itemizedlist>
<listitem>
<para>The syntax of the include directive has changed. To
indicate an unparsed include file, you do as follows:</para>
<programlisting role="template">&lt;include "included.html" ; parsed="n" &gt;</programlisting>
<para>You can also indicate the encoding of the included file
this way:</para>
<programlisting role="template"> &lt;include "included.html" ; encoding="ISO-8859-5"&gt;</programlisting>
</listitem>
<listitem>
<para>The built-in myString?trim was added for trimming the
leading and trailing white-space from strings.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>API changes</title>
<itemizedlist>
<listitem>
<para>The TemplateEventAdapter machinery was taken out. This was
never set up in a very useful manner and we anticipate that
version 2.1 will have more complete support for logging
events.</para>
</listitem>
<listitem>
<para>The template caching mechanism was streamlined and
simplified.</para>
</listitem>
<listitem>
<para>The FileTemplateCache can now be configured to load files
relative to a class loader, using the Class.getResource() call.
This allows templates to be bundled up in .jar files or in a
.war file for easy deployment of web-based apps.</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_0RC2">
<title>2.0 RC2</title>
<para>FreeMarker 2.0 RC 2 was released on 4 April 2002. Here is a
summary of changes wrt to the first release.</para>
<section>
<title>Changes to Template Language</title>
<itemizedlist>
<listitem>
<para>Certain built-in functionality is provided via a new
operator, '?'. Thus, <literal>myList?size</literal> provides the
number of elements in a list. Similarly,
<literal>myString?length</literal> provides the length of a
string, <literal>myString?upper_case</literal> puts the string
all in capital letters, and <literal>myHash?keys</literal>
provides a sequence containing the keys in the hash. See <xref
linkend="ref_builtins"/> for list of all available
built-ins.</para>
</listitem>
<listitem>
<para>Numerical comparisons can now be made using the "natural"
operators &lt; and &gt; but there are also "web-safe"
alternatives, such as <emphasis>\lt</emphasis> and
<emphasis>\gt</emphasis>, since the use of these characters may
confuse HTML editors and parsers. Note that these changed
between rc1 and rc2, they now start with a backslash. A little
asymmetry is the fact that if you use the natural greater-than
or greater-than-or-equals operators (i.e. &gt; or &gt;=) the
expression must be in parentheses. With any other operator, the
parentheses are optional.</para>
</listitem>
<listitem>
<para>Within an iteration loop -- i.e. a
<literal>foreach</literal> or a <literal>list</literal> block --
the current count in the loop is available as the special
variable
<literal><replaceable>index</replaceable>_count</literal>. where
<replaceable>index</replaceable> is the name of the variable in
the iteration. A boolean variable called
<literal><replaceable>index</replaceable>_has_next</literal> is
also defined that indicates whether there are any more items in
the iteration after this one. Note that the index starts at
zero, so you will often be adding one to it in practice.</para>
</listitem>
<listitem>
<para>The <literal>&lt;#break&gt;</literal> directive can now be
used to break out of a <literal>&lt;#foreach...&gt;</literal> or
a <literal>&lt;list...&gt;</literal> loop. (Prior to this
version, it only worked within a switch-case block.) There is a
new directive called <literal>&lt;#stop&gt;</literal> that, when
encountered, simply halts processing of the template. This can
be useful for debugging purposes.</para>
</listitem>
<listitem>
<para>When invoking java methods that have been exposed to the
page, using the code in freemarker.ext.*, there are built-ins
that allow you to indicate the numerical type that you wish to
pass as the value. For instance, if you had two methods, one
that takes an int and another that takes a long, and you wanted
to pass in a value, you would have to specify which method.
<literal>myMethod(1?int)</literal> or
<literal>myMethod(1?long)</literal>. This is unnecessary if
there is only one method of the given name.</para>
</listitem>
<listitem>
<para>Ranges can be used to get the sublist from a list or the
substring of a string. For example:
<literal>myList[0..3]</literal> will return items 0 through 3 of
the list in question. Or, for example, you could get all the
elements of the list except for the first and last ones via:
<literal>myList[1..(myList?size-2)]</literal></para>
</listitem>
<listitem>
<para>Or we could get the first 6 characters of a string via
<literal>myString[0..5]</literal></para>
</listitem>
<listitem>
<para>Lists can be concatenated using the '+' operator.
Previously, this overloading of '+' only applied to
strings.</para>
</listitem>
<listitem>
<para>An attempt to compare a number to a string now throws an
exception, since it is indicative of a coding error. Note that
there is a backward compatibility mode that can be set (see
below) that loosens this up in order to be able to process
legacy templates.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>API Changes</title>
<itemizedlist>
<listitem>
<para>The <literal>TemplateSequenceModel</literal> interface now
has a <literal>size()</literal> method for getting the number of
elements in the sequence in question.</para>
</listitem>
<listitem>
<para>The <literal>TemplateModelIterator</literal> interface now
has a <literal>hasNext()</literal> method.</para>
</listitem>
<listitem>
<para>The default sequence and hash implementations,
<literal>freemarker.template.SimpleSequence</literal> and
<literal>freemarker.template.SimpleHash</literal> are now
unsynchronized. If you need the methods to be synchronized, you
can get a synchronized wrapper via the
<literal>synchronizedWrapper()</literal> in either class.</para>
</listitem>
<listitem>
<para>The <literal>freemarker.utility.ExtendedList</literal> and
<literal>freemarker.utility.ExtendedHash</literal> classes were
removed, since all of the extra keys that it defined are now
available using the appropriate '?' built-in operation, i.e.
<literal>myHash?keys</literal> or <literal>myList?size</literal>
or <literal>myList?last</literal>.</para>
</listitem>
<listitem>
<para>There is a method in
<literal>java.freemarker.Configuration</literal> named
<literal>setDebugMode()</literal> which allows you to decide
whether stack traces are simply output to the web client (the
best situation in development) or thrown back to the caller to
be handled more gracefully (the best situation in
production).</para>
</listitem>
<listitem>
<para>There is a flag that can be set to turn on a processing
mode that is more backward-compatible with FreeMarker Classic.
This is off by default, but you can set it via
<literal>Template.setClassicCompatibility(true)</literal>. What
this does is that it allows scalars to be treated as a
single-item list in a list directive. Also, it allows somewhat
more looseness about types. In FreeMarker 1.x, <literal>&lt;#if
x=="1"&gt;</literal> and <literal>&lt;#if x==1&gt;</literal>
were in fact equivalent. This meant that legacy templates might
tend to be slack about this. If classic compatibility is not
set, an attempt to compare the string "1" with the number 1 will
result in an exception being thrown. (Note that it is preferable
to get your templates working without the backward compatibility
flag, since it usually will require only minor changes. However,
for people with a lot of templates and no time to check over
them, this flag may be of use.)</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="versions_2_0RC1">
<title>2.0 RC1</title>
<para>The first public release of FreeMarker 2.0 was on 18 March 2002.
Here is a summary of the changes in the Lazarus release, with respect
to the last stable release of FreeMarker Classic.</para>
<para><emphasis>NOTA BENE</emphasis>:</para>
<para>Despite the changes delineated above, the Lazarus release is
almost entirely backward-compatible with FreeMarker Classic. We
believe that <emphasis>most</emphasis> existing code and templates
that work under FreeMarker Classic will continue working under
Lazarus, with at most minimal changes. In practice, the most common
cases where legacy template code is broken will be where assumptions
were made about numbers and strings being equivalent. Note that in
FreeMarker 2, 2 + 2 does not result in "22". The String "1" and the
number 1 are entirely different animals and thus, any code will be
broken if it relies on the boolean expression ("1"==1) being true.
There is a "classic compatibility mode" that can be set via:
<literal>Template.setClassCompatibility()</literal> that can be set so
that Lazarus emulates some of the quirky behavior of FreeMarker
Classic. However, any code that relied on the above "features" of
FreeMarker classic really should be reworked. You are less likely to
run into the other incompatibilities that are listed above. If you
come across any other anomalies, please do tell us about them.</para>
<section>
<title>Support for Numerical operations, both arithmetic and
boolean, as well as numerical ranges.</title>
<itemizedlist>
<listitem>
<para>Scalars can now be either strings or numbers. (In
FreeMarker Classic all scalars were strings.) The basic
operations allowed are addition, subtraction, multiplication,
division, and modulus using the <literal>+</literal>,
<literal>-</literal>, <literal>*</literal>,
<literal>/</literal>, and <literal>%</literal> operators
respectively. Arbitrary-precision arithmetic with integers and
floating point numbers are provided. Though our goal is
definitely to follow the principle of least surprise, for
backward compatibility, the <literal>+</literal> operator still
is used for string concatenation. If either the left hand side
or the right hand side of <literal>lhs + rhs</literal> is
non-numerical, we revert to interpreting this as string
concatenation. Thus, in FreeMarker 2, 2+2 evaluates to the
number 4, while any of "2"+2 or 2+"2" or "2"+"2" evaluate to the
string "22". In FreeMarker Classic, rather embarrassingly, all
of the above, including 2+2, evaluated to the string "22". An
attempt to use any other arithmetic operator besides the
<literal>+</literal> with non-numerical operands will cause an
exception to be thrown.</para>
</listitem>
<listitem>
<para>Output of a numerical expression can be made explicit via
the alternative <literal>#{....}</literal> syntax. If the
expression within the curly parentheses does not evaluate to a
numerical value, an exception is thrown. The older ${....}
syntax can evaluate to either a number or a string. In general,
if, for logical reasons, the output <emphasis>must</emphasis> be
numerical, it is preferable to use the #{...} syntax, since it
adds an extra sanity check. Note that if, by some miracle, the
character sequence "#{" occurs in your template, you will have
to use a workaround to prevent problems. (The &lt;noparse&gt;
directive is one possibility.)</para>
</listitem>
<listitem>
<para>In this release, there is a facility for specifying the
number of digits to show after the decimal point. The following
code specifies to show at least 3 digits after the decimal point
but not more than 6. This is optional. This option is only
available if you use the #{...} syntax.</para>
<programlisting role="template">#{foo + bar ; m3M6} </programlisting>
<para>(Note that the above is something of a stopgap measure.
Future releases will move toward supporting fully
internationalization and localization of number and currency
formatting.</para>
</listitem>
<listitem>
<para>Numerical expressions can be used in boolean expressions
via the comparison operators: <literal>lt</literal>,
<literal>gt</literal>, <literal>lte</literal>, and
<literal>gte</literal>. In the web space, where FreeMarker is
most used in practice, using the more natural operators such as
&lt; and &gt; would tend to confuse HTML-oriented editors. An
attempt to compare non-numerical expressions using these
operators leads to a <literal>TemplateException</literal> being
thrown. If, by some coincidence, you have variables named "lt",
"gt", "lte", or "gte", you will have to change their names,
since they are now keywords in the language.</para>
</listitem>
<listitem>
<para>Numerical ranges are supported.</para>
<programlisting role="template">&lt;#list 1990..2001 as year&gt;
blah blah in the year ${year} blah
&lt;/#list&gt; </programlisting>
<para>The left hand and right hand sides of the
<literal>..</literal> operator must be numerical, or an
exception is thrown. They also need not be literal numbers, but
can be more complex expressions that evaluate to a numerical
scalar value. Note that it is also possible to write a range
that descends in value:</para>
<programlisting role="template">&lt;#list 2001..1990 as year&gt;
blah blah in the year ${year} blah blah
&lt;/#list&gt; </programlisting>
</listitem>
</itemizedlist>
</section>
<section>
<title>API Changes</title>
<itemizedlist>
<listitem>
<para>The <literal>TemplateNumberModel</literal> interface and
the <literal>SimpleNumber</literal> implementation were added to
support exposing numerical values.</para>
</listitem>
<listitem>
<para>The <literal>TemplateListModel</literal> API in FreeMarker
Classic had some design problems -- particularly in terms of
supporting thread-safe code. It has been deprecated in favor of
the following API's: <literal>TemplateCollectionModel</literal>
and <literal>TemplateSequenceModel</literal>. The
<literal>SimpleList</literal> class was refactored to implement
the above interfaces (and paradoxically, does not implement the
TemplateListModel interface.) Code that uses the deprecated
<literal>TemplateListModel</literal> should be
refactored.</para>
</listitem>
<listitem>
<para>The Expose Package by Attila Szegedi has been made an
integral part of the FreeMarker distribution and is now under
the freemarker.ext.* hierarchy. This package provides advanced
models for representing arbitrary Java objects as template
models, for representing XML documents as template models, as
well as classes to facilitate the integration of FreeMarker with
servlets and Ant.</para>
</listitem>
<listitem>
<para>In FreeMarker Classic, there were some utility classes
such as <literal>freemarker.template.utility.Addition</literal>
etcetera that existed as workarounds for the lack of numerical
operations in FreeMarker. Those have been removed and will
probably not be missed.</para>
</listitem>
<listitem>
<para>In FreeMarker Classic, the <literal>SimpleScalar</literal>
object was mutable, it had a <literal>setValue</literal> method.
This was fairly obviously a design mistake. Any code that relied
on this must be refactored. Note that in this release, both
<literal>SimpleScalar</literal> and the newly introduced
<literal>SimpleNumber</literal> are both immutable and
final.</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Syntactical Miscellany</title>
<itemizedlist>
<listitem>
<para>The if-elseif-else syntax was introduced. FreeMarker
classic only had if-else. This construct should probably (in the
opinion of the author of this document -- Revusky) be used in
preference to switch-case since the switch-case with
fall-through is a notoriously error-prone construct for most
mortal men.</para>
</listitem>
<listitem>
<para>You can now do a multiple assignment in one
&lt;assign...&gt; directive. For example: <literal>&lt;assign x
= 1, y = price*items, message="foo"&gt;</literal></para>
</listitem>
<listitem>
<para>A scalar will no longer be interpreted as a one-item list
in a &lt;list...&gt; or &lt;#foreach...&gt; block. If you have
code that relied on this feature, there is an easy workaround,
since you can simply define a list literal with exactly one
item.</para>
<programlisting role="template"> &lt;assign y=[x]&gt;
<emphasis>and then...</emphasis>
&lt;list y as item&gt;...&lt;/list&gt; </programlisting>
</listitem>
</itemizedlist>
</section>
</section>
</appendix>
<appendix xml:id="app_install">
<title>Installing FreeMarker</title>
<indexterm>
<primary>install</primary>
</indexterm>
<para>No real installation is needed. Simply ensure that
<literal>freemarker.jar</literal> is somewhere where your Java
application's class-loader will find it. In web application this usually
means putting <literal>freemarker.jar</literal> into the
<literal>WEB-INF/lib</literal> directory of your web application. (If
you want to use FreeMarker with JSP Model-2 style (which also means that
you can use custom JSP taglibs in the templates), some extra steps
needed. For more information please see <link
linkend="pgui_misc_servlet">the chapter about servlets</link>.)</para>
<para>FreeMarker has no required dependencies. But to use certain
<emphasis>optional</emphasis> FreeMarker features, the related party
libraries have to be available for the class-loader:</para>
<itemizedlist>
<listitem>
<para>Jaxen (recommended, <link
xlink:href="http://jaxen.org/">download here</link>) or Apache Xalan
is needed for XML XPath support. Please use at least Jaxen
1.1-beta-8, not older versions! Apache Xalan classes are included in
a package-relocated form in Sun/Oracle J2SE 1.4-1.8 (maybe later
too), and FreeMarker will use those if it doesn't find Jaxen or
Xalan elsewhere. But as Oracle can change these internal packages
anytime, it's still recommended to use an external Jaxen or
Xalan.</para>
</listitem>
<listitem>
<para>Obviously, <literal>javax.servlet</literal> classes are needed
for <literal>FreemarkerServlet</literal>. Servlet version 2.2 or
later is needed.</para>
</listitem>
<listitem>
<para>For the custom JSP taglib support, you will need JSP 2.0 API
or later avilable. No JSP implementation is needed, just the API.
This is already present in pretty much every servlet container. For
more information please see <link linkend="pgui_misc_servlet">the
chapter about servlets</link>.</para>
</listitem>
<listitem>
<para>Jython 2.0 or later classes are needed for the Jython
wrapper.</para>
</listitem>
<listitem>
<para>Pre-1.0 JDOM is needed for the long deprecated
<literal>freemarker.ext.jdom</literal> package. (When it was
created, there was no JDOM 1.0 yet.)</para>
</listitem>
</itemizedlist>
</appendix>
<appendix xml:id="app_legal">
<title>Legal</title>
<section xml:id="app_license">
<title>License</title>
<indexterm>
<primary>license</primary>
</indexterm>
<programlisting role="unspecified">
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed 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.
==============================================================================
END LICENSE
Historical notes
----------------
FreeMarker 1.x was released under the LGPL license. Later, by
community consensus, we have switched over to a BSD-style license. As
of FreeMarker 2.2pre1, the original author, Benjamin Geer, has
relinquished the copyright in behalf of Visigoth Software Society.
With FreeMarker 2.3.21 the license has changed to Apache License,
Version 2.0, and the owner has changed from Visigoth Software Society
to three of the FreeMarker 2.x developers, Attila Szegedi, Daniel
Dekany, and Jonathan Revusky.
After FreeMarker 2.3.24-pre01 (2015-09-02), the owner changes to the
Apache Software Foundation.</programlisting>
</section>
<section xml:id="app_eccn">
<title>Export Control</title>
<para>The FreeMarker source code doesn't include cryptography.
Furthermore its binary (downloadable) forms don't include any
cryptography software. Hence, FreeMarker has no Export Control
Classification Number (ECCN). Where an ECCN should be filled, the
label "not subject to EAR" could be used.</para>
<para>FreeMarker itself doesn't add any exporting limitations.</para>
</section>
</appendix>
</part>
<glossary xml:id="gloss">
<glossentry xml:id="gloss.startTag">
<glossterm>Start-tag</glossterm>
<glossdef>
<para><link linkend="gloss.tag">Tag</link>, which indicates that the
following content is under the element, up to the <link
linkend="gloss.endTag">end-tag</link>. The start-tag may also
specifies <link linkend="gloss.attribute">attributes</link> for the
element. An example of a start-tag: <literal>&lt;body
bgcolor=black&gt;</literal></para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.boolean">
<glossterm>Boolean</glossterm>
<glossdef>
<para>This is a variable type. A boolean variable represents a logical
true or false (yes or no). For example, if the visitor has been logged
in or not. There are only two possible boolean values:
<literal>true</literal> and <literal>false</literal>. Typically, you
will use booleans with an <literal>&lt;#if
<replaceable>...</replaceable>&gt;</literal> directive when you want
to display text based on some condition, say, you show a certain part
of the page only for visitors who has logged in.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.character">
<glossterm>Character</glossterm>
<glossdef>
<para>A symbol that people use in writing. Examples of characters:
Latin capital letter A (<quote>A</quote>), Latin small letter A
(<quote>a</quote>), digit four (<quote>4</quote>), number sign
(<quote>#</quote>), colon (<quote>:</quote>)</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.charset">
<glossterm>Charset</glossterm>
<glossdef>
<para>A charset is a rule (algorithm) for transforming a sequence of
<link linkend="gloss.character">characters</link> (text) to a sequence
of bits (or in practice, to a sequence of bytes). Whenever a character
sequence is stored on a digital media, or sent through a digital
channel (network), a charset must be applied. Examples of charsets are
ISO-8859-1, ISO-8859-6, Shift_JIS , UTF-8.</para>
<para>The capabilities of different charsers are different, that is,
not all charsets can be used for all languages. For example ISO-8859-1
can't represent Arabic letters, but ISO-8859-6 can, however it can't
represent the accented letters that that ISO-8859-1 can. Most charsets
are highly restrictive regarding the allowed characters. UTF-8 allows
virtually all possible characters, but most text editors can't handle
it yet (2004).</para>
<para>When different software components exchange text (as the HTTP
server and the browser, or the text editor you use for saving
templates and FreeMarker who loads them), it's very important that
they agree in the charset used for the binary encoding of the text. If
they don't, then the binary data will be misinterpreted by the
receiver (loader) component, which usually results in the distortion
of the non-English letters.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.outputEncoding">
<glossterm>Output encoding</glossterm>
<glossdef>
<para>Means output <link linkend="gloss.charset">charset</link>. In
the Java world the term <quote>encoding</quote> is commonly (mis)used
as a synonym to charset.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.templateEncoding">
<glossterm>Template encoding</glossterm>
<glossdef>
<para>Means template <link linkend="gloss.charset">charset</link>. In
the Java world the term <quote>encoding</quote> is commonly (mis)used
as a synonym to charset.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.collectionVariable">
<glossterm>Collection</glossterm>
<glossdef>
<para>A variable that (in conjunction with the <literal>list</literal>
directive) can spit out a series of variables.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.dataModel">
<glossterm>Data-model</glossterm>
<glossdef>
<para>Something that holds the information the template has to show
(or use in some other ways) when the template processor assembles the
output (e.g. a Web page). In FreeMarker this is best visualized as a
tree.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.directive">
<glossterm>Directive</glossterm>
<glossdef>
<para>Instructions to FreeMarker used in <link
linkend="gloss.FTL">FTL</link> <link
linkend="gloss.template">templates</link>. They are invoked by <link
linkend="gloss.FTLTag">FTL tags</link>.</para>
<glossseealso otherterm="gloss.predefinedDirective"/>
<glossseealso otherterm="gloss.userDefinedDirective"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.element">
<glossterm>Element</glossterm>
<glossdef>
<para>Elements are the most fundamental building pieces of <link
linkend="gloss.SGML">SGML</link> documents; an SGML document is
basically a tree of elements. Example of elements used in HTML: body,
head, title, p, h1, h2.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.endTag">
<glossterm>End-tag</glossterm>
<glossdef>
<para><link linkend="gloss.tag">Tag</link>, which indicates that the
following content is not under the element. Example:
<literal>&lt;/body&gt;</literal>.</para>
<glossseealso otherterm="gloss.startTag"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.environment">
<glossterm>Environment</glossterm>
<glossdef>
<para>An <literal>Environment</literal> object stores the runtime
state of a single template <link
linkend="gloss.templateProcessingJob">template processing job</link>.
That is, for each
<literal>Template.process(<replaceable>...</replaceable>)</literal>
call, an <literal>Environment</literal> instance will be created, and
then discarded when <literal>process</literal> returns. This object
stores the set of temporary variables created by the template, the
value of settings set by the template, the reference to the data-model
root, etc. Everything that is needed to fulfill the template
processing job.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.XML">
<glossterm>Extensible Markup Language</glossterm>
<glossdef>
<para>A subset (restricted version) of <link
linkend="gloss.SGML">SGML</link>. This is less powerful than SGML, but
it easier to learn and much easier to process with programs. If you
are an HTML author: XML documents are similar to HTML documents, but
the XML standard doesn't specify the usable elements. XML is a much
more general-purpose thing than HTML. For example you can use XML to
describe Web pages (like HTML) or to describe non-visual information
like a phone book database.</para>
<glossseealso otherterm="gloss.SGML">SGML</glossseealso>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.FTL">
<glossterm>FreeMarker Template Language</glossterm>
<glossdef>
<para>Simple programming language designed to write text file
templates, especially HTML templates.</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>FTL</glossterm>
<glosssee otherterm="gloss.FTL"/>
</glossentry>
<glossentry xml:id="gloss.FTLTag">
<glossterm>FTL tag</glossterm>
<glossdef>
<para><link linkend="gloss.tag">Tag</link>-like text fragment used to
invoke FreeMarker <link linkend="gloss.directive">directives</link> in
<link linkend="gloss.FTL">FTL</link> <link
linkend="gloss.template">templates</link>. These are similar to HTML
or XML tags at the first glance. The most prominent difference is that
the tag name is started with <literal>#</literal> or
<literal>@</literal>. Another important difference is that FTL tags do
not use <link linkend="gloss.attribute">attributes</link>, but a
substantially different syntax to specify parameters. Examples of FTL
tags: <literal>&lt;#if newUser&gt;</literal>,
<literal>&lt;/#if&gt;</literal>, <literal>&lt;@menuitem
title="Projects" link="projects.html"/&gt;</literal></para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.functionDefinitionBody">
<glossterm>Function definition body</glossterm>
<glossdef>
<para>The template fragment between the <literal>&lt;#function
<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#function&gt;</literal>. This template fragment will be
executed when you call the function (for example as
<literal>myFuction(1, 2)</literal>).</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.hashVariable">
<glossterm>Hash</glossterm>
<glossdef>
<para>A variable that acts as a container that stores sub variables
that can be retrieved via a string that is a lookup name.</para>
<glossseealso otherterm="gloss.sequenceVariable"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.lineBreak">
<glossterm>Line break</glossterm>
<glossdef>
<para>Line break is a special character (or a sequence of special
characters) that causes a line breaking when you see the text as plain
text (say, when you read the text with Windows notepad). Typically you
type this character by hitting ENTER or RETURN key. The line break is
represented with different characters on different platforms (to cause
incompatibility and confusion...): <quote>line feed</quote> character
on UNIX-es, <quote>carriage return</quote> character on Macintosh,
<quote>carriage return</quote> + <quote>line feed</quote> (two
characters!) on Windows and DOS. Note that line breaks in HTML do not
have a visual effect when viewed in a browser; you must use markup
such as <literal>&lt;BR&gt;</literal> for that. This manual never
means <literal>&lt;BR&gt;</literal> when it says
<quote>line-break</quote>.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.macroDefinitionBody">
<glossterm>Macro definition body</glossterm>
<glossdef>
<para>The template fragment between the <literal>&lt;#macro
<replaceable>...</replaceable>&gt;</literal> and
<literal>&lt;/#macro&gt;</literal>. This template fragment will be
executed when you call the macro (for example as
<literal>&lt;@myMacro/&gt;</literal>).</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.markupOutputValue">
<glossterm>Markup output value</glossterm>
<glossdef>
<para>A value with FTL type <quote>markup output</quote>. This type is
related to <link linkend="dgui_misc_autoescaping">auto-escaping
mechanism</link>; 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>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.methodVariable">
<glossterm>Method</glossterm>
<glossdef>
<para>A variable that calculates something based on parameters you
give, and returns the result.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.MVC">
<glossterm>MVC pattern</glossterm>
<glossdef>
<para>MVC stands for Model View Controller. It's a design pattern
started his life in the 70's as a framework developer by Trygve
Reenskaug for Smalltalk, and was used primary for for UI-s (user
interfaces). MVC considers three roles:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Model: Model represents application (domain) specific
information in a non-visual way. For example, an array of product
objects in the memory of your computer is the part of the
model.</para>
</listitem>
<listitem>
<para>View: View displays the model and provides UI. For example,
it's the task of the view component to render the array of product
objects to a HTML page.</para>
</listitem>
<listitem>
<para>Controller: The controller handles user input, modifies the
model, and ensures that the view is updated when needed. For
example it is the task of controller to take the incoming HTTP
requests, parse the received parameters (forms), dispatch the
requests to the proper business logic object, and chose the right
template for the HTTP response.</para>
</listitem>
</itemizedlist>
<para>The most important thing for us when applying MVC for Web
applications is the separation of View from the other two roles. This
allows the separation of designers (HTML authors) from programmers.
Designers deal with the visual aspects, programmers deal with the
application logic and other technical issues; everybody works on what
he is good at. Designers and programmers are less dependent on each
other. Designers can change the appearance without programmers having
to change or recompile the program.</para>
<para>For more information I recommend reading <link
xlink:href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html">chapter
4.4</link> of Designing Enterprise Applications with the J2EE Platform
blueprint.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.parseTimeError">
<glossterm>Parse-time error</glossterm>
<glossdef>
<para>An error occurring during the template parsing phase, as opposed
to the later template execution phase (see more explanation below).
The presence of a such error prevents the execution of the whole
template, even if the execution wouldn't use the part where the error
is. This is seen as an advantage, as it helps early (before
deployment, ideally in-editor) error detection.</para>
<para>A FreeMarker template is processed in two phases. First the
<emphasis>whole</emphasis> template is analyzed syntactically, which
is called parsing. The result of the parsing is a
<literal>Template</literal> Java object, which is usually cached for
fast reuse. Later, the already parsed template can be executed for
unlimited times to produce output based on the content of a <link
linkend="gloss.dataModel">data-model</link>. Errors occurring during
the parsing are called parse-time errors.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.predefinedDirective">
<glossterm>Predefined directive</glossterm>
<glossdef>
<para>Directive what is defined by FreeMarker, thus always available.
Example of predefined directives: <literal>if</literal>,
<literal>list</literal>, <literal>include</literal></para>
<glossseealso otherterm="gloss.userDefinedDirective"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.scalarVariable">
<glossterm>Scalar</glossterm>
<glossdef>
<para>A scalar variable stores a single value. A scalar is either a
string or a number or a date/time or a <link
linkend="gloss.boolean">boolean</link>.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.sequenceVariable">
<glossterm>Sequence</glossterm>
<glossdef>
<para>A sequence is a variable that contains a sequence of sub
variables. The sequence's sub variables are accessible via numerical
index, where the index of the very first object is 0, the index of the
second objects is 1, the index of the third object is 2, etc.</para>
<glossseealso otherterm="gloss.hashVariable"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.regularExpression">
<glossterm>Regular expression</glossterm>
<glossdef>
<para>A regular expression is a string that specifies a set of strings
that matches it. For example, the regular expression
<literal>"fo*"</literal> matches <literal>"f"</literal>,
<literal>"fo"</literal>, <literal>"foo"</literal>, etc. Regular
expressions are used in several languages and other tools. In
FreeMarker, the usage of them is a <quote>power user</quote> option.
So if you have never used them before, there is no need to worry about
not being familiar with them. But if you are interested in regular
expressions, you can find several Web pages and books about them.
FreeMarker uses the variation of regular expressions described at:
<link
xlink:href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html</link></para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>SGML</glossterm>
<glosssee otherterm="gloss.SGML"/>
</glossentry>
<glossentry xml:id="gloss.SGML">
<glossterm>Standard Generalized Markup Language</glossterm>
<glossdef>
<para>This is an international standard (ISO 8879) that specifies the
rules for the creation of platform-independent markup languages. HTML
is a markup language created with SGML. <link
linkend="gloss.XML">XML</link> is a subset (restricted version) of
SGML.</para>
<glossseealso otherterm="gloss.XML">XML</glossseealso>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.string">
<glossterm>String</glossterm>
<glossdef>
<para>A sequence of <link linkend="gloss.character">characters</link>
such as <quote>m</quote>, <quote>o</quote>, <quote>u</quote>,
<quote>s</quote>, <quote>e</quote>.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.tag">
<glossterm>Tag</glossterm>
<glossdef>
<para>Text fragment indicating the usage of an element in SGML.
Examples of tags: <literal>&lt;body bgcolor=black&gt;</literal>,
<literal>&lt;/body&gt;</literal></para>
<glossseealso otherterm="gloss.startTag"/>
<glossseealso otherterm="gloss.endTag"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.template">
<glossterm>Template</glossterm>
<glossdef>
<para>A template is a text file with some special character sequences
embedded into it. A template processor (e.g. FreeMarker) will
interpret special character sequences and it outputs a more or less
different text from the original text file, where the differences are
often based on a <link linkend="gloss.dataModel">data-model</link>.
Thus, the original text acts as a template of the possible
outputs.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.templateProcessingJob">
<glossterm>Template processing job</glossterm>
<glossdef>
<para>A template processing job is the process during which FreeMarker
merges the main (top-level) template with a data-model to produce the
output. Because templates can <literal>include</literal> and
<literal>import</literal> other templates, this may involves the
processing of multiple templates, but those will all belong to the
same template processing job, which was started with the processing of
the main template. A template-processing job only exists for the short
time period until the processing of the main template is finished, and
then it vanishes with all the variables created during the process
(variables created with <literal>assign</literal>,
<literal>macro</literal>, <literal>global</literal>, etc.
directives).</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.transformVariable">
<glossterm>Transform</glossterm>
<glossdef>
<para>This term refers to user-defined directives that are implemetned
with the now obsolete <literal>TemplateTransformModel</literal> Java
interface. The feature was originally made for implementing output
filters, hence the name.</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.threadSafe">
<glossterm>Thread-safe</glossterm>
<glossdef>
<para>An object is thread-safe if it is safe to call its methods from
multiple threads, even in parallel (i.e. multiple threads execute the
methods of the object at the same time). Non-thread-safe objects may
behave unpredictably in this situation, and generate wrong results,
corrupt internal data structures, etc. Thread-safety is typically
achieved in two ways with Java: with the usage
<literal>synchronized</literal> statement (or
<literal>synchronized</literal> methods), and with the immutability of
encapsulated data (i.e. you can't modify the field after you have
created the object).</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.userDefinedDirective">
<glossterm>User-defined directive</glossterm>
<glossdef>
<para>Directive that is not defined by the FreeMarker core, but by the
user. These are typically application domain specific directives, like
pull-down menu generation directives, HTML form handling
directives.</para>
<glossseealso otherterm="gloss.predefinedDirective"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.UCS">
<glossterm>UCS</glossterm>
<glossdef>
<para>This is international standard (ISO-10646) that defines a huge
set of <link linkend="gloss.character">characters</link> and assigns a
unique number for each character (<quote>!</quote> is 33, ...,
<quote>A</quote> is 61, <quote>B</quote> is 62, ..., Arabic letter
hamza is 1569... etc.). This character set (not charset) contains
almost all characters used today (Latin alphabet, Cyrillic alphabet,
Chinese letters, etc.). The idea behind UCS is that we can specify any
character with a unique number, not mater what the platform or the
language is.</para>
<glossseealso otherterm="gloss.unicode"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.unicode">
<glossterm>Unicode</glossterm>
<glossdef>
<para>De-facto standard developed by Unicode organization. It deals
with the classification of the characters in <link
linkend="gloss.UCS">UCS</link> (which is letter, which is digit, which
is uppercase, which is lowercase, etc.), and with other problems of
processing text made from the characters of UCS (e.g.
normalization).</para>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.whiteSpace">
<glossterm>White-space</glossterm>
<glossdef>
<para>Characters that are totally transparent but have impact on the
visual appearance of the text. Examples of white-space characters:
space, tab (horizontal and vertical), line breaks (CR and LF), form
feed.</para>
<glossseealso otherterm="gloss.lineBreak"/>
</glossdef>
</glossentry>
<glossentry>
<glossterm>XML</glossterm>
<glosssee otherterm="gloss.XML"/>
</glossentry>
<glossentry xml:id="gloss.attribute">
<glossterm>Attribute</glossterm>
<glossdef>
<para>In connection with <link linkend="gloss.XML">XML</link> or HTML
(or <link linkend="gloss.SGML">SGML</link> in general), attributes are
the named values associated with elements. For example, in
<literal>&lt;body bgcolor=black
text=green&gt;<replaceable>...</replaceable>&lt;/body&gt;</literal>,
the attributes are <literal>bgcolor=black</literal> and
<literal>text=green</literal>. On the left side of
<literal>=</literal> is the name of the attribute, while on the right
side is the value of the attribute. Note that in XML, the values must
be quoted (for example: <literal>&lt;body bgcolor="black"
text='green'&gt;</literal>), while in HTML it is optional for certain
values.</para>
<glossseealso otherterm="gloss.startTag"/>
</glossdef>
</glossentry>
<glossentry xml:id="gloss.fullQualifiedName">
<glossterm>Full-qualified name</glossterm>
<glossdef>
<para>... of nodes (XML node or other FTL node variable): The
full-qualified name of a node specifies not only the node name
(<literal><replaceable>node</replaceable>?node_name</literal>), but
also the node namespace
(<literal><replaceable>node</replaceable>?node_namespace</literal>),
this way it unambiguously identify a certain kind of node. The format
of the full-qualified name is
<literal><replaceable>nodeName</replaceable></literal> or
<literal><replaceable>prefix</replaceable>:<replaceable>nodeName</replaceable></literal>.
The prefix is shorthand to identify the node namespace (the a node
namespace is usually specified with a long ugly URI). In FTL, prefixes
are associated with the node namespaces with the
<literal>ns_prefixes</literal> parameter of <link
linkend="ref.directive.ftl">the <literal>ftl</literal>
directive</link>. In XML files, prefixes are associated with the node
namespaces with the
<literal>xmlns:<replaceable>prefix</replaceable></literal> attributes.
The lack of the prefix means that the node uses the default node
namespace, if a default node namespace is defined; otherwise it means
that the node does not belong to any node namespace. The default node
namespace is defined in FTL by registering reserved prefix
<literal>D</literal> with the <literal>ns_prefixes</literal> parameter
of the <literal>ftl</literal> directive. In XML files it is defined
with attribute <literal>xmlns</literal>.</para>
<para>... of Java classes: The full-qualified name of a Java class
contains both the class name and the name of the package the class
belongs to. This way it unambiguously specifies the class, regardless
of the context. An example of full-qualifed class name:
<literal>java.util.Map</literal> (as opposed to
<literal>Map</literal>).</para>
</glossdef>
</glossentry>
</glossary>
<index xml:id="alphaidx">
<title>Alphabetical Index</title>
</index>
</book>