You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2022/12/31 23:15:28 UTC
[freemarker] 01/09: Forward ported from 2.3-gae: Don't generate Google Analytics. (For simplicity I just copied the whole manual, but it's for FM2.)
This is an automated email from the ASF dual-hosted git repository.
ddekany pushed a commit to branch 3
in repository https://gitbox.apache.org/repos/asf/freemarker.git
commit ef0c4296d77dbb9331037d6c4eacea543f85f4cb
Author: ddekany <dd...@apache.org>
AuthorDate: Sat Dec 31 21:49:36 2022 +0100
Forward ported from 2.3-gae: Don't generate Google Analytics. (For simplicity I just copied the whole manual, but it's for FM2.)
---
freemarker-manual/src/main/docgen/en_US/book.xml | 43816 ++++++++++++++++++-
.../src/main/docgen/en_US/docgen.cjson | 39 +-
2 files changed, 43805 insertions(+), 50 deletions(-)
diff --git a/freemarker-manual/src/main/docgen/en_US/book.xml b/freemarker-manual/src/main/docgen/en_US/book.xml
index e1013618..2f9d3b7d 100644
--- a/freemarker-manual/src/main/docgen/en_US/book.xml
+++ b/freemarker-manual/src/main/docgen/en_US/book.xml
@@ -19,59 +19,43805 @@
-->
<book conformance="docgen" version="5.0" xml:lang="en"
xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
>
<info>
<title>Apache FreeMarker Manual</title>
<titleabbrev>Manual</titleabbrev>
- <productname>Freemarker 3.0.0</productname>
+ <productname>Freemarker 2.3.32</productname>
</info>
<preface role="index.html" xml:id="preface">
- <title>TODO</title>
+ <title>What is Apache FreeMarker?</title>
- <para>TODO... Eventually, we might copy the FM2 Manual and rework
- it.</para>
+ <para>FreeMarker is a <emphasis>template engine</emphasis>: a generic tool
+ to generate text output (HTML web pages, e-mails, configuration files,
+ source code, etc.) based on templates and changing data. It's not an
+ application for end-users in itself, but a Java library, a component that
+ programmers can embed into their products.</para>
- <para>Anchors to satisfy Docgen:</para>
+ <para>Templates are written in the FreeMarker Template Language (FTL).
+ It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
+ programming language like PHP. You are meant to prepare the data to
+ display in a real programming language, like issue database queries and do
+ business calculations, and then the template displays that already
+ prepared data. In the template you are focusing on how to present the
+ data, and outside the template you are focusing on what data to
+ present.</para>
- <itemizedlist>
- <listitem>
- <para xml:id="app_versions">app_versions</para>
- </listitem>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="figures/overview.png"/>
+ </imageobject>
+ </mediaobject>
- <listitem>
- <para xml:id="app_license">app_license</para>
- </listitem>
+ <para>This approach is often referred to as the <link
+ linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
+ particularly popular for dynamic web pages. It helps in separating web
+ page designers (HTML authors) from developers (Java programmers usually).
+ Designers won't face complicated logic in templates, and can change the
+ appearance of a page without programmers having to change or recompile
+ code.</para>
- <listitem>
- <para xml:id="exp_cheatsheet">exp_cheatsheet</para>
- </listitem>
+ <para>While FreeMarker was originally created for generating HTML pages in
+ MVC web application frameworks, it isn't bound to servlets or HTML or
+ anything web-related. It's used in non-web application environments as
+ well.</para>
- <listitem>
- <para xml:id="ref_directive_alphaidx">ref_directive_alphaidx</para>
- </listitem>
+ <para>FreeMarker is <link
+ xlink:href="http://www.fsf.org/philosophy/free-sw.html">Free</link>,
+ released under the Apache License, Version 2.0.</para>
+ </preface>
+
+ <part xml:id="dgui">
+ <title>Template Author's Guide</title>
+
+ <chapter xml:id="dgui_quickstart">
+ <title>Getting Started</title>
+
+ <para>This chapter is a very rough introduction to FreeMarker. The
+ chapters after this will go over things in much greater detail.
+ Nonetheless, once you have read this chapter, you will be able to write
+ simple but useful FreeMarker templates.</para>
+
+ <section xml:id="dgui_quickstart_basics">
+ <title>Template + data-model = output</title>
+
+ <para>Let's assume that you need a HTML page on a website, similar to
+ this:</para>
+
+ <programlisting role="output"><html>
+<head>
+ <title>Welcome!</title>
+</head>
+<body>
+ <h1>Welcome <emphasis>John Doe</emphasis>!</h1>
+ <p>Our latest product:
+ <a href="<emphasis>products/greenmouse.html</emphasis>"><emphasis>green mouse</emphasis></a>!
+</body>
+</html></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"><html>
+<head>
+ <title>Welcome!</title>
+</head>
+<body>
+ <h1>Welcome <emphasis>${user}</emphasis>!</h1>
+ <p>Our latest product:
+ <a href="<emphasis>${latestProduct.url}</emphasis>"><emphasis>${latestProduct.name}</emphasis></a>!
+</body>
+</html></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><#--</literal> and <literal>--></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><table></literal> and
+ <literal></table></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"><html>
+<head>
+ <title>Welcome!</title>
+</head>
+<body>
+ <h1>
+ Welcome ${user}<emphasis><#if user == "Big Joe"></emphasis>, our beloved leader<emphasis></#if></emphasis>!
+ </h1>
+ <p>Our latest product:
+ <a href="${latestProduct.url}">${latestProduct.name}</a>!
+</body>
+</html></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><#if
+ <replaceable>condition</replaceable>></literal> and
+ <literal></#if></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"><#if animals.python.price == <emphasis>0</emphasis>>
+ Pythons are free today!
+</#if></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"><#if animals.python.price <emphasis>!=</emphasis> 0>
+ Pythons are not free today!
+</#if></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"><#if <emphasis>animals.python.price < animals.elephant.price</emphasis>>
+ Pythons are cheaper than elephants today.
+</#if></programlisting>
+
+ <para>With the <literal><#else></literal> tag you can
+ specify what to do if the condition is false. For example:</para>
+
+ <programlisting role="template"><#if animals.python.price < animals.elephant.price>
+ Pythons are cheaper than elephants today.
+<emphasis><#else></emphasis>
+ Pythons are not cheaper than elephants today.
+</#if></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"><#if animals.python.price < animals.elephant.price>
+ Pythons are cheaper than elephants today.
+<emphasis><#elseif animals.elephant.price < animals.python.price></emphasis>
+ Elephants are cheaper than pythons today.
+<#else>
+ Elephants and pythons cost the same today.
+</#if></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"><#if animals.python.protected>
+ Pythons are protected animals!
+</#if></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"><p>We have these animals:
+<table border=1>
+ <emphasis><#list animals as animal></emphasis>
+ <tr><td>${<emphasis>animal</emphasis>.name}<td>${<emphasis>animal</emphasis>.price} Euros
+ <emphasis></#list></emphasis>
+</table></programlisting>
+
+ <para>then the output will be:</para>
+
+ <programlisting role="output"><p>We have these animals:
+<table border=1>
+ <emphasis><tr><td>mouse<td>50 Euros
+ <tr><td>elephant<td>5000 Euros
+ <tr><td>python<td>4999 Euros</emphasis>
+</table></programlisting>
+
+ <para>The generic form of the <literal>list</literal> directive
+ is:<literal> <#list <replaceable>sequence</replaceable> as
+ <replaceable>loopVariable</replaceable>><replaceable>repeatThis</replaceable></#list></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><#list
+ <replaceable>...</replaceable>></literal> and
+ <literal></#list></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"><ul>
+<emphasis><#list misc.fruits as fruit></emphasis>
+ <li>${fruit}
+<emphasis></#list></emphasis>
+</ul></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><ul></ul></literal> instead of just nothing.
+ To avoid that, you can use this form of
+ <literal>list</literal>:</para>
+
+ <programlisting role="template"><#list misc.fruits>
+ <ul>
+ <emphasis> <#items as fruit></emphasis>
+ <li>${fruit}
+ <emphasis> </#items></emphasis>
+ </ul>
+</#list></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"><p>Fruits: <#list misc.fruits as fruit>${fruit}<emphasis><#sep>, </emphasis></#list></programlisting>
+
+ <programlisting role="output"><p>Fruits: orange, banana</programlisting>
+
+ <para>The section covered by <literal>sep</literal> (which we
+ could be written like this too:
+ <literal><replaceable>...</replaceable><#sep>,
+ </#sep></#list></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"><p>Fruits: <#list misc.fruits as fruit>${fruit}<#sep>, <emphasis><#else>None</emphasis></#list></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"><p>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"><#list misc.fruits>
+ <p>Fruits:
+ <ul>
+ <#items as fruit>
+ <li>${fruit}<#sep> and</#sep>
+ </#items>
+ </ul>
+<#else>
+ <p>We have no fruits.
+</#list></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"><hr>
+<i>
+Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
+<br>
+All Rights Reserved.
+</i></programlisting>
+
+ <para>Whenever you need that file you simply insert it with the
+ <literal>include</literal> directive:</para>
+
+ <programlisting role="template"><html>
+<head>
+ <title>Test page</title>
+</head>
+<body>
+ <h1>Test page</h1>
+ <p>Blah blah...
+<emphasis> <#include "/copyright_footer.html"></emphasis>
+</body>
+</html></programlisting>
+
+ <para>and the output will be:</para>
+
+ <programlisting role="output"><html>
+<head>
+ <title>Test page</title>
+</head>
+<body>
+ <h1>Test page</h1>
+ <p>Blah blah...
+<emphasis><hr>
+<i>
+Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
+<br>
+All Rights Reserved.
+</i></emphasis>
+</body>
+</html></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><#list animals as animal></emphasis>
+ <div<emphasis><#if animal.protected></emphasis><emphasis> </emphasis>class="protected"<emphasis></#if></emphasis>>
+ ${animal.name} for ${animal.price} Euros
+ </div>
+<emphasis></#list></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><#list animals as
+ animal></literal> and the corresponding
+ <literal></#list></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><td
+ class="${animal?item_parity}Row"></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 -> it.protected)</literal>
+ gives the list of protected animals. To list protected animals
+ only, you could use <literal><#list animals?filter(it ->
+ it.protected) as
+ animal><replaceable>...</replaceable></#list></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"><h1>Welcome ${user<emphasis>!"visitor"</emphasis>}!</h1></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"><#if <emphasis>user??</emphasis>><h1>Welcome ${user}!</h1></#if></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 & Co.</quote> then
+ <literal>${name}</literal> should print <quote>Someone
+ <emphasis>&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>${"<"}</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"><#ftl output_format="HTML"></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"><#if cargo.weight < <emphasis>100</emphasis>>Light cargo</#if></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><#list <replaceable>...</replaceable>></literal>
+ sequences only. Or, the condition of <literal><#if
+ ...></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} <#-- uses mouse as a string -->
+${mouse.age} <#-- uses mouse as a hash -->
+${mouse.color} <#-- uses mouse as a hash --></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><#if
+ loggedIn
+ ><replaceable>...</replaceable></#if></literal> or
+ <literal><#if price ==
+ 0><replaceable>...</replaceable></#if></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"><@<emphasis>box</emphasis> title="Attention!">
+ Too much copy-pasting may leads to
+ maintenance headaches.
+</@<emphasis>box</emphasis>></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><@<replaceable>...</replaceable>></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><#--...--></primary>
+ </indexterm><indexterm>
+ <primary>#</primary>
+ </indexterm>: Comments are similar to HTML comments, but they
+ are delimited by <literal><#--</literal> and
+ <literal>--></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"><html><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<head><phrase role="markedInvisibleText">[BR]</phrase>
+Â Â <title>Welcome!</title><phrase role="markedInvisibleText">[BR]</phrase>
+</head><phrase role="markedInvisibleText">[BR]</phrase>
+<body><phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedComment"><#-- Greet the user with his/her name --></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+  <h1>Welcome <phrase role="markedInterpolation">${user}</phrase>!</h1><phrase
+ role="markedInvisibleText">[BR]</phrase>
+  <p>We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+Â Â <ul><phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag"><#list animals as animal></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+    <li><phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+ role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+ role="markedInvisibleText">[BR]</phrase>
+Â Â <phrase role="markedFTLTag"></#list></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+Â Â </ul><phrase role="markedInvisibleText">[BR]</phrase>
+</body><phrase role="markedInvisibleText">[BR]</phrase>
+</html></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><#if <#include
+ 'foo'>='bar'>...</#if></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"><h1>Welcome <phrase
+ role="markedInterpolation">${user <phrase role="markedComment"><#-- The name of user --></phrase>}</phrase>!</h1><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<p>We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+<ul><phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag"><#list <phrase role="markedComment"><#-- some comment... --></phrase> animals as <phrase
+ role="markedComment"><#-- again... --></phrase> animal></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><#...></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><#list animals as animal></literal> and
+ <literal></#list></literal>.</para>
+
+ <para><indexterm>
+ <primary>FTL tag</primary>
+ </indexterm>There are two kind of FTL tags:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Start-tag:
+ <literal><#<replaceable>directivename</replaceable>
+ <replaceable>parameters</replaceable>></literal></para>
+ </listitem>
+
+ <listitem>
+ <para>End-tag:
+ <literal></#<replaceable>directivename</replaceable>></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><#if
+ <replaceable>something</replaceable>><replaceable>...</replaceable></#if></literal>,
+ but just <literal><#include
+ <replaceable>something</replaceable>></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><@mydirective
+ <replaceable>parameters</replaceable>><replaceable>...</replaceable></@mydirective></literal>.
+ Further difference is that if the directive has no nested content, you
+ must use a tag like <literal><@mydirective
+ <replaceable>parameters</replaceable> /></literal>, similarly as in
+ XML (e.g. <literal><img <replaceable>...</replaceable>
+ /></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"><ul>
+<emphasis><#list animals as animal></emphasis>
+ <li>${animal.name} for ${animal.price} Euros
+ <emphasis><#if user == "Big Joe"></emphasis>
+ (except for you)
+<emphasis></#list></emphasis> <#-- WRONG! The "if" has to be closed first. -->
+<emphasis></#if></emphasis>
+</ul></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"><#list<phrase role="markedInvisibleText">[BR]</phrase>
+  animals       as<phrase role="markedInvisibleText">[BR]</phrase>
+Â Â Â Â Â animal<phrase role="markedInvisibleText">[BR]</phrase>
+></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"></#list    ></phrase></phrase></programlisting>
+
+ <para>You may not, however, insert white-space between the
+ <literal><</literal> or <literal></</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><</literal> and
+ <literal>></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><if user
+ == "Big
+ Joe"><replaceable>...</replaceable></if></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><#if
+ <replaceable>expression</replaceable>><replaceable>...</replaceable></#if></literal>.
+ The expression here must evaluate to a boolean value. For example
+ in <literal><#if 2 < 3></literal> the <literal>2 <
+ 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..<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..<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..<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 < y</literal>, <literal>x > y</literal>,
+ <literal>x >= y</literal>, <literal>x <= 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 && (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 -> x + 1</literal>, <literal>(x,
+ y) -> 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><</literal></td>
+ </tr>
+
+ <tr>
+ <td><literal>\g</literal></td>
+
+ <td>Greater-than sign: <literal>></literal></td>
+ </tr>
+
+ <tr>
+ <td><literal>\a</literal></td>
+
+ <td>Ampersand: <literal>&</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"><#list <emphasis>["foo", "bar", "baz"]</emphasis> as x>
+${x}
+</#list></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..<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><#list
+ <replaceable>...</replaceable>></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>..<<replaceable>end</replaceable></literal>
+ or
+ <literal><replaceable>start</replaceable>..!<replaceable>end</replaceable></literal>:
+ Range with exclusive end. For example,
+ <literal>1..<4</literal> gives <literal>[1, 2,
+ 3]</literal>, <literal>4..<1</literal> gives <literal>[4,
+ 3, 2]</literal>, and <literal>1..<1</literal> gives
+ <literal>[]</literal>. Note the last example; the result can
+ be an empty sequence. There's no difference between
+ <literal>..<</literal> and <literal>..!</literal>; the last
+ form is used in applications where using the
+ <literal><</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><#assign myRange =
+ 0..<x</literal>, NOT <literal><#assign myRange =
+ [0..<x]></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 ..< m / 2 - 1</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>..</literal>, <literal>..<</literal>,
+ <literal>..!</literal> and <literal>..*</literal> are
+ operators, so you can't have space inside them. Like
+ <literal>n .. <m</literal> is WRONG, but <literal>n ..<
+ 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"><#assign s = "Hello ${user}!">
+${s} <#-- Just to see what the value of s is -->
+</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><h1>Hello ${name}!</h1></literal>) and in
+ string literals (e.g. <literal><#include
+ "/footer/${company}.html"></literal>). A typical
+ <emphasis>WRONG</emphasis> usage is <literal><#if
+ ${big}>...</#if></literal>, which will cause a
+ syntactical error. You should simply write <literal><#if
+ big>...</#if></literal>. Also, <literal><#if
+ "${big}">...</#if></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"><#assign s = "Hello " + user + "!"></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"><#assign s = "ABCDEF">
+${s[2..3]}
+${s[2..<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"><#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
+- ${user}
+</#list></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><#list users
+ + admins as person></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"><#assign seq = ["A", "B", "C", "D", "E"]>
+<#list seq[1..3] as i>${i}</#list></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..<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"><#assign seq = ["A", "B", "C"]>
+
+Slicing with length limited ranges:
+- <#list seq[0..*2] as i>${i}</#list>
+- <#list seq[1..*2] as i>${i}</#list>
+- <#list seq[2..*2] as i>${i}</#list> <#-- Not an error -->
+- <#list seq[3..*2] as i>${i}</#list> <#-- Not an error -->
+
+Slicing with right-unlimited ranges:
+- <#list seq[0..] as i>${i}</#list>
+- <#list seq[1..] as i>${i}</#list>
+- <#list seq[2..] as i>${i}</#list>
+- <#list seq[3..] as i>${i}</#list></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"><#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
+- 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"} <#-- WRONG! --></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} <#-- Prints 2 -->
+${12.9 % 5} <#-- Prints 2 -->
+${12.1 % 5} <#-- Prints 2 -->
+
+${12 % 6} <#-- Prints 0 -->
+${12 % 6.9} <#-- Prints 0 --></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} <#-- Prints -2 -->
+${-12 % 5} <#-- Prints -2 -->
+${12 % -5} <#-- Prints 2 -->
+</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><#if
+ <replaceable>expression</replaceable>>...</#if></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"><#if <emphasis>user == "Big Joe"</emphasis>>
+ It is Big Joe
+</#if>
+<#if <emphasis>user != "Big Joe"</emphasis>>
+ It is not Big Joe
+</#if></programlisting>
+
+ <para>The <literal>user == "Big Joe"</literal> expression in the
+ <literal><#if ...></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><#if 1 == "1"></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><</literal>, <literal><=</literal>,
+ <literal>>=</literal> and <literal>></literal>. You can't use
+ them for strings! Example:</para>
+
+ <programlisting role="template"><#if x <emphasis><=</emphasis> 12>
+ x is less or equivalent with 12
+</#if></programlisting>
+
+ <para>There's a problem with <literal>>=</literal> and
+ <literal>></literal>. FreeMarker interprets the
+ <literal>></literal> character as the closing character of the
+ FTL tag. To prevent this, you can use <literal>lt</literal> instead
+ of <literal><</literal>, <literal>lte</literal> instead of
+ <literal><=</literal>, <literal>gt</literal> instead of
+ <literal>></literal> and <literal>gte</literal> instead of
+ <literal>>=</literal>, like in <literal><#if x gt
+ y></literal>. Another trick it to put the expression into <link
+ linkend="dgui_template_exp_parentheses">parentheses</link> like in
+ <literal><#if (x > y)></literal>, although it's considered
+ to be less elegant.</para>
+
+ <para>FreeMarker supports some more syntactical alternatives:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>&gt;</literal> and
+ <literal>&lt;</literal> can also be used, like in:
+ <literal><#if x &gt; y></literal> or <literal><#if
+ x &gt;= y></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>&<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>&&</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"><#if x < 12 <emphasis>&&</emphasis> color == "green">
+ We have less than 12 things, and they are green.
+</#if>
+<#if <emphasis>!</emphasis>hot> <#-- here hot must be a boolean -->
+ It's not hot.
+</#if></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>&&</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;</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>&<replaceable>...</replaceable>;</literal> things)
+ in FTL tags; it's just an exception with these operators.</para>
+ </listitem>
+
+ <listitem>
+ <para>Deprecated forms: <literal>&</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 & 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 & JERRY
+Tom &amp; Jerry
+TOM &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 + " & Duck")?html}</programlisting>
+
+ <programlisting role="output">Bar
+Horse
+Tom &amp; Jerry &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."}
+<#assign mouse="Jerry">
+${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!})
+<#assign mouse = "Jerry">
+(${mouse!})</programlisting>
+
+ <para>The output will be:</para>
+
+ <programlisting role="output">()
+(Jerry)</programlisting>
+
+ <warning>
+ <para>Due to syntactical ambiguities <literal><@something
+ a=x! b=y /></literal> will be interpreted as
+ <literal><@something a=x!(b=y) /></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><@something a=(x!) b=y
+ /></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"><#assign seq = ['a', 'b']>
+${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"><#if mouse??>
+ Mouse found
+<#else>
+ No mouse found
+</#if>
+Creating mouse...
+<#assign mouse = "Jerry">
+<#if mouse??>
+ Mouse found
+<#else>
+ No mouse found
+</#if></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><#assign x += y></literal> is shorthand for
+ <literal><#assign x = x + y></literal>, <literal><#assign x
+ *= y></literal> is shorthand for <literal><#assign x = x *
+ y></literal>, and so on.</para>
+
+ <para><literal><#assign x++></literal> differs from
+ <literal><#assign x += 1></literal> (or <literal><#assign x
+ = x + 1></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><#assign x--></literal> is shorthand for
+ <literal><#assign x -= 1></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><#assign x = x + 1></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>) ->
+ <replaceable>expression</replaceable></literal>. If there's only a
+ single argument, the parentheses can be omitted:
+ <literal><replaceable>name1</replaceable> ->
+ <replaceable>expression</replaceable></literal>.</para>
+
+ <para>As the right side of the <literal>-></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 ->
+ 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 ->
+ 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"> <#-- Output will be: -->
+${3 * 2 + 2} <#-- 8 -->
+${3 * (2 + 2)} <#-- 12 -->
+${3 * ((2 + 2) * (1 / 2))} <#-- 6 -->
+${"green " + "mouse"?upper_case} <#-- green MOUSE -->
+${("green " + "mouse")?upper_case} <#-- GREEN MOUSE -->
+<#if !(color == "red" || color == "green")>
+ The color is nor red nor green
+</#if></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><#-- ... --></literal> or as <literal>[#--
+ ... --]</literal>. Example:</para>
+
+ <programlisting role="template"><#assign x <#-- A comment --> = 123 <#-- A comment -->>
+<#function f(x <#-- A comment -->, y <#-- A comment -->)>
+ <#return <#-- A comment --> 1 <#-- A comment -->>
+</#function>
+<#assign someHash = {
+ "foo": 123, <#-- A comment -->
+ "bar": x <#-- A comment --> + 1,
+ <#-- A comment -->
+ "baaz": f(1 <#-- A comment -->, 2 <#-- A comment -->)
+} <#-- A comment -->></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>..<</literal>
+ <literal>..!</literal> <literal>..*</literal></td>
+ </tr>
+
+ <tr>
+ <td>relational operators</td>
+
+ <td><literal>< > <= >=</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>&&</literal></td>
+ </tr>
+
+ <tr>
+ <td>logical <quote>or</quote> operator</td>
+
+ <td><literal>||</literal></td>
+ </tr>
+
+ <tr>
+ <td>local lambda</td>
+
+ <td><literal>-></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><h1>Hello ${name}!</h1></literal>) and <link
+ linkend="dgui_template_exp_stringop_interpolation">in string literal
+ expressions</link> (e.g., <literal><#include
+ "/footer/${company}.html"></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><h1>Hello ${name}!</h1></literal>) and in
+ <link linkend="dgui_template_exp_direct_string">string
+ literals</link> (e.g. <literal><#include
+ "/footer/${company}.html"></literal>). A typical
+ <emphasis>WRONG</emphasis> usage is <literal><#if
+ ${big}>...</#if></literal>, which will give syntactical
+ error. You should simply write <literal><#if
+ big>...</#if></literal>. Also, <literal><#if
+ "${big}">...</#if></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"><a href="/shop/productdetails?id=${product.id?c}">Details...</a></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><#macro greet></emphasis>
+ <font size="+2">Hello Joe!</font>
+<emphasis></#macro></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><#macro greet></literal> and
+ <literal></#macro></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"><@greet></@greet></programlisting>
+
+ <para>But since
+ <literal><<replaceable>anything</replaceable>></<replaceable>anything</replaceable>></literal>
+ is equivalent with
+ <literal><<replaceable>anything</replaceable>/></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"><@greet/></programlisting>
+
+ <para>This will print:</para>
+
+ <programlisting role="output"> <font size="+2">Hello Joe!</font>
+ </programlisting>
+
+ <para>But macros can do much more, since the thing between
+ <literal><#macro <replaceable>...</replaceable>></literal> and
+ <literal></#macro></literal> is a template fragment, thus it
+ can contain interpolations
+ (<literal>${<replaceable>...</replaceable>}</literal>) and FTL tags
+ (e.g. <literal><#if
+ <replaceable>...</replaceable>><replaceable>...</replaceable></#if></literal>).</para>
+
+ <note>
+ <para>Programmers will say on
+ <literal><@<replaceable>...</replaceable>></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"><#macro greet <emphasis>person</emphasis>>
+ <font size="+2">Hello <emphasis>${person}</emphasis>!</font>
+</#macro></programlisting>
+
+ <para>and then you can use this macro as:</para>
+
+ <programlisting role="template"><@greet <emphasis>person="Fred"</emphasis>/> and <@greet <emphasis>person="Batman"</emphasis>/>
+</programlisting>
+
+ <para>which is similar to HTML syntax. This will print:</para>
+
+ <programlisting role="output"> <font size="+2">Hello <emphasis>Fred</emphasis>!</font>
+ and <font size="+2">Hello <emphasis>Batman</emphasis>!</font>
+ </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><@greet person=Fred/></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"><#macro greet person <emphasis>color</emphasis>>
+ <font size="+2" color="${color}">Hello ${person}!</font>
+</#macro></programlisting>
+
+ <para>and then you can use this macro like:</para>
+
+ <programlisting role="template"><@greet person="Fred" color="black"/></programlisting>
+
+ <para>The order of parameters is not important, so this is
+ equivalent with the previous:</para>
+
+ <programlisting role="template"><@greet color="black" person="Fred"/></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><@greet person="Fred" color="black"
+ background="green"/></literal> then you will get an error, since
+ you haven't mentioned parameter <literal>background</literal> in the
+ <literal><#macro
+ <replaceable>...</replaceable>></literal>.</para>
+
+ <para>Also, you must give value for all parameters that you have
+ defined for the macro. So if you try <literal><@greet
+ person="Fred"/></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"><#macro greet person color<emphasis>="black"</emphasis>>
+ <font size="+2" color="${color}">Hello ${person}!</font>
+</#macro></programlisting>
+
+ <para>Now <literal><@greet person="Fred"/></literal> is OK,
+ since it is equivalent with <literal><@greet person="Fred"
+ color="black"/></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><@greet person="Fred" color="red"/></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><#if
+ <replaceable>...</replaceable>><replaceable>nested
+ content</replaceable></#if></literal> can have. For example,
+ this creates a macro that draws borders around its nested
+ content:</para>
+
+ <programlisting role="template"><#macro border>
+ <table border=4 cellspacing=0 cellpadding=4><tr><td>
+ <emphasis><#nested></emphasis>
+ </tr></td></table>
+</#macro></programlisting>
+
+ <para>The <literal><#nested></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"><@border>The bordered text</@border></programlisting>
+
+ <para>the output will be:</para>
+
+ <programlisting role="output"> <table border=4 cellspacing=0 cellpadding=4><tr><td>
+ The bordered text
+ </td></tr></table>
+ </programlisting>
+
+ <para>The <literal>nested</literal> directive can be called for
+ multiple times, for example:</para>
+
+ <programlisting role="template"><#macro do_thrice><emphasis>
+ <#nested>
+ <#nested>
+ <#nested></emphasis>
+</#macro>
+<@do_thrice>
+ Anything.
+</@do_thrice></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"><@greet person="Joe">
+ Anything.
+</@greet></programlisting>
+
+ <para>then FreeMarker will not see this as an error, and simply
+ prints:</para>
+
+ <programlisting role="output"><font size="+2">Hello Joe!</font></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"><@border>
+ <ul>
+ <@do_thrice>
+ <li><@greet person="Joe"/>
+ </@do_thrice>
+ </ul>
+</@border></programlisting>
+
+ <para>and will print:</para>
+
+ <programlisting role="output"> <table border=4 cellspacing=0 cellpadding=4><tr><td>
+ <ul>
+ <li><font size="+2">Hello Joe!</font>
+
+ <li><font size="+2">Hello Joe!</font>
+
+ <li><font size="+2">Hello Joe!</font>
+
+ </ul>
+
+ </tr></td></table></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"><#macro repeat count>
+ <#local y = "test">
+ <#list 1..count as x>
+ ${y} ${count}/${x}: <#nested>
+ </#list>
+</#macro>
+<@repeat count=3>${y!"?"} ${x!"?"} ${count!"?"}</@repeat></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"><#macro test foo>${foo} (<#nested>) ${foo}</#macro>
+<@test foo="A"><@test foo="B"><@test foo="C"/></@test></@test>
+</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><#list foos as
+ foo><replaceable>...</replaceable></#list></literal>),
+ while the <emphasis>value</emphasis> of the variables is set by the
+ directive itself.</para>
+
+ <programlisting role="template"><#macro do_thrice>
+ <#nested <emphasis>1</emphasis>>
+ <#nested <emphasis>2</emphasis>>
+ <#nested <emphasis>3</emphasis>>
+</#macro>
+<@do_thrice <emphasis>; x</emphasis>> <#-- user-defined directive uses ";" instead of "as" -->
+ ${<emphasis>x</emphasis>} Anything.
+</@do_thrice></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><@...></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"><#macro repeat count>
+ <#list 1..count as x>
+ <#nested <emphasis>x, x/2, x==count</emphasis>>
+ </#list>
+</#macro>
+<@repeat count=4 ; <emphasis>c, halfc, last</emphasis>>
+ ${<emphasis>c</emphasis>}. ${<emphasis>halfc</emphasis>}<#if <emphasis>last</emphasis>> Last!</#if>
+</@repeat></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"><@repeat count=4 ; <emphasis>c, halfc, last</emphasis>>
+ ${c}. ${halfc}<#if last> Last!</#if>
+</@repeat>
+<@repeat count=4 ; <emphasis>c, halfc</emphasis>>
+ ${c}. ${halfc}
+</@repeat>
+<@repeat count=4>
+ Just repeat it...
+</@repeat></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><#assign foo =
+ "com.example.FooDirective"?new()></literal> or
+ <literal><#assign foo =
+ "com.example.FooMethod"?new()></literal> on the same place where
+ you would have <literal><#macro foo
+ <replaceable>...</replaceable>></literal> or
+ <literal><#function foo
+ <replaceable>...</replaceable>></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><#list xs as
+ x><replaceable>...</replaceable></#list></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"><#assign x = 1> <#-- create variable x -->
+${x}
+<#assign x = 2> <#-- replace variable x -->
+${x}
+<#assign x++> <#-- replace variable x -->
+${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"><#assign x = "plain">
+1. ${x} <#-- we see the plain var. here -->
+<@test/>
+6. ${x} <#-- the value of plain var. was not changed -->
+<#list ["loop"] as x>
+ 7. ${x} <#-- now the loop var. hides the plain var. -->
+ <#assign x = "plain2"> <#-- replaces the plain var, not the loop var. -->
+ 8. ${x} <#-- it still hides the plain var. -->
+</#list>
+9. ${x} <#-- now the new value of plain var. becomse visible -->
+
+<#macro test>
+ 2. ${x} <#-- we still see the plain var. here -->
+ <#local x = "local">
+ 3. ${x} <#-- now the local var. hides it -->
+ <#list ["loop"] as x>
+ 4. ${x} <#-- now the loop var. hides the local var. -->
+ </#list>
+ 5. ${x} <#-- now we see the local var. again -->
+</#macro></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"><#list ["loop 1"] as x>
+ ${x}
+ <#list ["loop 2"] as x>
+ ${x}
+ <#list ["loop 3"] as x>
+ ${x}
+ </#list>
+ ${x}
+ </#list>
+ ${x}
+</#list></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} <#-- prints: Big Joe -->
+<#assign user = "Joe Hider">
+${user} <#-- prints: Joe Hider -->
+${.globals.user} <#-- prints: Big Joe --></programlisting>
+
+ <para>You could also write <literal>.data_model.user</literal>
+ instead, and then not even a <literal><#global user =
+ "<replaceable>...</replaceable>"></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"><#macro copyright date>
+ <p>Copyright (C) ${date} Someone. All rights reserved.</p>
+</#macro>
+
+<#assign mail = "user@example.com"></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"><#<emphasis>import</emphasis> "/lib/example.ftl" as <emphasis>e</emphasis>>
+
+Some Web page...
+<@<emphasis>e</emphasis>.copyright date="1999-2002"/>
+${<emphasis>e</emphasis>.mail}</programlisting>
+
+ <programlisting role="output">Some Web page...
+ <p>Copyright (C) 1999-2002 Someone. All rights reserved.</p>
+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"><#macro copyright date>
+ <p>Copyright (C) ${date} Someone. All rights reserved.
+ <br>Email: <emphasis>${mail}</emphasis></p>
+</#macro>
+
+<#assign mail = "user@example.com"></programlisting>
+
+ <para>and <literal>some_web_page.ftl</literal> with this:</para>
+
+ <programlisting role="template"><#import "/lib/example.ftl" as e>
+<emphasis><#assign mail="other@example.com"></emphasis>
+<@e.copyright date="1999-2002"/>
+${e.mail}
+${mail}</programlisting>
+
+ <programlisting role="output"> <p>Copyright (C) 1999-2002 Someone. All rights reserved.
+ <br>Email: <emphasis>user@example.com</emphasis></p>
+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"><#import "/lib/example.ftl" as e>
+${e.mail}
+<#assign mail="other@example.com" <emphasis>in e</emphasis>>
+${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"><#macro copyright date>
+ <p>Copyright (C) ${date} <emphasis>${user}</emphasis>. All rights reserved.</p>
+</#macro></programlisting>
+
+ <para>Assuming <literal>user</literal> is <quote>John
+ Doe</quote>:</para>
+
+ <programlisting role="template"><#import "/lib/my_test.ftl" as my>
+User is: ${user}
+<@my.copyright date="1999-2002"/>
+</programlisting>
+
+ <programlisting role="output">User is: John Doe
+ <p>Copyright (C) 1999-2002 John Doe. All rights reserved.</p>
+</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"><#import "/lib/example.ftl" as e>
+<#import "/lib/example.ftl" as e2>
+<#import "/lib/example.ftl" as e3>
+${e.mail}, ${e2.mail}, ${e3.mail}
+<#assign mail="other@example.com" in e>
+${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><</literal>, <literal>></literal>,
+ <literal>&</literal>, <literal>"</literal>,
+ <literal>'</literal> as <literal>&lt;</literal>,
+ <literal>&gt;</literal>, <literal>&amp;</literal>,
+ <literal>&quot;</literal>,
+ <literal>&#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><</literal>, <literal>></literal>,
+ <literal>&</literal>, <literal>"</literal>,
+ <literal>'</literal> as <literal>&lt;</literal>,
+ <literal>&gt;</literal>, <literal>&amp;</literal>,
+ <literal>&quot;</literal>,
+ <literal>&#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><</literal>, <literal>></literal>,
+ <literal>&</literal>, <literal>"</literal>,
+ <literal>'</literal> as <literal>&lt;</literal>,
+ <literal>&gt;</literal>, <literal>&amp;</literal>,
+ <literal>&quot;</literal>,
+ <literal>&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"><#ftl output_format="XML">
+${"'"} <#-- Prints: &apos; --></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><#ftl
+ output_format="XML" auto_esc=true></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"><#-- Let's assume we have "HTML" output format by default. -->
+${"'"} <#-- Prints: &#39; -->
+<#outputformat "XML">
+ ${"'"} <#-- Prints: &apos; -->
+</#outputformat>
+${"'"} <#-- Prints: &#39; -->
+</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"><#-- Let's assume we have "HTML" output format by default. -->
+${'<b>test</b>'} <#-- prints: &lt;b&gt;test&lt;/b&gt; -->
+${'<b>test</b>'<emphasis>?no_esc</emphasis>} <#-- prints: <b>test</b> --></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">${'&'} <#-- prints: &amp; -->
+<emphasis><#noautoesc></emphasis>
+ ${'&'} <#-- prints: & -->
+ ...
+ ${'&'} <#-- prints: & -->
+<emphasis></#noautoesc></emphasis>
+${'&'} <#-- prints: &amp; --></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"><#ftl <emphasis>autoesc=false</emphasis>>
+${'&'} <#-- prints: & -->
+<emphasis><#autoesc></emphasis>
+ ${'&'} <#-- prints: &amp; -->
+ ...
+ ${'&'} <#-- prints: &amp; -->
+<emphasis></#autoesc></emphasis>
+${'&'} <#-- prints: & --></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"><#ftl <emphasis>autoesc=false</emphasis>>
+${'&'} <#-- prints: & -->
+${'&'<emphasis>?esc</emphasis>} <#-- prints: &amp; --></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"><#-- We assume that we have "HTML" output format by default. -->
+
+<@infoBox "Foo & bar" />
+<@infoBox "Foo <b>bar</b>"?no_esc />
+
+<#macro infoBox message>
+ <div class="infoBox">
+ ${message}
+ </div>
+</#macro></programlisting>
+
+ <programlisting role="output"> <div class="infoBox">
+ Foo &amp; bar
+ </div>
+ <div class="infoBox">
+ Foo <b>bar</b>
+ </div></programlisting>
+
+ <para>Another case where you get a markup output value is output
+ capturing:</para>
+
+ <programlisting role="template"><#-- We assume that we have "HTML" output format by default. -->
+<#assign captured><b>Test</b></#assign>
+Just a string: ${"<b>Test</b>"}
+Captured output: ${captured}</programlisting>
+
+ <programlisting role="output">Just a string: &lt;b&gt;Test&lt;/b&gt;
+Captured output: <b>Test</b></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"><#-- We assume that we have "HTML" output format by default. -->
+
+<#assign markupOutput1="<b>Test</b>"?no_esc>
+<#assign markupOutput2="Foo & bar"?esc>
+
+As expected:
+${markupOutput1}
+${markupOutput2}
+
+Possibly unintended double escaping:
+${markupOutput1?markup_string}
+${markupOutput2?markup_string}</programlisting>
+
+ <programlisting role="output">As expected:
+<b>Test</b>
+Foo &amp; bar
+
+Possibly unintended double escaping:
+&lt;b&gt;Test&lt;/b&gt;
+Foo &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><#assign
+ captured><replaceable>...</replaceable></#assign></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><#ftl
+ auto_esc=true></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"><#-- We assume that we have "HTML" output format by default. -->
+
+<#assign mo1 = "Foo's bar {}"?esc>
+HTML: ${mo1}
+XML: <#outputformat 'XML'>${mo1}</#outputformat>
+RTF: <#outputformat 'RTF'>${mo1}</#outputformat>
+
+<#assign mo2><p>Test</#assign>
+HTML: ${mo2}
+XML: <#attempt><#outputformat 'XML'>${mo2}</#outputformat><#recover>Failed</#attempt>
+RTF: <#attempt><#outputformat 'RTF'>${mo2}</#outputformat><#recover>Failed</#attempt></programlisting>
+
+ <programlisting role="output">HTML: Foo&#39;s bar {}
+XML: Foo&apos;s bar {}
+RTF: Foo's bar \{\}
+
+HTML: <p>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"><#-- We assume that we have "undefined" output format here. -->
+
+<#outputformat "HTML"><#assign htmlMO><p>Test</#assign></#outputformat>
+<#outputformat "XML"><#assign xmlMO><p>Test</p></#assign></#outputformat>
+<#outputformat "RTF"><#assign rtfMO>\par Test</#assign></#outputformat>
+HTML: ${htmlMO}
+XML: ${xmlMO}
+RTF: ${rtfMO}</programlisting>
+
+ <programlisting role="output">HTML: <p>Test
+XML: <p>Test</p>
+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"><#-- We assume that we have "HTML" output format by default. -->
+${"<h1>"?no_esc + "Foo & bar" + "</h1>"?no_esc}</programlisting>
+
+ <programlisting role="output"><h1>Foo &amp; bar</h1></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><#assign s = "Hello ${name}!"></literal>), it's
+ just a shorthand of using the <literal>+</literal> operator
+ (<literal><#assign s = "Hello" + name + "!"></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"><#-- We assume that we have "HTML" output format by default. -->
+<#assign name = "Foo & Bar">
+
+<#assign s = "<p>Hello ${name}!">
+${s}
+<p>Hello ${name}!
+
+To prove that s didn't contain the value in escaped form:
+${s?replace('&'), 'and'}</programlisting>
+
+ <programlisting role="output">&lt;p&gt;Hello Foo &amp; Bar!
+<p>Hello Foo &amp; Bar!
+
+To prove that "s" didn't contain the value in escaped form:
+&lt;p&gt;Hello Foo and Bar!</programlisting>
+ </section>
+
+ <section>
+ <title>Combined output formats</title>
+
+ <para>Combined output formats are output formats that are created
+ ad-hoc from other output formats by nesting them into each other,
+ so that the escaping of both output formats are applied. <link
+ linkend="topic.combinedOutputFormats">They are discussed
+ here...</link></para>
+ </section>
+ </section>
+ </section>
+
+ <section xml:id="dgui_misc_computer_vs_human_format">
+ <title>Formatting for humans, or for computers</title>
+
+ <para>By default
+ <literal>${<replaceable>someValue</replaceable>}</literal> outputs
+ numbers, date/time/date-time and boolean values in a format that
+ targets normal users (<quote>humans</quote>). You have various
+ settings to specify how that format looks, like
+ <literal>number_format</literal>, <literal>date_format</literal>,
+ <literal>time_format</literal>, <literal>datetime_format</literal>,
+ <literal>boolan_format</literal>. The output also often depends on the
+ <literal>locale</literal> setting (i.e., on the language, and country
+ of the user). So 3000000 is possibly printed as
+ <literal>3,000,000</literal> (i.e., with grouping separators), or
+ <literal>3.14</literal> is possibly printed as <literal>3,14</literal>
+ (i.e., with a different decimal separator).</para>
+
+ <para>At some places you need to output values that will be read
+ (parsed) by some program, in which case always use the <link
+ linkend="ref_builtin_c"><literal>c</literal> built-in</link>, as in
+ <literal>${<replaceable>someValue</replaceable>?c}</literal> (the
+ <quote>c</quote> stands for Computer). <emphasis>Then the formatting
+ depends on the <literal>c_format</literal> <link
+ linkend="pgui_config_settings">setting</link></emphasis>, which
+ usually refers to a computer language, like <literal>"JSON"</literal>.
+ The output of <literal>?c</literal> is not influenced by
+ <literal>locale</literal>, <literal>number_format</literal>,
+ etc.</para>
+
+ <para>The <literal>c</literal> built-in will format string values to
+ string literals. Like if the <literal>c_format</literal> setting is
+ <literal>"JSON"</literal>, then <literal>{"fullName":
+ ${fullName?c}}</literal> will output something like
+ <literal>{"fullName": "John Doe"}</literal>, where the quotation marks
+ (and <literal>\</literal> escaping if needed) were added by
+ <literal>?c</literal>.</para>
+
+ <note>
+ <para>At least as of 2.3.32, the <literal>c</literal> built-in
+ doesn't support date/time/datetime values, only numbers, booleans,
+ and strings.</para>
+ </note>
+
+ <para>When formatting for computers, at some places you want to output
+ a <literal>null</literal> (or its equivalent in the target language)
+ if the value you print is missing/<literal>null</literal>. The
+ convenient shortcut for that is using the <literal>cn</literal>
+ built-in (the <quote>n</quote> stands for Nullable), as in
+ <literal>${<replaceable>someValue</replaceable>?cn}</literal>. It
+ behaves like the <literal>c</literal> built-in, except that if
+ <literal><replaceable>someValue</replaceable></literal> evaluates to
+ <literal>null</literal>/missing, it outputs the
+ <literal>null</literal> literal in the syntax that the
+ <literal>c_format</literal> setting specifies, instead of stopping
+ with missing value error.</para>
+
+ <para>For the templates where the output is obviously only for
+ computer consumption, some prefers setting the
+ <literal>number_format</literal>, and
+ <literal>boolean_format</literal> settings to <literal>"c"</literal>.
+ (Before 2.3.32, for <literal>number_format</literal> you have to use
+ <literal>"computer"</literal> instead.) Then
+ <literal>${<replaceable>someValue</replaceable>}</literal>, for
+ number, and boolean values will format like <literal>?c</literal>
+ does. To output string literals (i.e, to add quotation and escaping),
+ you will still need an explicit <literal>?c</literal>. Also if you
+ need to output <literal>null</literal> literals, you still have to use
+ <literal>?cn</literal>.</para>
+
+ <para>These are the table of supported <literal>c_format</literal>
+ setting values (as of FreeMarker 2.3.32), and their intended
+ use:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>"JSON"</literal>: JSON generation. Generally,
+ <literal>"JavaScript or JSON"</literal> (see later) is recommended
+ over this.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>"JavaScript"</literal>: JavaScript generation.
+ Generally, <literal>"JavaScript or JSON"</literal> (see later) is
+ recommended over this.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>"Java"</literal>: Java source code
+ generation</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>"XS"</literal>: XML Schema compliant XML
+ generation</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>"JavaScript or JSON"</literal>: For generating
+ output that's compatible with both JSON and JavaScript. This setup
+ is therefore resilient against configuration mistakes, where we
+ generate output in one language, but use the
+ <literal>c_format</literal> for the other. The small price to pay
+ is that we can't utilize some language-specific opportunities to
+ make the output a bit shorter, but that hardly matters in
+ practice. This is the default if if the <link
+ linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
+ setting</link> is at least 2.3.32.</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>"legacy"</literal>: Default for backward
+ compatibility when the <link
+ linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
+ setting</link> is less than 2.3.32. Avoid! Can have rounding
+ losses, and formatting glitches for infinity and NaN.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The behaviour of these is documented at the <literal>c</literal>
+ built-in: <link linkend="ref_builtin_c">for numbers</link>, <link
+ linkend="ref_builtin_c_boolean">for boolean</link>, <link
+ linkend="ref_builtin_c_string">for strings</link>, <link
+ linkend="ref_builtin_cn">for null-s</link>.</para>
+ </section>
+
+ <section xml:id="dgui_misc_whitespace">
+ <title>White-space handling</title>
+
+ <indexterm>
+ <primary>white-space removal</primary>
+ </indexterm>
+
+ <para>The control of the <link
+ linkend="gloss.whiteSpace">white-space</link> in a template is a
+ problem that to some extent haunts every template engine in the
+ business.</para>
+
+ <para>Let see this template. I have marked the components of template
+ with colors: <phrase role="markedText">text</phrase>, <phrase
+ role="markedInterpolation">interpolation</phrase>, <phrase
+ role="markedFTLTag">FTL tag</phrase>. With the <phrase
+ role="markedInvisibleText">[BR]</phrase>-s I visualize the <link
+ linkend="gloss.lineBreak">line breaks</link>.</para>
+
+ <programlisting role="template"><phrase role="markedText"><p>List of users:<phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag"><#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}]></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<ul><phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag"><#list users as user></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+ <phrase role="markedFTLTag"><#if !user.hidden></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+ <li><phrase role="markedInterpolation">${user.name}</phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+ <phrase role="markedFTLTag"></#if></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag"></#list></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+</ul><phrase role="markedInvisibleText">[BR]</phrase>
+<p>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"><p>List of users:<phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+<ul><phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+ <phrase role="markedInvisibleText">[BR]</phrase>
+ <li></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>
+ <li></phrase>Julia<phrase role="markedText"><phrase
+ role="markedInvisibleText">[BR]</phrase>
+ <phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInvisibleText">[BR]</phrase>
+</ul><phrase role="markedInvisibleText">[BR]</phrase>
+<p>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><@myMacro/></literal>, <literal><#if
+ <replaceable>...</replaceable>></literal>) and/or FTL
+ comments (e.g. <literal><#-- blah --></literal>), apart
+ from the the ignored white-space itself. For example, if a line
+ contains only an <literal><#if
+ <replaceable>...</replaceable>></literal>, then the
+ indentation before the tag and the line break after the tag will
+ be ignored. However, if the line contains <literal><#if
+ <replaceable>...</replaceable>>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><#if
+ <replaceable>...</replaceable>><#list
+ <replaceable>...</replaceable>></literal> is subject to
+ white-space ignoring, while a line that contains
+ <literal><#if <replaceable>...</replaceable>>Â <#list
+ <replaceable>...</replaceable>></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"><p>List of users:<phrase
+ role="markedInvisibleText">[BR]</phrase>
+<ul><phrase role="markedInvisibleText">[BR]</phrase>
+ <li></phrase>Joe<phrase role="markedText"><phrase
+ role="markedInvisibleText">[BR]</phrase>
+ <li></phrase>Julia<phrase role="markedText"><phrase
+ role="markedInvisibleText">[BR]</phrase>
+</ul><phrase role="markedInvisibleText">[BR]</phrase>
+<p>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"><p>List of users:<phrase
+ role="markedInvisibleText">[BR]</phrase></phrase>
+<phrase role="markedFTLTag"><#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}]></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedText"><ul><phrase role="markedInvisibleText">[BR]</phrase></phrase>
+<phrase role="markedFTLTag"><#list users as user></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+ <phrase role="markedFTLTag"><#if !user.hidden></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedText"> <li><phrase role="markedInterpolation">${user.name}</phrase><phrase
+ role="markedInvisibleText">[BR]</phrase></phrase>
+ <phrase role="markedFTLTag"></#if></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag"></#list></phrase><phrase
+ role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedText"></ul><phrase role="markedInvisibleText">[BR]</phrase>
+<p>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><#compress></emphasis>
+<#assign users = [{"name":"Joe", "hidden":false},
+ {"name":"James Bond", "hidden":true},
+ {"name":"Julia", "hidden":false}]>
+List of users:
+<#list users as user>
+ <#if !user.hidden>
+ - ${user.name}
+ </#if>
+</#list>
+That's all.
+<emphasis></#compress></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><#compress><replaceable>...</replaceable></#compress></literal>
+ on the last example with <literal><@compress
+ single_line=true><replaceable>...</replaceable></@compress></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><</literal> and <literal>></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><#if x>[=y]</#if></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><</literal> and <literal>></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"><p>We have these animals:
+<table border=1>
+ <tr><th>Name<th>Price
+ <emphasis>[#list animals as animal]</emphasis>
+ <tr>
+ <td>
+ <emphasis>[#if animal.size == "large"]</emphasis><b><emphasis>[/#if]</emphasis>
+ ${animal.name}
+ <emphasis>[#if animal.size == "large"]</emphasis></b><emphasis>[/#if]</emphasis>
+ <td>${animal.price} Euros
+ <emphasis>[/#list]</emphasis>
+</table></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><#if <replaceable>...</replaceable>></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><#ftl <replaceable>...</replaceable>></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.
+--]
+<p>We have these animals:
+<table border=1>
+ <tr><th>Name<th>Price
+ [#list animals as animal]
+ <tr>
+ <td>
+ [#if animal.size == "large"]<b>[/#if]
+ <emphasis>[=animal.name]</emphasis>
+ [#if animal.size == "large"]</b>[/#if]
+ <td><emphasis>[=animal.price]</emphasis> Euros
+ [/#list]
+</table></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<String, Object> root = new HashMap<>();
+
+// 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"><html>
+<head>
+ <title>Welcome!</title>
+</head>
+<body>
+ <h1>Welcome ${user}!</h1>
+ <p>Our latest product:
+ <a href="${latestProduct.url}">${latestProduct.name}</a>!
+</body>
+</html></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"><#assign x = "something">
+${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><@upper></emphasis>
+ bar
+ <#-- All kind of FTL is allowed here -->
+ <#list ["red", "green", "blue"] as color>
+ ${color}
+ </#list>
+ baaz
+<emphasis></@upper></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.
+ *
+ *
+ * <p><b>Directive info</b></p>
+ *
+ * <p>Directive parameters: None
+ * <p>Loop variables: None
+ * <p>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 <#nested> 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 < 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"><#-- Maybe you have directives that you have implemented in FTL -->
+<#macro something>
+ ...
+</#macro>
+
+<#-- Now you can't use <#macro upper>, but instead you can: -->
+<#assign upper = "com.example.UpperDirective"?new()>
+</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><hr></literal>-s.
+ Let's call this directive "repeat". Example template:</para>
+
+ <programlisting role="template"><#assign x = 1>
+
+<emphasis><@repeat count=4></emphasis>
+ Test ${x}
+ <#assign x++>
+<emphasis></@repeat></emphasis>
+
+<emphasis><@repeat count=3 hr=true></emphasis>
+ Test
+<emphasis></@repeat></emphasis>
+
+<emphasis><@repeat count=3; cnt></emphasis>
+ ${cnt}. Test
+<emphasis></@repeat></emphasis></programlisting>
+
+ <para>Output:</para>
+
+ <programlisting role="output"> Test 1
+ Test 2
+ Test 3
+ Test 4
+
+ Test
+<hr> Test
+<hr> 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
+ * <tt>&lt;hr></tt>-s.
+ *
+ *
+ * <p><b>Directive info</b></p>
+ *
+ * <p>Parameters:
+ * <ul>
+ * <li><code>count</code>: The number of repetations. Required!
+ * Must be a non-negative number. If it is not a whole number then it will
+ * be rounded <em>down</em>.
+ * <li><code>hr</code>: Tells if a HTML "hr" element could be printed between
+ * repetations. Boolean. Optional, defaults to <code>false</code>.
+ * </ul>
+ *
+ * <p>Loop variables: One, optional. It gives the number of the current
+ * repetation, starting from 1.
+ *
+ * <p>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 < 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 > 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 < countParam; i++) {
+ // Prints a <hr> between all repetations if the "hr" parameter
+ // was true:
+ if (hrParam && i != 0) {
+ out.write("<hr>");
+ }
+
+ // Set the loop variable, if there is one:
+ if (loopVars.length > 0) {
+ loopVars[0] = new SimpleNumber(i + 1);
+ }
+
+ // Executes the nested body (same as <#nested> 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"><init-param>
+ <param-name>object_wrapper</param-name>
+ <param-value>DefaultObjectWrapper(2.3.27)</param-value>
+</init-param></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<E1, E2> {
+ 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><#list someTupple
+ <replaceable>...</replaceable>></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<?, ?> tupple;
+
+ public TuppleAdapter(Tupple<?, ?> 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<?, ?>) obj, this);
+ }
+
+ return super.handleUnknownType(obj);
+ }
+
+}</programlisting>
+
+ <para>and then where you configure FreeMarker (<link
+ linkend="pgui_config">about configuring, see here...</link>) we plug
+ our object wrapper in:</para>
+
+ <programlisting role="unspecified">// Where you initialize the cfg *singleton* (happens just once in the application life-cycle):
+cfg = new Configuration(Configuration.VERSION_2_3_27);
+...
+cfg.setObjectWrapper(new MyAppObjectWrapper(cfg.getIncompatibleImprovements()));</programlisting>
+
+ <para>or if you are configuring FreeMarker with
+ <literal>java.util.Properties</literal> instead (and let's say it's
+ also a <literal>.properties</literal> file):</para>
+
+ <programlisting role="unspecified">object_wrapper=com.example.myapp.freemarker.MyAppObjectWrapper(2.3.27)</programlisting>
+ </section>
+ </section>
+ </chapter>
+
+ <chapter xml:id="pgui_config">
+ <title>The Configuration</title>
+
+ <indexterm>
+ <primary>Configuration</primary>
+ </indexterm>
+
+ <para>This is just an overview. See the <olink
+ targetdoc="api">FreeMarker Java API documentation</olink> for the
+ details.</para>
+
+ <section xml:id="pgui_config_basics">
+ <title>Basics</title>
+
+ <para>First of all, be sure you have read the <link
+ linkend="pgui_quickstart_createconfiguration">Getting Started</link>
+ chapter.</para>
+
+ <para>A configuration is a
+ <literal>freemarker.template.Configuration</literal> object that
+ stores your common (global, application level) settings and defines
+ variables that you want to be available in all templates (so called
+ shared variables). Also, it deals with the creation and caching of
+ <literal>Template</literal> instances.</para>
+
+ <para>An application typically uses only a single shared
+ <literal>Configuration</literal> instance. More precisely, typically
+ you have one <literal>Configuration</literal> instance per
+ independently developed component that internally uses FreeMarker, so
+ they can be configured independently of each other. For example, your
+ e-mail sender component and your report generator component (service)
+ probably want to use their own <literal>Configuration</literal>-s, as
+ their needs differ.</para>
+
+ <para>As the behavior of templates depends on the configuration
+ settings, each <literal>Template</literal> instance has an associated
+ <literal>Configuration</literal> instance. If you obtain the
+ <literal>Template</literal> instances with
+ <literal>Configuration.getTemplate</literal>, the associated
+ <literal>Configuration</literal> instance will be the one whose
+ <literal>getTemplate</literal> method was called. If you create the
+ <literal>Template</literal> instances directly with the
+ <literal>Template</literal> constructor, the
+ <literal>Configuration</literal> should be specified as constructor
+ parameter.</para>
+ </section>
+
+ <section xml:id="pgui_config_sharedvariables">
+ <title>Shared variables</title>
+
+ <indexterm>
+ <primary>shared variable</primary>
+ </indexterm>
+
+ <para><emphasis role="term">Shared variables</emphasis> are variables
+ that are defined for all templates. You can add shared variables to
+ the configuration with the <literal>setSharedVariable</literal>
+ methods:</para>
+
+ <programlisting role="unspecified">Configuration cfg = new Configuration(Configuration.VERSION_2_3_27);
+<replaceable>..</replaceable>.
+cfg.setSharedVariable("warp", new WarpDirective());
+cfg.setSharedVariable("company", "Foo Inc.");</programlisting>
+
+ <para>In all templates that use this configuration, an user-defined
+ directive with name <literal>wrap</literal> and a string with name
+ <literal>company</literal> will be visible in the data-model root, so
+ you don't have to add them to the root hash again and again. A
+ variable in the root object that you pass to the
+ <literal>Template.process</literal> will hide the shared variable with
+ the same name.</para>
+
+ <warning>
+ <para>Never use <literal>TemplateModel</literal> implementation that
+ is not <link linkend="gloss.threadSafe">thread-safe</link> for
+ shared variables, if the configuration is used by multiple threads!
+ This is the typical situation for Servlet based applications.</para>
+ </warning>
+
+ <para>Due to backward compatibility heritage, the set of shared
+ variables is initially (i.e., for a new
+ <literal>Configuration</literal> instance) not empty. It contains the
+ following user-defined directives (they are "user-defined" in the
+ sense that you use <literal>@</literal> to call them instead of
+ <literal>#</literal>):</para>
+
+ <informaltable border="1">
+ <thead>
+ <tr>
+ <th>name</th>
+
+ <th>class</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <tr>
+ <td><literal>capture_output</literal></td>
+
+ <td><literal>freemarker.template.utility.CaptureOutput</literal></td>
+ </tr>
+
+ <tr>
+ <td><literal>compress</literal></td>
+
+ <td><literal>freemarker.template.utility.StandardCompress</literal></td>
+ </tr>
+
+ <tr>
+ <td><literal>html_escape</literal></td>
+
+ <td><literal>freemarker.template.utility.HtmlEscape</literal></td>
+ </tr>
+
+ <tr>
+ <td><literal>normalize_newlines</literal></td>
+
+ <td><literal>freemarker.template.utility.NormalizeNewlines</literal></td>
+ </tr>
+
+ <tr>
+ <td><literal>xml_escape</literal></td>
+
+ <td><literal>freemarker.template.utility.XmlEscape</literal></td>
+ </tr>
+ </tbody>
+ </informaltable>
+ </section>
+
+ <section xml:id="pgui_config_settings">
+ <title>Settings</title>
+
+ <indexterm>
+ <primary>setting</primary>
+ </indexterm>
+
+ <para><emphasis role="term">Settings</emphasis> are named values that
+ influence the behavior of FreeMarker. Examples of settings are:
+ <literal>locale</literal>, <literal>number_format</literal>,
+ <literal>default_encoding</literal>,
+ <literal>template_exception_handler</literal>. The full list of
+ settings can be found in the <olink
+ targetdoc="apiConfigurationSettings">Java API documentation of
+ <literal>Configuration.setSetting(...)</literal></olink>.</para>
+
+ <para>The settings coming from the <literal>Configuration</literal>
+ can be overridden in a <literal>Template</literal> instance. For
+ example, if you set the <literal>locale</literal> setting to
+ <literal>"en_US"</literal> in the configuration, then the
+ <literal>locale</literal> in all templates that use this configuration
+ will be <literal>"en_US"</literal>, except in templates where the
+ <literal>locale</literal> was explicitly specified differently (see
+ <link linkend="ref_directive_include_localized">localization</link>).
+ Thus, the setting values in the <literal>Configuration</literal> serve
+ as defaults that can be overridden in a per template manner. The value
+ coming from the <literal>Configuration</literal> instance or
+ <literal>Template</literal> instance can be further overridden for a
+ single <literal>Template.process</literal> call. For each such call a
+ <literal>freemarker.core.Environment</literal> object is created
+ internally that holds the runtime environment of the template
+ processing, including the setting values that were overridden on that
+ level. The values stored there can even be changed during the template
+ processing, so a template can set settings itself, like switching
+ <literal>locale</literal> at the middle of the ongoing
+ processing.</para>
+
+ <para>This can be imagined as 3 layers
+ (<literal>Configuration</literal>, <literal>Template</literal>,
+ <literal>Environment</literal>) of settings, where the topmost layer
+ that contains the value for a certain setting provides the effective
+ value of that setting. For example (settings A to F are just imaginary
+ settings for this example):</para>
+
+ <informaltable border="1">
+ <col align="left"/>
+
+ <col align="center" span="6"/>
+
+ <thead>
+ <tr>
+ <th/>
+
+ <th>Setting A</th>
+
+ <th>Setting B</th>
+
+ <th>Setting C</th>
+
+ <th>Setting D</th>
+
+ <th>Setting E</th>
+
+ <th>Setting F</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <tr>
+ <td>Layer 3: <literal>Environment</literal></td>
+
+ <td>1</td>
+
+ <td>-</td>
+
+ <td>-</td>
+
+ <td>1</td>
+
+ <td>-</td>
+
+ <td>-</td>
+ </tr>
+
+ <tr>
+ <td>Layer 2: <literal>Template</literal></td>
+
+ <td>2</td>
+
+ <td>2</td>
+
+ <td>-</td>
+
+ <td>-</td>
+
+ <td>2</td>
+
+ <td>-</td>
+ </tr>
+
+ <tr>
+ <td>Layer 1: <literal>Configuration</literal></td>
+
+ <td>3</td>
+
+ <td>3</td>
+
+ <td>3</td>
+
+ <td>3</td>
+
+ <td>-</td>
+
+ <td>-</td>
+ </tr>
+ </tbody>
+ </informaltable>
+
+ <para>The effective value of settings will be: A = 1, B = 2, C = 3, D
+ = 1, E = 2. The F setting is probably <literal>null</literal>, or it
+ throws exception when you try to get it.</para>
+
+ <para>Let's see exactly how to set settings:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>Configuration</literal> layer: In principle you set
+ the settings with the setter methods of the
+ <literal>Configuration</literal> object, fore example:</para>
+
+ <programlisting role="unspecified">Configuration myCfg = new Configuration(Configuration.VERSION_2_3_27);
+myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+myCfg.setDefaultEncoding("UTF-8");
+DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_27);
+owb.setForceLegacyNonListCollections(false);
+owb.setDefaultDateType(TemplateDateModel.DATETIME);
+myCfg.setObjectWrapper(owb.build());</programlisting>
+
+ <para>You do this before you start to actually use the
+ <literal>Configuration</literal> object (typically, when you
+ initialize the application); you should treat the object as
+ read-only after that.</para>
+
+ <para>In practice, in most frameworks you have to specify the
+ settings in some kind of framework-specific configuration file
+ that require specifying settings as <literal>String</literal>
+ name-value pairs (like in a <literal>.properties</literal> file).
+ In that case the authors of the frameworks most probably use the
+ <literal>Confguration.setSetting(String name, String
+ value)</literal> method; see available setting names and the
+ format of the values in the <link
+ xlink:href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setSetting-java.lang.String-java.lang.String-">API
+ documentation of <literal>setSetting</literal></link>. Example for
+ Spring Framework:</para>
+
+ <programlisting role="unspecified"><bean id="freemarkerConfig"
+ class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
+ <property name="freemarkerSettings">
+ <props>
+ <prop key="incompatible_improvements">2.3.27</prop>
+ <prop key="template_exception_handler">rethrow</prop>
+ <prop key="default_encoding">UTF-8</prop>
+ <prop key="object_wrapper">
+ DefaultObjectWrapper(
+ 2.3.27,
+ forceLegacyNonListCollections = false,
+ defaultDateType = freemarker.template.TemplateDateModel.DATETIME)
+ </prop>
+ </props>
+ </property>
+</bean></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"><#setting locale="it_IT">
+<#setting number_format="0.####"></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><#<replaceable>...</replaceable>></literal> or
+ <literal><@<replaceable>...</replaceable>></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><@<replaceable>exp</replaceable>
+ <replaceable>...</replaceable>></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<#if badVar>Foo</#if>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><#if badVar></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<#if "foo${badVar}" == "foobar">Foo</#if>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
+<#if true>
+ Foo
+ ${badVar}
+ Bar
+</#if>
+c</programlisting>
+
+ <para>or in the macro definition body:</para>
+
+ <programlisting role="template">a
+<@test />
+b
+<#macro test>
+ Foo
+ ${badVar}
+ Bar
+</#macro></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"><p>Output format: ${.output_format}
+<p>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><#setting
+ number_format="@smart"></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<String, TemplateNumberFormatFactory> customNumberFormats = ...;
+...
+customNumberFormats.put("hex", HexTemplateNumberFormatFactory.INSTANCE);
+...
+cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
+
+ <para>Now we can use this format in templates:</para>
+
+ <programlisting role="template">${x?string.@hex}</programlisting>
+
+ <para>or even set it as the default number format:</para>
+
+ <programlisting role="unspecified">cfg.setNumberFormat("@hex");</programlisting>
+ </section>
+
+ <section xml:id="pgui_config_custom_formats_ex_cust_algo_advanced">
+ <title>Advanced custom number format example</title>
+
+ <para>This is a more complex custom number format that shows how to
+ deal with parameters in the format string, also how to delegate to
+ another format:</para>
+
+ <programlisting role="unspecified">package com.example;
+
+import java.util.Locale;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+import freemarker.template.utility.NumberUtil;
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Shows a number in base N number system. Can only format numbers that fit into an {@code int},
+ * however, optionally you can specify a fallback format. This format has one required parameter,
+ * the numerical system base. That can be optionally followed by "|" and a fallback format.
+ */
+public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+ public static final BaseNTemplateNumberFormatFactory INSTANCE
+ = new BaseNTemplateNumberFormatFactory();
+
+ private BaseNTemplateNumberFormatFactory() {
+ // Defined to decrease visibility
+ }
+
+ @Override
+ public TemplateNumberFormat get(String params, Locale locale, Environment env)
+ throws InvalidFormatParametersException {
+ TemplateNumberFormat fallbackFormat;
+ {
+ int barIdx = params.indexOf('|');
+ if (barIdx != -1) {
+ String fallbackFormatStr = params.substring(barIdx + 1);
+ params = params.substring(0, barIdx);
+ try {
+ fallbackFormat = env.getTemplateNumberFormat(fallbackFormatStr, locale);
+ } catch (TemplateValueFormatException e) {
+ throw new InvalidFormatParametersException(
+ "Couldn't get the fallback number format (specified after the \"|\"), "
+ + StringUtil.jQuote(fallbackFormatStr) + ". Reason: " + e.getMessage(),
+ e);
+ }
+ } else {
+ fallbackFormat = null;
+ }
+ }
+
+ int base;
+ try {
+ base = Integer.parseInt(params);
+ } catch (NumberFormatException e) {
+ if (params.length() == 0) {
+ throw new InvalidFormatParametersException(
... 33954 lines suppressed ...