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 2015/12/30 19:11:21 UTC

[01/35] incubator-freemarker git commit: Made place for the Chinese manual.

Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3 ad73f5f4a -> f0695c39a


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen-help/editors-readme.txt
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen-help/editors-readme.txt b/src/manual/en_US/docgen-help/editors-readme.txt
new file mode 100644
index 0000000..5280d97
--- /dev/null
+++ b/src/manual/en_US/docgen-help/editors-readme.txt
@@ -0,0 +1,105 @@
+Guide to FreeMarker Manual for Editors
+======================================
+
+Non-technical
+-------------
+
+- The Template Author's Guide is for Web designers. Assume that a
+  designer is not a programmer, (s)he doesn't even know what is Java.
+  Forget that FM is implemented in Java when you edit the Template
+  Author's Guide. Try to avoid technical writing.
+
+- In the Guide chapters, be careful not to mention things that were
+  not explained earlier. The Guide chapters should be understandable
+  if you read them continuously.
+
+- If you add a new topic or term, don't forget to add it to the Index.
+  Also, consider adding entries for it to the Glossary.
+
+- Don't use too sophisticated English. Use basic words and grammar.
+
+
+Technical
+---------
+
+- For the editing use XXE (XMLmind XML Editor), with its default XML
+  *source* formatting settings (identation, max line length and like).
+  You should install the "DocBook 5 for Freemarker" addon, which you can
+  find inside the "docgen" top-level SVN module.
+
+- The HTML is generated with Docgen (docgen.jar), which will check some
+  of the rules described here. To invoke it, issue "ant manual" from
+  the root of the "freemarker" module. (Note: you may need to check out
+  and build "docgen" first.)
+
+- Understand all document conventions in the Preface chapter. Note that
+  all "programlisting"-s should have a "role" attribute with a value that
+  is either: "template", "dataModel", "output", "metaTemplate" or
+  "unspecified". (If you miss this, the XXE addon will show the
+  "programlisting" in red.)
+
+- Verbatim content in flow text:
+
+  * In flow text, all data object names, class names, FTL fragments,
+    HTML fragments, and all other verbatim content is inside "literal"
+    element.
+
+  * Use replaceable element inside literal element for replaceable
+    parts and meta-variables like:
+    <literal&lt;if <replaceable>condition</replaceable>></literal>
+    <literal><replaceable>templateDir</replaceable>/copyright.ftl</literal>
+
+- Hierarchy:
+
+  * The hierarchy should look like:
+
+      book -> part -> chapter -> section -> section -> section -> section
+
+    where the "part" and the "section"-s are optional.
+    Instead of chapter you may have "preface" or "appendix".
+
+  * Don't use "sect1", "sect2", etc. Instead nest "section"-s into each other,
+    but not deeper than 3 levels.
+
+  * Use "simplesect" if you want to divide up something visually, but
+    you don't want those sections to appear in the ToC, or go into their own
+    HTML page. "simplesect"-s can appear under all "section" nesting
+    levels, and they always look the same regardless of the "section"
+    nesting levels.
+
+- Lists:
+
+  * When you have list where the list items are short (a few words),
+    you should give spacing="compact" to the "itemizedlist" or
+    "orderedlist" element.
+
+  * Don't putting listings inside "para"-s. Put them between "para"-s instead.
+
+- Xrefs, id-s, links:
+
+  * id-s of parts, chapters, sections and similar elements must
+    contain US-ASCII lower case letters, US-ASCII numbers, and
+    underscore only. id-s of parts and chapters are used as the
+    filenames of HTML-s generated for that block.
+    When you find out the id, deduce it from the position in the ToC
+    hierarchy. The underscore is used as the separator between the path
+    steps.
+
+  * All other id-s must use prefix:
+    - example: E.g.: id="example.foreach"
+    - ref: Reference information...
+      * directive: about a directive. E.g.: "ref.directive.foreach"
+      * builtin
+    - gloss: Term in the Glossary
+    - topic: The recommended point of document in a certain topic
+      * designer: for designers.
+          E.g.: id="topic.designer.methodDataObject"
+      * programmer: for programmers
+      * or omit the secondary category if it is for everybody
+    - misc: Anything doesn't fit in the above categories
+
+  * When you refer to a part, chapter or section, often you should use
+    xref, not link. The xreflabel attribute of the link-end should not be set;
+    then it's deduced from the titles.
+
+- The "book" element must have this attribute: conformance="docgen"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen-misc/googleAnalytics.html
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen-misc/googleAnalytics.html b/src/manual/en_US/docgen-misc/googleAnalytics.html
new file mode 100644
index 0000000..bf440f2
--- /dev/null
+++ b/src/manual/en_US/docgen-misc/googleAnalytics.html
@@ -0,0 +1,9 @@
+<script>
+  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+  ga('create', 'UA-55420501-1', 'auto');
+  ga('send', 'pageview');
+</script>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen-originals/figures/model2sketch_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen-originals/figures/model2sketch_with_alpha.png b/src/manual/en_US/docgen-originals/figures/model2sketch_with_alpha.png
new file mode 100644
index 0000000..ce120cc
Binary files /dev/null and b/src/manual/en_US/docgen-originals/figures/model2sketch_with_alpha.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen-originals/figures/odg-convert-howto.txt
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen-originals/figures/odg-convert-howto.txt b/src/manual/en_US/docgen-originals/figures/odg-convert-howto.txt
new file mode 100644
index 0000000..1db294c
--- /dev/null
+++ b/src/manual/en_US/docgen-originals/figures/odg-convert-howto.txt
@@ -0,0 +1,24 @@
+Converting to SVG:
+1. Open the ODG file with Libeoffice/OpenOffice Draw
+2. Ctrl+A to select all objects
+3. File/Export..., chose SVG format, and then tick "Selection"
+4. Check the result. If contour lines at the right and bottom edge of the
+   figure are partically clipped (stroke width is halved), set a stroke with
+   other than 0 for all shapes.
+   
+Converting to a decent quality (though non-transparent) PNG:
+1. Open the ODG file with Libeoffice/OpenOffice Draw
+2. Export to PDF
+3. Open PDF in Adobe Acrobat Reader
+4. Go to Adobe Acrobat Reader preferences and set it to not use subpixel
+   anti-aliasing, just normal anti-aliasing. They used to call this LCD vs
+   Monitor mode.
+5. Zoom in/out until you get the desired size in pixels, take a
+   screen shot, crop it in some image editor, save it as PNG.
+   
+Converting to transparent but somewhat ugly PNG:
+1. Convert to SVG as described earlier
+2. Use Apache Batik Rasterizer command line utility like:
+   $BARIK_INSTALLATION\batik-rasterizer-1.8.jar -dpi 72 -m image/png ${FIGURE}.svg
+   If Batik fails (as it doesn't support all SVG features), use Inkscape.
+   Of course avoid supixel anti-aliasing, as it's not device independent.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen-originals/figures/overview.odg
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen-originals/figures/overview.odg b/src/manual/en_US/docgen-originals/figures/overview.odg
new file mode 100644
index 0000000..0533b7c
Binary files /dev/null and b/src/manual/en_US/docgen-originals/figures/overview.odg differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen-originals/figures/tree_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen-originals/figures/tree_with_alpha.png b/src/manual/en_US/docgen-originals/figures/tree_with_alpha.png
new file mode 100644
index 0000000..dc4fba8
Binary files /dev/null and b/src/manual/en_US/docgen-originals/figures/tree_with_alpha.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/docgen.cjson
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen.cjson b/src/manual/en_US/docgen.cjson
new file mode 100644
index 0000000..221f349
--- /dev/null
+++ b/src/manual/en_US/docgen.cjson
@@ -0,0 +1,112 @@
+//charset: UTF-8
+
+deployUrl: "http://freemarker.org/docs/"
+onlineTrackerHTML: "docgen-misc/googleAnalytics.html"
+searchKey: "014728049242975963158:8awjt03uofm"
+validation: {
+  programlistingsRequireRole
+  // programlistingsRequireLanguage
+  maximumProgramlistingWidth: 100
+}
+showXXELogo
+generateEclipseTOC
+// eclipse: {
+//  link_to: "freemarker-toc.xml#ManualLink"
+// }
+
+removeNodesWhenOnline: [ "preface" ]
+
+copyrightHolder: "The FreeMarker Project"
+copyrightStartYear: 1999
+
+seoMeta: {
+  "dgui_quickstart": {
+    "title": "Getting Started with template writing"
+  }
+  "pgui_quickstart": {
+    "title": "Getting Started with the Java API"
+  }
+}
+
+logo: {
+  href: "http://freemarker.org"
+  src: logo.png,
+  alt: "FreeMarker"
+}
+
+olinks: {
+  homepage: "http://freemarker.org/"
+  api: "api/index.html"
+  
+  // Homepage links:
+  freemarkerdownload: "http://freemarker.org/freemarkerdownload.html"
+  contribute: "http://freemarker.org/contribute.html"
+  history: "http://freemarker.org/history.html"
+  what-is-freemarker: "id:preface"
+  mailing-lists: "http://freemarker.org/mailing-lists.html"
+  
+  // External URL-s:
+  onlineTemplateTester: "http://freemarker-online.kenshoo.com/"
+  twitter: "https://twitter.com/freemarker"
+  sourceforgeProject: "https://sourceforge.net/projects/freemarker/"
+  githubProject: "https://github.com/freemarker/freemarker"
+  newBugReport: "https://sourceforge.net/p/freemarker/bugs/new/"
+  newStackOverflowQuestion: "http://stackoverflow.com/questions/ask?tags=freemarker"
+}
+
+internalBookmarks: {
+  "Alpha. index": alphaidx
+  "Glossary": gloss
+  "Expressions": exp_cheatsheet
+  "?builtins": ref_builtins_alphaidx
+  "#directives": ref_directive_alphaidx
+  ".spec_vars": ref_specvar
+  "FAQ": app_faq
+}
+
+tabs: {
+  "Home": "olink:homepage"
+  "Manual": ""  // Empty => We are here
+  "Java API": "olink:api"
+}
+
+// Available icons:
+// .icon-heart
+// .icon-bug
+// .icon-download
+// .icon-star
+secondaryTabs: {
+  "Contribute": { class: "icon-heart", href: "olink:contribute" }
+  "Report a Bug": { class: "icon-bug", href: "olink:newBugReport" }
+  "Download": { class: "icon-download", href: "olink:freemarkerdownload" }
+}
+
+footerSiteMap: {
+  "Overview": {
+    "What is FreeMarker?": "olink:what-is-freemarker"
+    "Download": "olink:freemarkerdownload"
+    "Version history": "id:app_versions"
+    "About us": "olink:history"
+    "License": "id:app_license"
+  }
+  "Handy stuff": {
+    "Try template online": "olink:onlineTemplateTester"
+    "Expressions cheatsheet": "id:exp_cheatsheet"
+    "#directives": "id:ref_directive_alphaidx"
+    "?built_ins": "id:ref_builtins_alphaidx"
+    ".special_vars": "id:ref_specvar"
+  }
+  "Community": {
+    "FreeMarker on Github": "olink:githubProject"
+    "Follow us on Twitter": "olink:twitter"
+    "Report a bug": "olink:newBugReport"
+    "Ask a question": "olink:newStackOverflowQuestion"
+    "Mailing lists": "olink:mailing-lists"
+  }
+}
+
+socialLinks: {
+  "Github": { class: "github", href: "olink:githubProject" }
+  "Twitter": { class: "twitter", href: "olink:twitter" }
+  "Stack Overflow": { class: "stack-overflow", href: "olink:newStackOverflowQuestion" }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/favicon.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/favicon.png b/src/manual/en_US/favicon.png
new file mode 100644
index 0000000..ce0de20
Binary files /dev/null and b/src/manual/en_US/favicon.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/figures/model2sketch.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/figures/model2sketch.png b/src/manual/en_US/figures/model2sketch.png
new file mode 100644
index 0000000..93f9a6b
Binary files /dev/null and b/src/manual/en_US/figures/model2sketch.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/figures/overview.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/figures/overview.png b/src/manual/en_US/figures/overview.png
new file mode 100644
index 0000000..b32e0bd
Binary files /dev/null and b/src/manual/en_US/figures/overview.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/figures/tree.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/figures/tree.png b/src/manual/en_US/figures/tree.png
new file mode 100644
index 0000000..dcd9bf3
Binary files /dev/null and b/src/manual/en_US/figures/tree.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/logo.png
----------------------------------------------------------------------
diff --git a/src/manual/en_US/logo.png b/src/manual/en_US/logo.png
new file mode 100644
index 0000000..193dc11
Binary files /dev/null and b/src/manual/en_US/logo.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/favicon.png
----------------------------------------------------------------------
diff --git a/src/manual/favicon.png b/src/manual/favicon.png
deleted file mode 100644
index ce0de20..0000000
Binary files a/src/manual/favicon.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/figures/model2sketch.png
----------------------------------------------------------------------
diff --git a/src/manual/figures/model2sketch.png b/src/manual/figures/model2sketch.png
deleted file mode 100644
index 93f9a6b..0000000
Binary files a/src/manual/figures/model2sketch.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/figures/overview.png
----------------------------------------------------------------------
diff --git a/src/manual/figures/overview.png b/src/manual/figures/overview.png
deleted file mode 100644
index b32e0bd..0000000
Binary files a/src/manual/figures/overview.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/figures/tree.png
----------------------------------------------------------------------
diff --git a/src/manual/figures/tree.png b/src/manual/figures/tree.png
deleted file mode 100644
index dcd9bf3..0000000
Binary files a/src/manual/figures/tree.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/logo.png
----------------------------------------------------------------------
diff --git a/src/manual/logo.png b/src/manual/logo.png
deleted file mode 100644
index 193dc11..0000000
Binary files a/src/manual/logo.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/zh_CN/placeholder.txt
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/placeholder.txt b/src/manual/zh_CN/placeholder.txt
new file mode 100644
index 0000000..a83feff
--- /dev/null
+++ b/src/manual/zh_CN/placeholder.txt
@@ -0,0 +1,5 @@
+Add the Chinese Manual here, then delete this file.
+You can use these to test if the Manual is generated succesfully:
+
+  ant manualOffline_zh_CN
+  ant manualFreemarkerOrg_zh_CN


[02/35] incubator-freemarker git commit: Made place for the Chinese manual.

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
new file mode 100644
index 0000000..c561322
--- /dev/null
+++ b/src/manual/en_US/book.xml
@@ -0,0 +1,37479 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<book conformance="docgen" version="5.0" xml:lang="en"
+      xmlns="http://docbook.org/ns/docbook"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      xmlns:ns5="http://www.w3.org/1999/xhtml"
+      xmlns:ns4="http://www.w3.org/2000/svg"
+      xmlns:ns3="http://www.w3.org/1998/Math/MathML"
+      xmlns:ns="http://docbook.org/ns/docbook">
+  <info>
+    <title>FreeMarker Manual</title>
+
+    <titleabbrev>Manual</titleabbrev>
+
+    <productname>Freemarker 2.3.24 Preview 1</productname>
+  </info>
+
+  <preface role="index.html" xml:id="preface">
+    <title>What is FreeMarker?</title>
+
+    <para>FreeMarker is a <emphasis>template engine</emphasis>: a generic tool
+    to generate text output (HTML web pages, e-mails, configuration files,
+    source code, etc.) based on templates and changing data. It's not an
+    application for end-users in itself, but a Java library, a component that
+    programmers can embed into their products.</para>
+
+    <para>Templates are written in the FreeMarker Template Language (FTL).
+    It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
+    programming language like PHP. You meant to prepare the data to display in
+    a real programming language, like issue database queries and do business
+    calculations, and then the template displays that already prepared data.
+    In the template you are focusing on how to present the data, and outside
+    the template you are focusing on what data to present.</para>
+
+    <mediaobject>
+      <imageobject>
+        <imagedata fileref="figures/overview.png"/>
+      </imageobject>
+    </mediaobject>
+
+    <para>This approach is often referred to as the <link
+    linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
+    particularly popular for dynamic Web pages. It helps in separating the Web
+    page designers (HTML authors) from the developers (Java programmers
+    usually). Designers won't face complicated logic in templates, and can
+    change the appearance of a page without programmers having to change or
+    recompile code.</para>
+
+    <para>While FreeMarker was originally created for generating HTML pages in
+    MVC web application frameworks, it isn't bound to servlets or HTML or
+    anything Web-related. It's used in non-web application environments as
+    well.</para>
+
+    <para>FreeMarker is <link
+    xlink:href="http://www.fsf.org/philosophy/free-sw.html">Free</link>,
+    released under the Apache License, Version 2.0.</para>
+  </preface>
+
+  <part xml:id="dgui">
+    <title>Template Author's Guide</title>
+
+    <chapter xml:id="dgui_quickstart">
+      <title>Getting Started</title>
+
+      <para>This chapter is a very rough introduction to FreeMarker. The
+      chapters after this will go over things in much greater detail.
+      Nonetheless, once you have read this chapter, you will be able to write
+      simple but useful FreeMarker templates.</para>
+
+      <section xml:id="dgui_quickstart_basics">
+        <title>Template + data-model = output</title>
+
+        <para>Let's assume that you need a HTML page in a Web shop, similar to
+        this:</para>
+
+        <programlisting role="output">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome <emphasis>John Doe</emphasis>!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="<emphasis>products/greenmouse.html</emphasis>"&gt;<emphasis>green mouse</emphasis>&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+        <para>But the user name ("John Doe" above) should depend on who the
+        logged in Web page visitor is, and the latest product should come from
+        a database and thus it potentially changes too. Thus you can't enter
+        these into the HTML directly, you can't use static HTML. Instead, you
+        can use a <emphasis role="term">template</emphasis> of the desired
+        output. The template is the same as the static HTML would be, except
+        that it contains some instructions to FreeMarker that makes it
+        dynamic:</para>
+
+        <programlisting role="template" xml:id="example.first">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome <emphasis>${user}</emphasis>!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="<emphasis>${latestProduct.url}</emphasis>"&gt;<emphasis>${latestProduct.name}</emphasis>&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+        <para>The template is stored on the Web server, usually just like the
+        static HTML page would be. But whenever someone visits this page,
+        FreeMarker will step in and transform the template on-the-fly to plain
+        HTML by replacing the
+        <literal>${<replaceable>...</replaceable>}</literal>-s with up-to-date
+        content, and send the result to the visitor's Web browser. So the
+        visitor's Web browser will receive something like the first example
+        HTML (i.e., plain HTML without FreeMarker instructions), and it will
+        not perceive that FreeMarker is used on the server. (Of course, the
+        template file stored on the Web server is not changed by this; the
+        substitutions only appear in the Web server's response.)</para>
+
+        <para>Note that the template doesn't contain the programming logic to
+        find out who the current visitor is, or to query the database to get
+        the latest product. The data to be displayed is prepared outside
+        FreeMarker, usually by parts written in some <quote>real</quote>
+        programming language like Java. The template author needn't know how
+        these values were calculated. In fact, the way these values are
+        calculated can be completely changed while the templates can remain
+        exactly the same, and also, the look of the page can be completely
+        changed without touching anything but the template. This separation of
+        presentation logic and business logic can be especially useful when
+        the template authors (designers) and the programmers are different
+        individuals, but also helps managing application complexity if they
+        are the same person. Keeping templates focused on presentation issues
+        (visual design, layout and formatting) is a key for using template
+        engines like FreeMarker efficiently.</para>
+
+        <para><indexterm>
+            <primary>data-model</primary>
+          </indexterm>The totality of data that was prepared for the template
+        is called the <emphasis role="term">data-model</emphasis>. As far as
+        the template author is concerned, the data-model is a tree-like
+        structure (like folders and files on your hard disk), which, in this
+        case, could be visualized as:</para>
+
+        <programlisting role="dataModel">(root)
+  |
+  +- <emphasis>user</emphasis> = "Big Joe"
+  |
+  +- <emphasis>latestProduct</emphasis>
+      |
+      +- <emphasis>url</emphasis> = "products/greenmouse.html"
+      |
+      +- <emphasis>name</emphasis> = "green mouse"</programlisting>
+
+        <note>
+          <para>The above is just a visualization; the data-model is not in a
+          textual format, it's from Java objects. For the Java programmers,
+          the root is perhaps a Java object with <literal>getUser()</literal>
+          and <literal>getLatestProduct()</literal> methods, or maybe a Java
+          <literal>Map</literal> with <literal>"user"</literal> and
+          <literal>"latestProducts"</literal> keys. Similarly,
+          <literal>latestProduct</literal> is perhaps a Java Object with
+          <literal>getUrl()</literal> and <literal>getName()</literal>
+          methods.</para>
+        </note>
+
+        <para>Earlier, you have picked values from this data-model, with the
+        <literal>user</literal> and <literal>latestProduct.name</literal>
+        expressions. If we go on with the analogy that the data model is like
+        a file system, then <quote>(root)</quote> and
+        <literal>latestProduct</literal> correspond to directories (folders),
+        and <literal>user</literal>, <literal>url</literal> and
+        <literal>name</literal> are files in those directories.</para>
+
+        <para>To recapitulate, a template and a data-model is needed for
+        FreeMarker to generate the output (like the HTML shown first):</para>
+
+        <para><phrase role="markedTemplate">Template</phrase> + <phrase
+        role="markedDataModel">data-model</phrase> = <phrase
+        role="markedOutput">output</phrase></para>
+      </section>
+
+      <section xml:id="dgui_quickstart_datamodel">
+        <title>The data-model at a glance</title>
+
+        <para>As you have seen, the data-model is basically a tree. This tree
+        can be arbitrarily complicated and deep, for example:</para>
+
+        <programlisting role="dataModel"
+                        xml:id="example.qStart.dataModelWithHashes">(root)
+  |
+  +- animals
+  |   |
+  |   +- mouse
+  |   |   |   
+  |   |   +- size = "small"
+  |   |   |   
+  |   |   +- price = 50
+  |   |
+  |   +- elephant
+  |   |   |   
+  |   |   +- size = "large"
+  |   |   |   
+  |   |   +- price = 5000
+  |   |
+  |   +- python
+  |       |   
+  |       +- size = "medium"
+  |       |   
+  |       +- price = 4999
+  |
+  +- message = "It is a test"
+  |
+  +- misc
+      |
+      +- foo = "Something"</programlisting>
+
+        <para>The variables that act like directories (the root,
+        <literal>animals</literal>, <literal>mouse</literal>,
+        <literal>elephant</literal>, <literal>python</literal>,
+        <literal>misc</literal>) are called <emphasis
+        role="term">hashes</emphasis>. Hashes store other variables (the so
+        called <anchor xml:id="topic.dataModel.subVar"/><emphasis>sub
+        variables</emphasis>) by a lookup name (e.g., <quote>animals</quote>,
+        <quote>mouse</quote> or <quote>price</quote>).</para>
+
+        <para>The variables that store a single value
+        (<literal>size</literal>, <literal>price</literal>,
+        <literal>message</literal> and <literal>foo</literal>) are called
+        <emphasis role="term">scalars</emphasis>.</para>
+
+        <para><anchor xml:id="topic.qStart.accessVariables"/>When you want to
+        use a subvariable in a template, you specify its path from the root,
+        and separate the steps with dots. To access the
+        <literal>price</literal> of a <literal>mouse</literal>, you start from
+        the root and go into <literal>animals</literal>, and then go into
+        <literal>mouse</literal> then go into <literal>price</literal>. So you
+        write <literal>animals.mouse.price</literal>.</para>
+
+        <para>Another important kind of variables are <emphasis
+        role="term">sequences</emphasis>. They store subvariables like hashes,
+        but here subvariables doesn't have a name, they are just items in a
+        list. For example, in this data-model, <literal>animals</literal> and
+        <literal>misc.fruits</literal> are sequences:</para>
+
+        <programlisting role="dataModel"
+                        xml:id="example.qStart.dataModelWithSequences">(root)
+  |
+  +- animals
+  |   |
+  |   +- (1st)
+  |   |   |
+  |   |   +- name = "mouse"
+  |   |   |
+  |   |   +- size = "small"
+  |   |   |
+  |   |   +- price = 50
+  |   |
+  |   +- (2nd)
+  |   |   |
+  |   |   +- name = "elephant"
+  |   |   |
+  |   |   +- size = "large"
+  |   |   |
+  |   |   +- price = 5000
+  |   |
+  |   +- (3rd)
+  |       |
+  |       +- name = "python"
+  |       |
+  |       +- size = "medium"
+  |       |
+  |       +- price = 4999
+  |
+  +- misc
+      |
+      +- fruits
+          |
+          +- (1st) = "orange"
+          |
+          +- (2nd) = "banana"</programlisting>
+
+        <para>To access a subvariable of a sequence you use a numerical index
+        in square brackets. Indexes start from 0 (it's a programmer tradition
+        to start with 0), thus the index of the 1st item is 0, the index of
+        the 2nd item is 1, and so on. So to get the name of the first animal
+        you write <literal>animals[0].name</literal>. To get the second item
+        in <literal>misc.fruits</literal> (the string
+        <literal>"banana"</literal>) you write
+        <literal>misc.fruits[1]</literal>. (In practice, you usually just walk
+        through sequences in order, not caring about the index, but that will
+        be <link linkend="topic.tutorial.list">shown later</link>.)</para>
+
+        <para>Scalars can be further divided into these categories:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>String: Text, that is, an arbitrary sequence of characters
+            such as ''m'', ''o'', ''u'', ''s'', ''e'' above. For example the
+            <literal>name</literal>-s and <literal>size</literal>-s are
+            strings above.</para>
+          </listitem>
+
+          <listitem>
+            <para>Number: It's a numerical value, like the
+            <literal>price</literal>-s above. The string
+            <literal>"50"</literal> and the number <literal>50</literal> are
+            two totally different things in FreeMarker. The former is just a
+            sequence of two characters (which happens to be readable as a
+            number for humans), while the latter is a numerical value that you
+            can use in arithmetical calculations.</para>
+          </listitem>
+
+          <listitem>
+            <para>Date-like: Either a date-time (stores a date with time of
+            the day), or a date (no time of day), or a time (time of day, no
+            date).</para>
+          </listitem>
+
+          <listitem>
+            <para>Boolean: A true/false (yes/no, on/off, etc.) thing. Like
+            animals could have a <literal>protected</literal> subvariable,
+            which store if the animal is protected or not.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Summary:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>The data-model can be visualized as a tree.</para>
+          </listitem>
+
+          <listitem>
+            <para>Scalars store a single value. The value can be a string or a
+            number or a date-time/date/time or a boolean.</para>
+          </listitem>
+
+          <listitem>
+            <para>Hashes are containers that store other variables and
+            associate them with a unique lookup name.</para>
+          </listitem>
+
+          <listitem>
+            <para>Sequences are containers that store other variables in an
+            ordered sequence. The stored variables can be retrieved via their
+            numerical index, starting from 0.</para>
+          </listitem>
+        </itemizedlist>
+
+        <note>
+          <para>There are other, more advanced value types that we don't cover
+          here, such as methods and directives.</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_quickstart_template">
+        <title>The template at a glance</title>
+
+        <para>The simplest template is a plain HTML file (or whatever text
+        file; FreeMarker is not confined to HTML). When the client visits that
+        page, FreeMarker will send that HTML to the client as is. However if
+        you want that page to be more dynamic then you begin to put special
+        parts into the HTML which will be understood by FreeMarker:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><literal>${<replaceable>...</replaceable>}</literal>:
+            FreeMarker will replace it in the output with the actual value of
+            the expression inside the curly brackets. They are called
+            <emphasis role="term">interpolation</emphasis>s.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">FTL tags</emphasis> (for FreeMarker
+            Template Language tags): FTL tags are a bit similar to HTML tags,
+            but they are instructions to FreeMarker and will not be printed to
+            the output. The name of these tags start with
+            <literal>#</literal>. (User-defined FTL tags use
+            <literal>@</literal> instead of <literal>#</literal>, but they are
+            an advanced topic.)</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Comments:</emphasis> Comments are
+            similar to HTML comments, but they are delimited by
+            <literal>&lt;#--</literal> and <literal>--&gt;</literal>. Unlike
+            HTML comments, FTL comments won't get into the output (won't be
+            visible in the page source for the visitor), because FreeMarker
+            skips them.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Anything not an FTL tag or an interpolation or comment is
+        considered as static text, and will not be interpreted by FreeMarker;
+        it is just printed to the output as is.</para>
+
+        <para>With FTL tags you refer to so-called <emphasis
+        role="term">directives</emphasis>. This is the same kind of
+        relationship as between HTML tags (e.g.:
+        <literal>&lt;table&gt;</literal> and
+        <literal>&lt;/table&gt;</literal>) and HTML elements (e.g., the
+        <literal>table</literal> element) to which you refer to with the HTML
+        tags. (If you don't feel this difference then just take "FTL tag" and
+        "directive" as synonyms.)</para>
+
+        <note>
+          <para>You can easily try writing templates on <link
+          xlink:href="http://freemarker-online.kenshoo.com/">http://freemarker-online.kenshoo.com/</link></para>
+        </note>
+
+        <section>
+          <title>Some basic directives</title>
+
+          <para>Here we will look at some of the most commonly used directives
+          (<link linkend="ref_directives">but there are much
+          more</link>).</para>
+
+          <section>
+            <title>The if directive</title>
+
+            <para>With the <literal>if</literal> directive you can
+            conditionally skip a section of the template. For example, assume
+            that in the <link linkend="example.first">very first
+            example</link> you want to greet your boss, Big Joe, differently
+            than other users:</para>
+
+            <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;
+    Welcome ${user}<emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>, our beloved leader<emphasis>&lt;/#if&gt;</emphasis>!
+  &lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>Here you have told FreeMarker that the <quote>, our beloved
+            leader</quote> should be there only if the value of the variable
+            <literal>user</literal> is equal to the string <literal>"Big
+            Joe"</literal>. In general, things between <literal>&lt;#if
+            <replaceable>condition</replaceable>&gt;</literal> and
+            <literal>&lt;/#if&gt;</literal> tags are skipped if
+            <literal><replaceable>condition</replaceable></literal> is false
+            (the boolean value).</para>
+
+            <para>Let's look at
+            <literal><replaceable>condition</replaceable></literal> more
+            closely: <literal>==</literal> is an operator that tests if the
+            values at its left and right side are equivalent, and the results
+            is a boolean value, true or false accordingly. On the left side of
+            <literal>==</literal> I have <link
+            linkend="topic.qStart.accessVariables">referenced a
+            variable</link> with the syntax that should be already familiar;
+            this will be replaced with the value of the variable. In general,
+            unquoted words inside directives or interpolations are treated as
+            references to variables. On the right side I have specified a
+            literal string. Literal strings in templates must
+            <emphasis>always</emphasis> be put inside quotation marks.</para>
+
+            <para>This will print <quote>Pythons are free today!</quote> if
+            their price is 0:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price == <emphasis>0</emphasis>&gt;
+  Pythons are free today!
+&lt;/#if&gt;</programlisting>
+
+            <para>Similarly as earlier when a string was specified directly,
+            here a number is specified directly (<literal>0</literal>). Note
+            that the number is <emphasis>not</emphasis> quoted. If you quoted
+            it (<literal>"0"</literal>), FreeMarker were misinterpret it as a
+            string literal, and because the price to compare it to is number,
+            you get an error.</para>
+
+            <para>This will print "Pythons are not free today!" if their price
+            is not 0:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price <emphasis>!=</emphasis> 0&gt;
+  Pythons are not free today!
+&lt;/#if&gt;</programlisting>
+
+            <para>As you probably guessed, <literal>!=</literal> means
+            <quote>not equals</quote>.</para>
+
+            <para>You can write things like this too (using <link
+            linkend="example.qStart.dataModelWithHashes">the data-model used
+            to demonstrate hashes</link>):</para>
+
+            <programlisting role="template">&lt;#if <emphasis>animals.python.price &lt; animals.elephant.price</emphasis>&gt;
+  Pythons are cheaper than elephants today.
+&lt;/#if&gt;</programlisting>
+
+            <para>With the <literal>&lt;#else&gt;</literal> tag you can
+            specify what to do if the condition is false. For example:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
+  Pythons are cheaper than elephants today.
+<emphasis>&lt;#else&gt;</emphasis>
+  Pythons are not cheaper than elephants today.
+&lt;/#if&gt;</programlisting>
+
+            <para>This prints <quote>Pythons are cheaper than elephants
+            today.</quote> if the price of python is less than the price of
+            elephant, or else it prints <quote>Pythons are not cheaper than
+            elephants today.</quote> You can refine this further by using
+            <literal>elseif</literal>:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
+  Pythons are cheaper than elephants today.
+<emphasis>&lt;#elseif animals.elephant.price &lt; animals.python.price&gt;</emphasis>
+  Elephants are cheaper than pythons today.
+&lt;#else&gt;
+  Elephants and pythons cost the same today.
+&lt;/#if&gt;</programlisting>
+
+            <para>If you have a variable with boolean value (a true/false
+            thing) then you can use it directly as the
+            <literal><replaceable>condition</replaceable></literal> of
+            <literal>if</literal>:</para>
+
+            <programlisting role="template">&lt;#if animals.python.protected&gt;
+  Pythons are protected animals!
+&lt;/#if&gt;</programlisting>
+          </section>
+
+          <section>
+            <title>The list directive</title>
+
+            <anchor xml:id="topic.tutorial.list"/>
+
+            <para>This is needed when you want to list something. For example
+            if you merge this template with the <link
+            linkend="example.qStart.dataModelWithSequences">data-model used
+            earlier to demonstrate sequences</link>:</para>
+
+            <programlisting role="template">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+  <emphasis>&lt;#list animals as animal&gt;</emphasis>
+    &lt;tr&gt;&lt;td&gt;${<emphasis>animal</emphasis>.name}&lt;td&gt;${<emphasis>animal</emphasis>.price} Euros
+  <emphasis>&lt;/#list&gt;</emphasis>
+&lt;/table&gt;</programlisting>
+
+            <para>then the output will be:</para>
+
+            <programlisting role="output">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+    <emphasis>&lt;tr&gt;&lt;td&gt;mouse&lt;td&gt;50 Euros
+    &lt;tr&gt;&lt;td&gt;elephant&lt;td&gt;5000 Euros
+    &lt;tr&gt;&lt;td&gt;python&lt;td&gt;4999 Euros</emphasis>
+&lt;/table&gt;</programlisting>
+
+            <para>The generic form of the <literal>list</literal> directive
+            is:<literal> &lt;#list <replaceable>sequence</replaceable> as
+            <replaceable>loopVariable</replaceable>&gt;<replaceable>repeatThis</replaceable>&lt;/#list&gt;</literal>.
+            The <literal><replaceable>repeatThis</replaceable></literal> part
+            will be repeated for each item in the sequence that you have
+            specified with
+            <literal><replaceable>sequence</replaceable></literal>, one after
+            the other, starting from the first item. In all repetitions
+            <literal><replaceable>loopVariable</replaceable></literal> will
+            hold the value of the current item. This variable exists only
+            between the <literal>&lt;#list
+            <replaceable>...</replaceable>&gt;</literal> and
+            <literal>&lt;/#list&gt;</literal> tags.</para>
+
+            <para>The <literal><replaceable>sequence</replaceable></literal>
+            can be any kind of expression, like we could list the fruits of
+            the example data model like this:</para>
+
+            <programlisting role="template">&lt;ul&gt;
+<emphasis>&lt;#list misc.fruits as fruit&gt;</emphasis>
+  &lt;li&gt;${fruit}
+<emphasis>&lt;/#list&gt;</emphasis>
+&lt;/ul&gt;</programlisting>
+
+            <para>The <literal>misc.fruits</literal> expression should be
+            familiar to you; it <link
+            linkend="topic.qStart.accessVariables">references a variable in
+            the data-model</link>.</para>
+
+            <para>A problem with the above example is that if we happen to
+            have 0 fruits, it will still print an empty
+            <literal>&lt;ul&gt;&lt;/ul&gt;</literal> instead of just nothing.
+            To avoid that, you can use this form of
+            <literal>list</literal>:</para>
+
+            <programlisting role="template">&lt;#list misc.fruits&gt;
+  &lt;ul&gt;
+   <emphasis> &lt;#items as fruit&gt;</emphasis>
+      &lt;li&gt;${fruit}
+ <emphasis>   &lt;/#items&gt;</emphasis>
+  &lt;/ul&gt;
+&lt;/#list&gt;</programlisting>
+
+            <para>Here, the <literal>list</literal> directive represents the
+            listing as a whole, and only the part inside the
+            <literal>items</literal> directive is repeated for each fruit. If
+            we have 0 fruits, everything inside <literal>list</literal> is
+            skipped, hence we will not have <literal>ul</literal> tags in
+            case.</para>
+
+            <para>Another frequent listing-related task: let's list the fruits
+            separating them with something, like comma:</para>
+
+            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}<emphasis>&lt;#sep&gt;, </emphasis>&lt;/#list&gt;</programlisting>
+
+            <programlisting role="output">&lt;p&gt;Fruits: orange, banana</programlisting>
+
+            <para>The section covered by <literal>sep</literal> (which we
+            could be written like this too:
+            <literal><replaceable>...</replaceable>&lt;#sep&gt;,
+            &lt;/#sep&gt;&lt;/#list&gt;</literal>) will be only executed when
+            there will be a next item. Hence there's no comma after the last
+            fruit.</para>
+
+            <para>Here again, what's if we have 0 fruits? Just printing
+            <quote>Fruits:</quote> and then nothing is awkward. A
+            <literal>list</literal>, just like an <literal>if</literal>, can
+            have an <literal>else</literal>, which is executed if there were 0
+            list items:</para>
+
+            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}&lt;#sep&gt;, <emphasis>&lt;#else&gt;None</emphasis>&lt;/#list&gt;</programlisting>
+
+            <note>
+              <para>As a matter of fact, this simplistic example could be
+              written like this, but it uses language devices that are off
+              topic here:</para>
+
+              <programlisting role="template">&lt;p&gt;Fruits: ${fruits?join(", ", "None")}</programlisting>
+            </note>
+
+            <para>All these directives (<literal>list</literal>,
+            <literal>items</literal>, <literal>sep</literal>,
+            <literal>else</literal>) can be used together:</para>
+
+            <programlisting role="template">&lt;#list misc.fruits&gt;
+  &lt;p&gt;Fruits:
+  &lt;ul&gt;
+    &lt;#items as fruit&gt;
+      &lt;li&gt;${fruit}&lt;#sep&gt; and&lt;/#sep&gt;
+    &lt;/#items&gt;
+  &lt;/ul&gt;
+&lt;#else&gt;
+  &lt;p&gt;We have no fruits.
+&lt;/#list&gt;</programlisting>
+
+            <note>
+              <para>You can read more about these directives <link
+              linkend="ref_directive_list">in the Reference</link>.</para>
+            </note>
+          </section>
+
+          <section>
+            <title>The include directive</title>
+
+            <para>With the <literal>include</literal> directive you can insert
+            the content of another file into the template.</para>
+
+            <para>Suppose you have to show the same copyright notice on
+            several pages. You can create a file that contains the copyright
+            notice only, and insert that file everywhere where you need that
+            copyright notice. Say, you store this copyright notice in
+            <literal>copyright_footer.html</literal>:</para>
+
+            <programlisting role="template">&lt;hr&gt;
+&lt;i&gt;
+Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
+&lt;br&gt;
+All Rights Reserved.
+&lt;/i&gt;</programlisting>
+
+            <para>Whenever you need that file you simply insert it with the
+            <literal>include</literal> directive:</para>
+
+            <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Test page&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Test page&lt;/h1&gt;
+  &lt;p&gt;Blah blah...
+<emphasis>  &lt;#include "/copyright_footer.html"&gt;</emphasis>
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>and the output will be:</para>
+
+            <programlisting role="output">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Test page&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Test page&lt;/h1&gt;
+  &lt;p&gt;Blah blah...
+<emphasis>&lt;hr&gt;
+&lt;i&gt;
+Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
+&lt;br&gt;
+All Rights Reserved.
+&lt;/i&gt;</emphasis>
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>If you change the <literal>copyright_footer.html</literal>,
+            then the visitor will see the new copyright notice on all
+            pages.</para>
+
+            <note>
+              <para>A much more powerful way of reusing snippets is using
+              macros, but that's an advanced topic <link
+              linkend="dgui_misc_userdefdir">discussed later</link>.</para>
+            </note>
+          </section>
+        </section>
+
+        <section>
+          <title>Using directives together</title>
+
+          <para>You can use directives as many times on a page as you want,
+          and you can nest directives into each other freely. For example,
+          here you nest <literal>if</literal> directive inside a
+          <literal>list</literal> directive:</para>
+
+          <programlisting role="template"><emphasis>&lt;#list animals as animal&gt;</emphasis>
+      &lt;div<emphasis>&lt;#if animal.protected&gt;</emphasis><emphasis> </emphasis>class="protected"<emphasis>&lt;/#if&gt;</emphasis>&gt;
+        ${animal.name} for ${animal.price} Euros
+      &lt;/div&gt;
+<emphasis>&lt;/#list&gt;</emphasis></programlisting>
+
+          <para>Note that since FreeMarker does not interpret text outside FTL
+          tags, interpolations and FTL comments, above you could use the FTL
+          tags inside a 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 coming from
+          the data-model, but added by FreeMarker to the values. To make it
+          unambiguous where the subvarable comes from, to access them you have
+          to use <literal>?</literal> (question mark) instead of
+          <literal>.</literal> (dot). <anchor
+          xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most
+          commonly used built-ins:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>user?upper_case</literal> gives the upper case
+              version of the value of <literal>user</literal> (like
+              <quote>JOHN DOE</quote> instead of <quote>John
+              Doe</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animal.name?cap_first</literal> give the
+              <literal>animal.name</literal> with its first letter converted
+              to upper case (like <quote>Mouse</quote> instead of
+              <quote>mouse</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?length</literal> gives the number of
+              <emphasis>characters</emphasis> in the value of
+              <literal>user</literal> (8 for <quote>John Doe</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animals?size</literal> gives the number of
+              <emphasis>items</emphasis> in the <literal>animals</literal>
+              sequence (3 in our example data-model)</para>
+            </listitem>
+
+            <listitem>
+              <para>If you are between <literal>&lt;#list animals as
+              animal&gt;</literal> and the corresponding
+              <literal>&lt;/#list&gt;</literal> tag:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para><literal>animal?index</literal> gives the 0-based
+                  index of <literal>animal</literal> inside
+                  <literal>animals</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>animal?counter</literal> is like
+                  <literal>index</literal>, but gives the 1-based index</para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>animal?item_parity</literal> gives the
+                  strings <quote>odd</quote> or <quote>even</quote>, depending
+                  on the current counter parity. This is commonly used for
+                  coloring rows with alternating colors, like in
+                  <literal>&lt;td
+                  class="${animal?item_parity}Row"&gt;</literal>.</para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+          </itemizedlist>
+
+          <para>Some built-ins require parameters to specify the behavior
+          more, for example:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>animal.protected?string("Y", "N")</literal>
+              return the string <quote>Y</quote> or <quote>N</quote> depending
+              on the boolean value of
+              <literal>animal.protected</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animal?item_cycle('lightRow',
+              'darkRow')</literal> is the more generic variant of
+              <literal>item_parity</literal> from earlier.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>fruits?join(", ")</literal>: converts the list to
+              a string by concatenating items, and inserting the parameter
+              separator between each items (like <quote>orange,
+              banana</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?starts_with("J")</literal> gives boolean
+              true of false depending on if <literal>user</literal> starts
+              with the letter <quote>J</quote> or not.</para>
+            </listitem>
+          </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 the referring 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, so the "missing" term used here
+          covers both cases.</phrase></para>
+
+          <para>Wherever you refer to a variable, you can specify a default
+          value for the case the variable is missing, by following the
+          variable name with a <literal>!</literal> and the default value.
+          Like in the following example, when <literal>user</literal> is
+          missing from data model, the template will behave like if
+          <literal>user</literal>'s value were the string
+          <literal>"visitor"</literal>. (When <literal>user</literal> isn't
+          missing, this template behaves exactly like with
+          <literal>${user}</literal>):</para>
+
+          <programlisting role="template">&lt;h1&gt;Welcome ${user<emphasis>!"visitor"</emphasis>}!&lt;/h1&gt;</programlisting>
+
+          <para>You can ask whether a variable isn't missing by putting
+          <literal>??</literal> after its name. Combining this with the
+          already introduced <literal>if</literal> directive you can skip the
+          whole greeting if the <literal>user</literal> variable is
+          missing:</para>
+
+          <programlisting role="template">&lt;#if <emphasis>user??</emphasis>&gt;&lt;h1&gt;Welcome ${user}!&lt;/h1&gt;&lt;/#if&gt;</programlisting>
+
+          <para>Regarding variable accessing with multiple steps, like
+          <literal>animals.python.price</literal>, writing
+          <literal>animals.python.price!0</literal> is correct only if
+          <literal>animals.python</literal> is never missing and only the last
+          subvariable, <literal>price</literal>, is possibly missing (in which
+          case here we assume it's <literal>0</literal>). If
+          <literal>animals</literal> or <literal>python</literal> is missing,
+          the template processing will stop with an "undefined variable"
+          error. To prevent that, you have to write
+          <literal>(animals.python.price)!0</literal>. In that case the
+          expression will be <literal>0</literal> even if
+          <literal>animals</literal> or <literal>python</literal> is missing.
+          Same logic goes for <literal>??</literal>;
+          <literal>animals.python.price??</literal> versus
+          <literal>(animals.python.price)??</literal>.</para>
+        </section>
+
+        <section xml:id="dgui_quickstart_template_autoescaping">
+          <title>Escaping for HTML, XML and other markup</title>
+
+          <para>Let's say the template generates HTML, and you insert values
+          with <literal>${<replaceable>...</replaceable>}</literal> that are
+          plain text (not HTML), like company names coming from a database.
+          Characters that has special meaning in HTML must be
+          <emphasis>escaped</emphasis> in such values, like if
+          <literal>name</literal> is <quote>Someone &amp; Co.</quote> then
+          <literal>${name}</literal> should print <quote>Someone
+          <emphasis>&amp;amp;</emphasis> Co.</quote>.</para>
+
+          <para>FreeMarker automatically escapes all values printed with
+          <literal>${<replaceable>...</replaceable>}</literal> <emphasis>if
+          it's properly configured</emphasis> (that's the responsibility of
+          the programmers; <link
+          linkend="pgui_config_outputformatsautoesc">see here how</link>). The
+          recommended practice is using <literal>ftlh</literal> file extension
+          to activate HTML auto-escaping, and <literal>ftlx</literal> file
+          extension to activate XML auto-escaping.</para>
+
+          <para>You can try if auto-escaping is on like
+          <literal>${"&lt;"}</literal> (for HTML or XML escaping). If it's
+          not, and the configuration won't be adjusted, add this as the very
+          first line of the template:</para>
+
+          <programlisting role="template">&lt;#ftl output_format="HTML"&gt;</programlisting>
+
+          <para>(Use <literal>"XML"</literal> instead of
+          <literal>"HTML"</literal> above if you generate XML.)</para>
+
+          <para>If the string value to print deliberately contains markup,
+          auto-escaping must be prevented like
+          <literal>${<replaceable>value</replaceable>?no_esc}</literal>.</para>
+
+          <para>You can find out much more about auto-escaping and output
+          formats <link linkend="dgui_misc_autoescaping">here...</link></para>
+
+          <note>
+            <para>The kind of automatic escaping described here requires at
+            least FreeMarker 2.3.24. If you have to use an earlier version,
+            use the deprecated <link
+            linkend="ref_directive_escape"><literal>escape</literal>
+            directive</link> instead.</para>
+          </note>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_datamodel">
+      <title>Values, Types</title>
+
+      <section xml:id="dgui_datamodel_basics">
+        <title>Basics</title>
+
+        <note>
+          <para>It is assumed that you have already read the <xref
+          linkend="dgui_quickstart"/> chapter.</para>
+        </note>
+
+        <para>Understanding the concept of values and types is crucial for the
+        understanding of data-models. However, the concept of values and types
+        is not confined to data-models, as you will see.</para>
+
+        <section xml:id="topic.value">
+          <title>What is a value?</title>
+
+          <indexterm>
+            <primary>value</primary>
+          </indexterm>
+
+          <para><phrase role="forProgrammers">Real programmers can safely skip
+          this section.</phrase></para>
+
+          <para>Examples of <emphasis>values</emphasis> as you know the term
+          from the everyday math are 16, 0.5, and so on, i.e. numbers. In the
+          case of computer languages the value term has a wider meaning, as a
+          value needn't be a number. For example, take this data-model:</para>
+
+          <programlisting role="dataModel" xml:id="example.stdDataModel">(root)
+ |
+ +- user = "Big Joe"
+ |
+ +- today = Jul 6, 2007
+ |
+ +- todayHoliday = false
+ |
+ +- lotteryNumbers
+ |   |
+ |   +- (1st) = 20
+ |   |
+ |   +- (2st) = 14
+ |   |
+ |   +- (3rd) = 42
+ |   |
+ |   +- (4th) = 8
+ |   |
+ |   +- (5th) = 15
+ |
+ +- cargo
+     |
+     +- name = "coal"
+     |
+     +- weight = 40
+</programlisting>
+
+          <para>We say that the <emphasis>value</emphasis> of the the
+          <literal>user</literal> variable is "Big Joe" (a string), the
+          <emphasis>value</emphasis> of <literal>today</literal> is Jul 6,
+          2007 (a date), the <emphasis>value</emphasis> of
+          <literal>todayHoliday</literal> is false (a boolean, ie. a yes/no
+          thing). The <emphasis>value</emphasis> of
+          <literal>lotteryNumbers</literal> is the sequence that contains 20,
+          14, 42, 8, 15. Surely <literal>lotteryNumbers</literal> is multiple
+          values in the sense that it <emphasis>contains</emphasis> multiple
+          values (for example, the 2nd item in it is a the
+          <emphasis>value</emphasis> 14), but still,
+          <literal>lotteryNumbers</literal> itself is a single value. It's
+          like a box that contains many other items; the whole box can be seen
+          as a single item. Last not least we also have the
+          <emphasis>value</emphasis> of <literal>cargo</literal>, which is a
+          hash (a box-like thing again).So, a value is something that can be
+          stored in a variable (e.g., in <literal>user</literal> or
+          <literal>cargo</literal> or <literal>cargo.name</literal>). But a
+          value need not be stored in a variable to be called a value, for
+          example we have the value 100 here:</para>
+
+          <programlisting role="template">&lt;#if cargo.weight &lt; <emphasis>100</emphasis>&gt;Light cargo&lt;/#if&gt;</programlisting>
+
+          <para>The temporaly result of a calculations are also called values,
+          like 20 and 120 when this template is executed (it will print
+          120):</para>
+
+          <programlisting role="template">${cargo.weight / 2 + 100}</programlisting>
+
+          <para>Explanation for this last: As the result of dividing the two
+          values, 40 (the weight of the cargo) and 2, a new value 20 is
+          created. Then 100 is added to it, so the value 120 is created. Then
+          120 is printed
+          (<literal>${<replaceable>...</replaceable>}</literal>), and the
+          template execution goes on and all these values gone.</para>
+
+          <para>Certainly now you feel what the value term means.</para>
+        </section>
+
+        <section>
+          <title>What is type?</title>
+
+          <para>Values have an important aspect, their type. For example the
+          type of the value of the <literal>user</literal> variable is string,
+          and the type of the value of the <literal>lotteryNumbers</literal>
+          variable is sequence. The type of a value is important because it
+          determines to a large extent how and where you can use the value.
+          Like <literal>${user / 2}</literal> is an error, but
+          <literal>${cargo.weight / 2}</literal> works and prints 20, since
+          division only does make sense for a number, but not for a string.
+          Or, using dot like in <literal>cargo.name</literal> does make sense
+          only if <literal>cargo</literal> is a hash. Or, you can list with
+          <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
+          sequences only. Or, the condition of <literal>&lt;#if
+          ...&gt;</literal> must be a boolean. And so on.</para>
+
+          <note>
+            <para>A little terminology... Saying "a boolean" or "a boolean
+            value" or "a value of type boolean" are all the same.</para>
+          </note>
+
+          <para xml:id="topic.multitype"><indexterm>
+              <primary>Multi-typed value</primary>
+            </indexterm>A value can have multiple types at the same time,
+          although it's rarely utilized. For example in the data-model below
+          <literal>mouse</literal> is both a string and a hash:</para>
+
+          <programlisting role="dataModel">(root)
+ |
+ +- mouse = "Yerri"
+     |
+     +- age = 12
+     |
+     +- color = "brown"</programlisting>
+
+          <para>If you merge this template with the above data-model:</para>
+
+          <programlisting role="template">${mouse}       &lt;#-- uses mouse as a string --&gt;
+${mouse.age}   &lt;#-- uses mouse as a hash --&gt;
+${mouse.color} &lt;#-- uses mouse as a hash --&gt;</programlisting>
+
+          <para>the output will be:</para>
+
+          <programlisting role="output">Yerri
+12
+brown</programlisting>
+        </section>
+
+        <section>
+          <title>The data-model is a hash</title>
+
+          <para>Looking at the various data-model examples you may already
+          realized: the thing marked as "(root)" is just a value of type hash.
+          When you write something like <literal>user</literal>, that means
+          that you want the "user" variable stored in the root hash. Like if
+          you were writing <literal>root.user</literal>, except that there is
+          no variable called "root" so that wouldn't work.</para>
+
+          <para>Some may get confused by the fact that our example data-model,
+          that is, the root hash, contains further hashes and sequences
+          (<literal>lotteryNumbers</literal> and <literal>cargo</literal>).
+          There is nothing special in that. A hash contains other variables,
+          and those variables have a value, which can be a string, a number,
+          etc., and of course it can be a hash or sequence as well. Because,
+          as it was explained earlier, a sequence or a hash is just a value,
+          like a string or a number is.</para>
+        </section>
+      </section>
+
+      <section xml:id="dgui_datamodel_types">
+        <title>The types</title>
+
+        <para>The suppored types are:</para>
+
+        <itemizedlist spacing="compact">
+          <listitem>
+            <para><link linkend="dgui_datamodel_scalar"
+            os="">Scalars:</link></para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para>String</para>
+              </listitem>
+
+              <listitem>
+                <para>Number</para>
+              </listitem>
+
+              <listitem>
+                <para>Boolean</para>
+              </listitem>
+
+              <listitem>
+                <para>Date-like (date, time, or date-time)</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para><link
+            linkend="dgui_datamodel_container">Containers:</link></para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para>Hash</para>
+              </listitem>
+
+              <listitem>
+                <para>Sequence</para>
+              </listitem>
+
+              <listitem>
+                <para>Collection</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Subroutines:</para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para><link linkend="dgui_datamodel_method">Methods and
+                functions</link></para>
+              </listitem>
+
+              <listitem>
+                <para><link linkend="dgui_datamodel_userdefdir">User-defined
+                directives</link></para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>Miscellaneous/seldom used:</para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para><link linkend="dgui_datamodel_node">Node</link></para>
+              </listitem>
+
+              <listitem>
+                <para><link linkend="dgui_datamodel_markupoutput">Markup
+                output</link></para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="dgui_datamodel_scalar">
+          <title>Scalars</title>
+
+          <anchor xml:id="topic.designer.scalarVariable"/>
+
+          <para>These are the basic, simple kind of values. They can
+          be:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><indexterm>
+                  <primary>string</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>String: It is simple text, e.g., the name of a
+              product.</para>
+
+              <para>If you want to give a string value directly in the
+              template, rather than use a variable that comes from the data
+              model, you write the text between quotation marks, e.g.,
+              <literal>"green mouse"</literal> or <literal>'green
+              mouse'</literal>. (More details regarding the syntax can be
+              found <link linkend="dgui_template_exp_direct_string"
+              xml:lang="">later</link>.)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>number</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Number: For example the price of a product.
+              <phrase role="forProgrammers">Whole numbers and non-whole
+              numbers are not distinguished; there is only a single number
+              type. So for example 3/2 will be always 1.5, and never 1. Just
+              like if you are using a calculator.</phrase></para>
+
+              <para>If you want to give a numerical value directly in the
+              template, then you write for example: <literal>150</literal> or
+              <literal>-90.05</literal> or <literal>0.001</literal>. (More
+              details regarding the syntax can be found <link
+              linkend="dgui_template_exp_direct_number"
+              xml:lang="">later</link>.)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>boolean</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Boolean: A boolean value represents a logical true
+              or false (yes or no). For example, if a the visitor has been
+              logged in or not. Typically you use booleans as the condition of
+              the <literal>if</literal> directive, like <literal>&lt;#if
+              loggedIn
+              &gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal> or
+              <literal>&lt;#if price ==
+              0&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>; in
+              the last case the result of the <literal>price == 0</literal>
+              part is a boolean value.</para>
+
+              <para>In the templates you can directly specify a boolean with
+              the reserved words <literal>true</literal> and
+              <literal>false</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>date</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm><indexterm>
+                  <primary>time</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm><indexterm>
+                  <primary>date-time</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Date: A date-like value stores date/time related
+              data. It has three variations:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para>Date: Like April 4, 2003. Day precision, no time of
+                  day part.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Time: Like 10:19:18 PM. Millisecond precision, no date
+                  part.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Date-time (sometimes called "time stamp") as April 4,
+                  2003 10:19:18 PM. Both date and time, with millisecond
+                  precision.</para>
+                </listitem>
+              </itemizedlist>
+
+              <para>Unfortunately, because of the limitations of the Java
+              platform, FreeMarker sometimes can't decide which parts of the
+              date are in use (i.e., if it is date-time, a date or a time).
+              The solution for this problem is an advanced topic that will be
+              discussed <link
+              linkend="ref_builtin_date_datetype">later</link>.</para>
+
+              <para>It is possible to define date-like values directly in
+              templates, but this is an advanced topic that will be explained
+              <link linkend="ref_builtin_string_date">later</link>.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Bear in mind that FreeMarker distinguishes strings from
+          numbers, booleans and date-like values. For example, while the
+          string <literal>"150"</literal> looks like the number
+          <literal>150</literal>, a string is still just arbitrary sequence of
+          characters, and you can't do arithmetic with it, can't compare it
+          with another number, etc.</para>
+        </section>
+
+        <section xml:id="dgui_datamodel_container">
+          <title>Containers</title>
+
+          <remark>Re-explanation of hashes and sequences from a more
+          ''professional'' viewpoint as earlier, and some meditation about
+          them.</remark>
+
+          <para>These are the values whose purpose is to contain other
+          variables; they are just containers. The contained variables are
+          often referred as <emphasis>sub variables</emphasis>. The container
+          types are:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><indexterm>
+                  <primary>hash</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Hash: Associates a unique lookup name with each of
+              its sub variables. The name is an unrestricted string. A hash
+              <emphasis>doesn't define an ordering</emphasis> for the sub
+              variables in it. That is, there is no such thing as the first
+              subvariable, and the second subvariable, etc.; the variables are
+              just accessed by name.</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>sequence</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Sequence: Associates an integer number with each
+              of its sub variables. The first subvariable is associated with
+              0, the second with 1, the third to 2, and so on; the sub
+              variables are ordered. These numbers are often called the
+              <emphasis>indexes</emphasis> of the sub variables. Sequences are
+              usually dense, i.e., all indexes up to the index of the last
+              subvariable have an associated subvariable, but it's not
+              strictly necessary. The type of the subvariable values need not
+              be the same.</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>collection</primary>
+
+                  <secondary>the FTL value type</secondary>
+                </indexterm>Collection: A collection, from the viewpoint of
+              the template author, is a restricted sequence. You cannot access
+              its size or retrieve its sub variables by index, but they can be
+              still listed with the <link
+              linkend="ref.directive.list"><literal>list</literal>
+              directive</link>.</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>
+        </section>
+
+        <section>
+          <title>Subroutines</title>
+
+          <section xml:id="dgui_datamodel_method">
+            <title>Methods and functions</title>
+
+            <anchor xml:id="topic.designer.methodVariable"/>
+
+            <indexterm>
+              <primary>method</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>A value that is a method or a function is used to calculate
+            another value, influenced by the parameters you give to it.</para>
+
+            <para><phrase role="forProgrammers">For programmer types:
+            Methods/functions are first-class values, just like in functional
+            programming languages. This means that functions/methods can be
+            the parameters or return values of other functions/methods, you
+            can assign them to variables, and so on.</phrase></para>
+
+            <para>Suppose that programmers have put the method variable
+            <literal>avg</literal> in the data-model that can be used to
+            calculate the average of numbers. If you give the 3 and 5 as
+            parameters when you access <literal>avg</literal>, then you get
+            the value 4.</para>
+
+            <para>The usage of methods will be explained <link
+            linkend="dgui_template_exp_methodcall">later</link>, but perhaps
+            this example helps to understand what methods are:</para>
+
+            <programlisting role="template">The average of 3 and 5 is: ${avg(3, 5)}
+The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
+The average of the price of a python and an elephant is:
+${avg(animals.python.price, animals.elephant.price)}</programlisting>
+
+            <para>this will output:</para>
+
+            <programlisting role="output">The average of 3 and 5 is: 4
+The average of 6 and 10 and 20 is: 12
+The average of the price of a python and an elephant is:
+4999.5</programlisting>
+
+            <para>What is the difference between a method and a function? As
+            far as the template author is concerned, nothing. Well not really
+            nothing, as methods typically come from the data-model (<phrase
+            role="forProgrammers">as they reflect the methods of Java
+            objects</phrase>), and functions are defined in templates (with
+            the <link
+            linkend="ref.directive.function"><literal>function</literal>
+            directive</link> -- an advanced topic), but both can be used on
+            the same way.</para>
+          </section>
+
+          <section xml:id="dgui_datamodel_userdefdir">
+            <title>User-defined directives</title>
+
+            <indexterm>
+              <primary>macro</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>directive</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>user-defined directive</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>A value of this type can be used as user-defined directive
+            (with other words, as FreeMarker tag). An user-defined directive
+            is a subroutine, something like a little reusable template
+            fragment. But this is an advanced topic that will be explained
+            <link linkend="dgui_misc_userdefdir">later</link> in its own
+            chapter.</para>
+
+            <para><phrase role="forProgrammers">For programmer types:
+            user-defined directives (such as macros), are first-class values
+            too, just like functions/methods are.</phrase></para>
+
+            <para>Just to get an idea about user-defined directives (so just
+            ignore this if you won't understand), assume we have a variable,
+            <literal>box</literal>, whose value is a user-defined directive
+            that prints some kind of fancy HTML message box with a title bar
+            and a message in it. The <literal>box</literal> variable could be
+            used in the template like this (for example):</para>
+
+            <programlisting role="template">&lt;@<emphasis>box</emphasis> title="Attention!"&gt;
+  Too much copy-pasting may leads to
+  maintenance headaches.
+&lt;/@<emphasis>box</emphasis>&gt;</programlisting>
+          </section>
+
+          <section>
+            <title>Function/method versus user-defined directive</title>
+
+            <para>This is for advanced users again (so ignore it if you don't
+            understand). It's a frequent dilemma if you should use a
+            function/method or an user-defined directive to implement
+            something. The rule of thumb is: Implement the facility as
+            user-defined directive instead of as function/method if:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>... the purpose of it is generating a piece of the
+                output that's not just a single value, and typically involves
+                markup. The template language was designed for printing to the
+                output directly, piece by piece, as it goes though
+                <literal>list</literal> loops, <literal>if</literal>-s, etc.
+                Building up a string value in a variable then returning it is
+                much less convenient.</para>
+              </listitem>
+
+              <listitem>
+                <para>... it's the side-effect that is important and not the
+                return value. For example, a directive whose purpose is to add
+                an entry to the server log is like that. (In fact you can't
+                have a return value for a user-defined directive, but some
+                kind of feedback is still possible by setting non-local
+                variables.)</para>
+              </listitem>
+
+              <listitem>
+                <para>... it will do flow control on the caller side (like for
+                example <literal>list</literal> or <literal>if</literal>
+                directives do). You just can't do that with a
+                function/method.</para>
+              </listitem>
+
+              <listitem>
+                <para>... you are using legacy escaping via the
+                <literal>escape</literal> directive (instead of <link
+                linkend="dgui_misc_autoescaping">auto-escaping</link>), and
+                the result contains markup. When you print the result with
+                <literal>${<replaceable>...</replaceable>}</literal>, the
+                markup will be escaped and thus ruined, but if it's printed by
+                a directive call
+                (<literal>&lt;@<replaceable>...</replaceable>&gt;</literal>),
+                it won't be.</para>
+              </listitem>
+            </itemizedlist>
+
+            <para>The Java methods of FreeMarker-unaware Java objects are
+            normally visible as methods in templates, regardless of the nature
+            of the Java method; you have no choice there.</para>
+          </section>
+        </section>
+
+        <section>
+          <title>Miscellaneous</title>
+
+          <section xml:id="dgui_datamodel_node">
+            <title>Nodes</title>
+
+            <indexterm>
+              <primary>node</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>Node variables represent a node in a tree structure, and are
+            used mostly with <link linkend="xgui">XML processing</link>, which
+            is an advanced, and specialized topic.</para>
+
+            <para>Still, a quick overview <emphasis>for advanced
+            users</emphasis>: A node is similar to a sequence that stores
+            other nodes, which are often referred as the children nodes. A
+            node stores a reference to its container node, which is often
+            referred as the parent node. The main point of being a node is the
+            topological information; other data must be stored by utilizing
+            that a value can have multiple types. Like, a value may be both a
+            node and a number, in which case it can store a number as the
+            "pay-load". Apart from the topological information, a node can
+            store some metainformation as well: a node name, a node type
+            (string), and a node namespace (string). For example, if the node
+            symbolizes a <literal>h1</literal> element in an XHTML document,
+            then its name could be <literal>"h1"</literal>, it's node type
+            could be <literal>"element"</literal>, and it's namespace could be
+            <literal>"http://www.w3.org/1999/xhtml"</literal>. But it's up to
+            the designer of the data-model if what meaning these
+            metainformations have, and if they are used at all. The way of
+            retrieving the topological and metainformations is described <link
+            linkend="ref_builtins_node">in a later chapter</link> (that you
+            don't have to understand at this point).</para>
+          </section>
+
+          <section xml:id="dgui_datamodel_markupoutput">
+            <title>Markup output</title>
+
+            <indexterm>
+              <primary>markup output</primary>
+
+              <secondary>the FTL value type</secondary>
+            </indexterm>
+
+            <para>This type is related to <link
+            linkend="dgui_misc_autoescaping">auto-escaping mechanism</link>
+            introduced FreeMarker 2.3.24; you can <link
+            linkend="dgui_misc_autoescaping_movalues">read about this type
+            there</link>. But in short, this is a value that stores text
+            that's already in the output markup format (like HTML, XML, RTF,
+            etc.), and hence must not be auto-escaped.</para>
+
+            <para>Values of this type are usually produced inside the
+            templates (like with <link
+            linkend="ref_builtin_no_esc"><literal>no_esc</literal>
+            built-in</link> or <link linkend="ref_directive_assign">output
+            capturing assignments</link>), but can also be part of the
+            data-model. Such values in the data-model are useful for example
+            if you have message resources that sometimes contain the message
+            in HTML format, rather than in plain text. If the data-model uses
+            HTML markup output values for those messages instead of strings,
+            then the template author need not know which messages contain HTML
+            and which plain text, as double escaping will be avoided
+            automatically when the message is inserted with
+            <literal>${<replaceable>...</replaceable>}</literal>.</para>
+          </section>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_template">
+      <title>The Template</title>
+
+      <indexterm>
+        <primary>template</primary>
+      </indexterm>
+
+      <note>
+        <para>It is assumed that you have already read the <xref
+        linkend="dgui_quickstart"/> and the <xref linkend="dgui_datamodel"/>
+        chapter.</para>
+      </note>
+
+      <section xml:id="dgui_template_overallstructure">
+        <title>Overall structure</title>
+
+        <para>Templates are in fact programs you write in a language called
+        <indexterm>
+            <primary>FTL</primary>
+          </indexterm><emphasis role="term">FTL</emphasis> (for FreeMarker
+        Template Language). This is a quite simple programming language
+        designed for writing templates and nothing else.</para>
+
+        <para>A template (= FTL program) is a mix of the following
+        sections:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><emphasis role="term">Text</emphasis><indexterm>
+                <primary>text</primary>
+              </indexterm>: Text that will be printed to the output as
+            is.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Interpolation</emphasis><indexterm>
+                <primary>interpolation</primary>
+              </indexterm>: These sections will be replaced with a calculated
+            value in the output. Interpolations are delimited by
+            <literal>${</literal> and <literal>}</literal> (or with
+            <literal>#{</literal> and <literal>}</literal>, but that shouldn't
+            be used anymore; <link
+            linkend="ref_depr_numerical_interpolation">see more
+            here</link>).</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">FTL tags</emphasis><indexterm>
+                <primary>FTL tag</primary>
+              </indexterm>: FTL tags are a bit similar to HTML tags, but they
+            are instructions to FreeMarker and will not be printed to the
+            output.</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">Comments</emphasis><indexterm>
+                <primary>comment</primary>
+              </indexterm><indexterm>
+                <primary>&lt;#--...--&gt;</primary>
+              </indexterm><indexterm>
+                <primary>#</primary>
+              </indexterm>: Comments are similar to HTML comments, but they
+            are delimited by <literal>&lt;#--</literal> and
+            <literal>--&gt;</literal>. Comments will be ignored by FreeMarker,
+            and will not be written to the output.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Let's see a concrete template. I have marked the template's
+        components with colors: <phrase role="markedText">text</phrase>,
+        <phrase role="markedInterpolation">interpolation</phrase>, <phrase
+        role="markedFTLTag">FTL tag</phrase>, <phrase
+        role="markedComment">comment</phrase>. With the <phrase
+        role="markedInvisibleText">[BR]</phrase>-s I intend to visualize the
+        <link linkend="gloss.lineBreak">line breaks</link>.</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;html&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;title&gt;Welcome!&lt;/title&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedComment">&lt;#-- Greet the user with his/her name --&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;h1&gt;Welcome <phrase role="markedInterpolation">${user}</phrase>!&lt;/h1&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;#list animals as animal&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+    &lt;li&gt;<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/html&gt;</phrase></programlisting>
+
+        <para>FTL distinguishes upper case and lower case letters. So
+        <literal>list</literal> is good directive name, while
+        <literal>List</literal> is not. Similarly <literal>${name}</literal>
+        is not the same as <literal>${Name}</literal> or
+        <literal>${NAME}</literal></para>
+
+        <para>It is important to realize that <phrase
+        role="markedInterpolation">interpolations</phrase> can be used in
+        <phrase role="markedText">text</phrase> (and in string literal
+        expressions; see <link
+        linkend="dgui_template_exp_stringop_interpolation">later</link>)
+        only.</para>
+
+        <para>An <phrase role="markedFTLTag">FTL tag</phrase> can't be inside
+        another <phrase role="markedFTLTag">FTL tag</phrase> nor inside an
+        <phrase role="markedInterpolation">interpolation</phrase>. For example
+        this is <emphasis>WRONG</emphasis>: <literal>&lt;#if &lt;#include
+        'foo'&gt;='bar'&gt;...&lt;/#if&gt;</literal></para>
+
+        <para><phrase role="markedComment">Comments</phrase> can be placed
+        inside <phrase role="markedFTLTag">FTL tags</phrase> and <phrase
+        role="markedInterpolation">interpolations</phrase>. For
+        example:</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;h1&gt;Welcome <phrase
+              role="markedInterpolation">${user <phrase role="markedComment">&lt;#-- The name of user --&gt;</phrase>}</phrase>!&lt;/h1&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;#list <phrase role="markedComment">&lt;#-- some comment... --&gt;</phrase> animals as <phrase
+                role="markedComment">&lt;#-- again... --&gt;</phrase> animal&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase></phrase>
+<replaceable>...</replaceable></programlisting>
+
+        <note>
+          <para>For those of you who have tried the above examples: You may
+          notice that some of spaces, tabs and line breaks are missing from
+          the template output, even though we said that <phrase
+          role="markedText">text</phrase> is printed as is. Don't bother with
+          it now. This is because the feature called ''white-space stripping''
+          is turned on, and that automatically removes some superfluous
+          spaces, tabs and line breaks. This will be explained <link
+          linkend="dgui_misc_whitespace">later</link>.</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_template_directives">
+        <title>Directives</title>
+
+        <indexterm>
+          <primary>&lt;#...&gt;</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>#</primary>
+        </indexterm>
+
+        <anchor xml:id="term.designer.directive"/>
+
+        <remark>Note that the Expressions chapter depends on this chapter, and
+        Interpolations chapter depends on Expressions chapter. Thus Directives
+        must be the first chapter after Basics.</remark>
+
+        <para><indexterm>
+            <primary>directive</primary>
+          </indexterm>You use FTL tags to call <emphasis
+        role="term">directives</emphasis>. In the example you have called the
+        <literal>list</literal> directive. Syntactically you have done it with
+        two tags: <literal>&lt;#list animals as animal&gt;</literal> and
+        <literal>&lt;/#list&gt;</literal>.</para>
+
+        <para><indexterm>
+            <primary>FTL tag</primary>
+          </indexterm>There are two kind of FTL tags:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>Start-tag:
+            <literal>&lt;#<replaceable>directivename</replaceable>
+            <replaceable>parameters</replaceable>&gt;</literal></para>
+          </listitem>
+
+          <listitem>
+            <para>End-tag:
+            <literal>&lt;/#<replaceable>directivename</replaceable>&gt;</literal></para>
+          </listitem>
+        </itemizedlist>
+
+        <para>This is similar to HTML or XML syntax, except that the tag name
+        starts with <literal>#</literal>. If the directive doesn't have nested
+        content (content between the start-tag and the end-tag), you must use
+        the start-tag with no end-tag. For example you write <literal>&lt;#if
+        <replaceable>something</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>,
+        but just <literal>&lt;#include
+        <replaceable>something</replaceable>&gt;</literal> as FreeMarker knows
+        that the <literal>include</literal> directive can't have nested
+        content.</para>
+
+        <para>The format of the
+        <literal><replaceable>parameters</replaceable></literal> depends on
+        the
+        <literal><replaceable>directivename</replaceable></literal>.</para>
+
+        <para>In fact there are two types of directives: <link
+        linkend="gloss.predefinedDirective">predefined directives</link> and
+        <link linkend="gloss.userDefinedDirective">user-defined
+        directives</link>. For user-defined directives you use
+        <literal>@</literal> instead of <literal>#</literal>, for example
+        <literal>&lt;@mydirective
+        <replaceable>parameters</replaceable>&gt;<replaceable>...</replaceable>&lt;/@mydirective&gt;</literal>.
+        Further difference is that if the directive has no nested content, you
+        must use a tag like <literal>&lt;@mydirective
+        <replaceable>parameters</replaceable> /&gt;</literal>, similarly as in
+        XML (e.g. <literal>&lt;img <replaceable>...</replaceable>
+        /&gt;</literal>). But user-defined directives is an advanced topic
+        that will be discussed <link
+        linkend="dgui_misc_userdefdir">later</link>.</para>
+
+        <para>FTL tags, like HTML tags, must be properly nested. So the code
+        below is wrong, as the <literal>if</literal> directive is both inside
+        and outside of the nested content of the <literal>list</literal>
+        directive:</para>
+
+        <programlisting role="template">&lt;ul&gt;
+<emphasis>&lt;#list animals as animal&gt;</emphasis>
+  &lt;li&gt;${animal.name} for ${animal.price} Euros
+  <emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>
+     (except for you)
+<emphasis>&lt;/#list&gt;</emphasis> &lt;#-- WRONG! The "if" has to be closed first. --&gt;
+<emphasis>&lt;/#if&gt;</emphasis>
+&lt;/ul&gt;</programlisting>
+
+        <para>Note that FreeMarker doesn't care about the nesting of HTML
+        tags, only about the nesting of FTL tags. It just sees HTML as flat
+        text, it doesn't interpret it in any way.</para>
+
+        <para>If you try to use a non-existing directive (e.g., you mistype
+        the directive name), FreeMarker will decline to use the template and
+        produce an error message.</para>
+
+        <para>FreeMarker ignores superfluous <link
+        linkend="gloss.whiteSpace">white-space</link> inside FTL tags. So you
+        can write this:</para>
+
+        <programlisting role="template"><phrase role="markedText"><phrase
+              role="markedFTLTag">&lt;#list<phrase role="markedInvisibleText">[BR]</phrase>
+  animals       as<phrase role="markedInvisibleText">[BR]</phrase>
+     animal<phrase role="markedInvisibleText">[BR]</phrase>
+&gt;</phrase><phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;/#list    &gt;</phrase></phrase></programlisting>
+
+        <para>You may not, however, insert white-space between the
+        <literal>&lt;</literal> or <literal>&lt;/</literal> and the directive
+        name.</para>
+
+        <para>The complete list and description of all directives can be found
+        in the <xref linkend="ref_directives"/> (but I recommend that you look
+        at the chapter about expressions first).</para>
+
+        <note>
+          <para>FreeMarker can be configured to use <literal>[</literal> and
+          <literal>]</literal> instead of <literal>&lt;</literal> and
+          <literal>&gt;</literal> in the FTL tags and FTL comments, like
+          <literal>[#if user == "Big
+          Joe"]<replaceable>...</replaceable>[/#if]</literal>. For more
+          information read: <xref
+          linkend="dgui_misc_alternativesyntax"/>.</para>
+        </note>
+
+        <note>
+          <para>FreeMarker can be configured so that it understands predefined
+          directives without <literal>#</literal> (like <literal>&lt;if user
+          == "Big
+          Joe"&gt;<replaceable>...</replaceable>&lt;/if&gt;</literal>).
+          However we don't recommend the usage of this mode. For more
+          information read: <xref linkend="ref_depr_oldsyntax"/></para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_template_exp">
+        <title>Expressions</title>
+
+        <para><indexterm>
+            <primary>expression</primary>
+          </indexterm>When you supply values for interpolations or directive
+        parameters you can use variables or more complex expressions. For
+        example, if x is the number 8 and y is 5, the value of <literal>(x +
+        y)/2</literal> resolves to the numerical value 6.5.</para>
+
+        <para>Before we go into details, let's see some concrete
+        examples:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>When you supply value for interpolations: The usage of
+            interpolations is
+            <literal>${<replaceable>expression</replaceable>}</literal> where
+            expression gives the value you want to insert into the output as
+            text. So <literal>${(5 + 8)/2}</literal> prints ``6.5'' to the
+            output (or possibly ``6,5'' if the language of your output is not
+            US English).</para>
+          </listitem>
+
+          <listitem>
+            <para>When you supply a value for the directive parameter: You
+            have already seen the <literal>if</literal> directive in the
+            Getting Started section. The syntax of this directive is:
+            <literal>&lt;#if
+            <replaceable>expression</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>.
+            The expression here must evaluate to a boolean value. For example
+            in <literal>&lt;#if 2 &lt; 3&gt;</literal> the <literal>2 &lt;
+            3</literal> (2 is less than 3) is an expression which evaluates to
+            <literal>true</literal>.</para>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="exp_cheatsheet">
+          <title>Quick overview (cheat sheet)</title>
+
+          <para>This is a reminder for those of you who already know
+          FreeMarker or are just experienced programmers:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para><link linkend="dgui_template_exp_direct">Specify values
+              directly</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_string">Strings</link>:
+                  <literal>"Foo"</literal> or <literal>'Foo'</literal> or
+                  <literal>"It's \"quoted\""</literal> or <literal>'It\'s
+                  "quoted"'</literal> or
+                  <literal>r"C:\raw\string"</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="d

<TRUNCATED>


[28/35] incubator-freemarker git commit: Added an overload to Configuration.getSupportedBuiltInNames and Configuration.getSupportedBuiltInDirectiveNames that has a namingConvention parameter. This is useful for tooling as since 2.3.23 we support both cam

Posted by dd...@apache.org.
Added an overload to Configuration.getSupportedBuiltInNames and Configuration.getSupportedBuiltInDirectiveNames that has a namingConvention parameter. This is useful for tooling as since 2.3.23 we support both camel case naming convention (like s?upperCase) and the legacy one (like s?upper_case). Furthermore the old 0 argument overload will now utilize Configuration.getNamingConvention() to only return the relevant names if it's not AUTO_DETECT_NAMING_CONVENTION.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/72927166
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/72927166
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/72927166

Branch: refs/heads/2.3
Commit: 7292716630d9539bd47a40e20327006447d0c770
Parents: f20271e
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 02:03:58 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 02:03:58 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/BuiltIn.java      |  31 ++--
 src/main/java/freemarker/core/_CoreAPI.java     | 145 ++++++++++++-------
 .../java/freemarker/template/Configuration.java |  50 +++++--
 src/manual/en_US/book.xml                       |  32 ++++
 .../java/freemarker/core/CamelCaseTest.java     |   4 +-
 .../freemarker/template/ConfigurationTest.java  |  41 ++++++
 6 files changed, 225 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/72927166/src/main/java/freemarker/core/BuiltIn.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltIn.java b/src/main/java/freemarker/core/BuiltIn.java
index 144d70b..ab796b0 100644
--- a/src/main/java/freemarker/core/BuiltIn.java
+++ b/src/main/java/freemarker/core/BuiltIn.java
@@ -24,6 +24,8 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 
 import freemarker.core.BuiltInsForDates.iso_BI;
 import freemarker.core.BuiltInsForDates.iso_utc_or_local_BI;
@@ -77,8 +79,11 @@ abstract class BuiltIn extends Expression implements Cloneable {
     protected Expression target;
     protected String key;
 
+    static final Set<String> CAMEL_CASE_NAMES = new TreeSet<String>();
+    static final Set<String> SNAKE_CASE_NAMES = new TreeSet<String>();
+    
     static final int NUMBER_OF_BIS = 259;
-    static final HashMap builtins = new HashMap(NUMBER_OF_BIS * 3 / 2 + 1, 1f);
+    static final HashMap<String, BuiltIn> BUILT_INS_BY_NAME = new HashMap(NUMBER_OF_BIS * 3 / 2 + 1, 1f);
     static {
         // Note that you must update NUMBER_OF_BIS if you add new items here!
         
@@ -272,7 +277,7 @@ abstract class BuiltIn extends Expression implements Cloneable {
         putBI("url", new BuiltInsForStringsEncoding.urlBI());
         putBI("url_path", "urlPath", new BuiltInsForStringsEncoding.urlPathBI());
         putBI("values", new BuiltInsForHashes.valuesBI());
-        putBI("web_safe", "webSafe", (BuiltIn) builtins.get("html"));  // deprecated; use ?html instead
+        putBI("web_safe", "webSafe", BUILT_INS_BY_NAME.get("html"));  // deprecated; use ?html instead
         putBI("word_list", "wordList", new BuiltInsForStringsBasic.word_listBI());
         putBI("xhtml", new BuiltInsForStringsEncoding.xhtmlBI());
         putBI("xml", new BuiltInsForStringsEncoding.xmlBI());
@@ -280,18 +285,22 @@ abstract class BuiltIn extends Expression implements Cloneable {
         putBI("groups", new BuiltInsForStringsRegexp.groupsBI());
         putBI("replace", new BuiltInsForStringsRegexp.replace_reBI());
         
-        if (NUMBER_OF_BIS < builtins.size()) {
-            throw new AssertionError("Update NUMBER_OF_BIS! Should be: " + builtins.size());
+        if (NUMBER_OF_BIS < BUILT_INS_BY_NAME.size()) {
+            throw new AssertionError("Update NUMBER_OF_BIS! Should be: " + BUILT_INS_BY_NAME.size());
         }
     }
     
     private static void putBI(String name, BuiltIn bi) {
-        builtins.put(name, bi);
+        BUILT_INS_BY_NAME.put(name, bi);
+        SNAKE_CASE_NAMES.add(name);
+        CAMEL_CASE_NAMES.add(name);
     }
 
-    private static void putBI(String name, String nameCamelCase, BuiltIn bi) {
-        builtins.put(name, bi);
-        builtins.put(nameCamelCase, bi);
+    private static void putBI(String nameSnakeCase, String nameCamelCase, BuiltIn bi) {
+        BUILT_INS_BY_NAME.put(nameSnakeCase, bi);
+        BUILT_INS_BY_NAME.put(nameCamelCase, bi);
+        SNAKE_CASE_NAMES.add(nameSnakeCase);
+        CAMEL_CASE_NAMES.add(nameCamelCase);
     }
     
     /**
@@ -303,7 +312,7 @@ abstract class BuiltIn extends Expression implements Cloneable {
     static BuiltIn newBuiltIn(int incompatibleImprovements, Expression target, Token keyTk,
             FMParserTokenManager tokenManager) throws ParseException {
         String key = keyTk.image;
-        BuiltIn bi = (BuiltIn) builtins.get(key);
+        BuiltIn bi = BUILT_INS_BY_NAME.get(key);
         if (bi == null) {
             StringBuilder buf = new StringBuilder("Unknown built-in: ").append(StringUtil.jQuote(key)).append(". ");
             
@@ -311,8 +320,8 @@ abstract class BuiltIn extends Expression implements Cloneable {
                     "Help (latest version): http://freemarker.org/docs/ref_builtins.html; "
                     + "you're using FreeMarker ").append(Configuration.getVersion()).append(".\n" 
                     + "The alphabetical list of built-ins:");
-            List names = new ArrayList(builtins.keySet().size());
-            names.addAll(builtins.keySet());
+            List names = new ArrayList(BUILT_INS_BY_NAME.keySet().size());
+            names.addAll(BUILT_INS_BY_NAME.keySet());
             Collections.sort(names);
             char lastLetter = 0;
             

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/72927166/src/main/java/freemarker/core/_CoreAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_CoreAPI.java b/src/main/java/freemarker/core/_CoreAPI.java
index 826f29e..df95196 100644
--- a/src/main/java/freemarker/core/_CoreAPI.java
+++ b/src/main/java/freemarker/core/_CoreAPI.java
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.Set;
 import java.util.TreeSet;
 
+import freemarker.template.Configuration;
 import freemarker.template.Template;
 import freemarker.template.TemplateDirectiveBody;
 import freemarker.template.TemplateException;
@@ -45,69 +46,101 @@ public class _CoreAPI {
 
     // Can't be instantiated
     private _CoreAPI() { }
+
+    private static void addName(Set<String> allNames, Set<String> lcNames, Set<String> ccNames,
+            String commonName) {
+        allNames.add(commonName);
+        lcNames.add(commonName);
+        ccNames.add(commonName);
+    }
+    
+    private static void addName(Set<String> allNames, Set<String> lcNames, Set<String> ccNames,
+            String lcName, String ccName) {
+        allNames.add(lcName);
+        allNames.add(ccName);
+        lcNames.add(lcName);
+        ccNames.add(ccName);
+    }
     
-    public static final Set/*<String>*/ BUILT_IN_DIRECTIVE_NAMES;
+    public static final Set<String> ALL_BUILT_IN_DIRECTIVE_NAMES;
+    public static final Set<String> LEGACY_BUILT_IN_DIRECTIVE_NAMES;
+    public static final Set<String> CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES;
     static {
-        Set/*<String>*/ names = new TreeSet();
-        names.add("assign");
-        names.add("attempt");
-        names.add("autoEsc");
-        names.add("autoesc");
-        names.add("break");
-        names.add("call");
-        names.add("case");
-        names.add("comment");
-        names.add("compress");
-        names.add("default");
-        names.add("else");
-        names.add("elseif");
-        names.add("elseIf");
-        names.add("escape");
-        names.add("fallback");
-        names.add("flush");
-        names.add("foreach");
-        names.add("forEach");
-        names.add("ftl");
-        names.add("function");
-        names.add("global");
-        names.add("if");
-        names.add("import");
-        names.add("include");
-        names.add("items");
-        names.add("list");
-        names.add("local");
-        names.add("lt");
-        names.add("macro");
-        names.add("nested");
-        names.add("noautoesc");
-        names.add("noAutoEsc");
-        names.add("noescape");
-        names.add("noEscape");
-        names.add("noparse");
-        names.add("noParse");
-        names.add("nt");
-        names.add("outputformat");
-        names.add("outputFormat");
-        names.add("recover");
-        names.add("recurse");
-        names.add("return");
-        names.add("rt");
-        names.add("sep");
-        names.add("setting");
-        names.add("stop");
-        names.add("switch");
-        names.add("t");
-        names.add("transform");
-        names.add("visit");
-        BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(names);
+        Set<String> allNames = new TreeSet();
+        Set<String> lcNames = new TreeSet();
+        Set<String> ccNames = new TreeSet();
+        
+        addName(allNames, lcNames, ccNames, "assign");
+        addName(allNames, lcNames, ccNames, "attempt");
+        addName(allNames, lcNames, ccNames, "autoesc", "autoEsc");
+        addName(allNames, lcNames, ccNames, "break");
+        addName(allNames, lcNames, ccNames, "call");
+        addName(allNames, lcNames, ccNames, "case");
+        addName(allNames, lcNames, ccNames, "comment");
+        addName(allNames, lcNames, ccNames, "compress");
+        addName(allNames, lcNames, ccNames, "default");
+        addName(allNames, lcNames, ccNames, "else");
+        addName(allNames, lcNames, ccNames, "elseif", "elseIf");
+        addName(allNames, lcNames, ccNames, "escape");
+        addName(allNames, lcNames, ccNames, "fallback");
+        addName(allNames, lcNames, ccNames, "flush");
+        addName(allNames, lcNames, ccNames, "foreach", "forEach");
+        addName(allNames, lcNames, ccNames, "ftl");
+        addName(allNames, lcNames, ccNames, "function");
+        addName(allNames, lcNames, ccNames, "global");
+        addName(allNames, lcNames, ccNames, "if");
+        addName(allNames, lcNames, ccNames, "import");
+        addName(allNames, lcNames, ccNames, "include");
+        addName(allNames, lcNames, ccNames, "items");
+        addName(allNames, lcNames, ccNames, "list");
+        addName(allNames, lcNames, ccNames, "local");
+        addName(allNames, lcNames, ccNames, "lt");
+        addName(allNames, lcNames, ccNames, "macro");
+        addName(allNames, lcNames, ccNames, "nested");
+        addName(allNames, lcNames, ccNames, "noautoesc", "noAutoEsc");
+        addName(allNames, lcNames, ccNames, "noescape", "noEscape");
+        addName(allNames, lcNames, ccNames, "noparse", "noParse");
+        addName(allNames, lcNames, ccNames, "nt");
+        addName(allNames, lcNames, ccNames, "outputformat", "outputFormat");
+        addName(allNames, lcNames, ccNames, "recover");
+        addName(allNames, lcNames, ccNames, "recurse");
+        addName(allNames, lcNames, ccNames, "return");
+        addName(allNames, lcNames, ccNames, "rt");
+        addName(allNames, lcNames, ccNames, "sep");
+        addName(allNames, lcNames, ccNames, "setting");
+        addName(allNames, lcNames, ccNames, "stop");
+        addName(allNames, lcNames, ccNames, "switch");
+        addName(allNames, lcNames, ccNames, "t");
+        addName(allNames, lcNames, ccNames, "transform");
+        addName(allNames, lcNames, ccNames, "visit");
+        
+        ALL_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(allNames);
+        LEGACY_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(lcNames);
+        CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(ccNames);
     }
     
     /**
      * Returns the names of the currently supported "built-ins" ({@code expr?builtin_name}-like things).
-     * @return {@link Set} of {@link String}-s. 
+     * 
+     * @param namingConvention
+     *            One of {@link Configuration#AUTO_DETECT_NAMING_CONVENTION},
+     *            {@link Configuration#LEGACY_NAMING_CONVENTION}, and
+     *            {@link Configuration#CAMEL_CASE_NAMING_CONVENTION}. If it's
+     *            {@link Configuration#AUTO_DETECT_NAMING_CONVENTION} then the union of the names in all the naming
+     *            conventions is returned.
      */
-    public static Set/*<String>*/ getSupportedBuiltInNames() {
-        return Collections.unmodifiableSet(BuiltIn.builtins.keySet());
+    public static Set<String> getSupportedBuiltInNames(int namingConvention) {
+        Set<String> names;
+        if (namingConvention == Configuration.AUTO_DETECT_NAMING_CONVENTION) {
+            names = BuiltIn.BUILT_INS_BY_NAME.keySet();
+        } else if (namingConvention == Configuration.LEGACY_NAMING_CONVENTION) {
+            names = BuiltIn.SNAKE_CASE_NAMES;
+        } else if (namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION) {
+            names = BuiltIn.CAMEL_CASE_NAMES;
+        } else {
+            throw new IllegalArgumentException("Unsupported naming convention constant: " + namingConvention);
+        }
+        return Collections.unmodifiableSet(names);
     }
     
     public static void appendInstructionStackItem(TemplateElement stackEl, StringBuilder sb) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/72927166/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index bd7d46c..8be37db 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -3157,30 +3157,62 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     /**
+     * Same as {@link #getSupportedBuiltInNames(int)} with argument {@link #getNamingConvention()}.
+     * 
+     * @since 2.3.20
+     */
+    public Set getSupportedBuiltInNames() {
+        return getSupportedBuiltInNames(getNamingConvention());
+    }
+
+    /**
      * Returns the names of the supported "built-ins". These are the ({@code expr?builtin_name}-like things). As of this
      * writing, this information doesn't depend on the configuration options, so it could be a static method, but
      * to be future-proof, it's an instance method. 
      * 
-     * @return {@link Set} of {@link String}-s.
+     * @param namingConvention
+     *            One of {@link #AUTO_DETECT_NAMING_CONVENTION}, {@link #LEGACY_NAMING_CONVENTION}, and
+     *            {@link #CAMEL_CASE_NAMING_CONVENTION}. If it's {@link #AUTO_DETECT_NAMING_CONVENTION} then the union
+     *            of the names in all the naming conventions is returned. 
      * 
-     * @since 2.3.20
+     * @since 2.3.24
      */
-    public Set getSupportedBuiltInNames() {
-        return _CoreAPI.getSupportedBuiltInNames();
+    public Set<String> getSupportedBuiltInNames(int namingConvention) {
+        return _CoreAPI.getSupportedBuiltInNames(namingConvention);
     }
     
     /**
-     * Returns the names of the directives that are predefined by FreeMarker. These are the things that you call like
-     * <tt>&lt;#directiveName ...&gt;</tt>.
-     * 
-     * @return {@link Set} of {@link String}-s.
+     * Same as {@link #getSupportedBuiltInDirectiveNames(int)} with argument {@link #getNamingConvention()}.
      * 
      * @since 2.3.21
      */
     public Set getSupportedBuiltInDirectiveNames() {
-        return _CoreAPI.BUILT_IN_DIRECTIVE_NAMES;
+        return getSupportedBuiltInDirectiveNames(getNamingConvention());
     }
 
+    /**
+     * Returns the names of the directives that are predefined by FreeMarker. These are the things that you call like
+     * <tt>&lt;#directiveName ...&gt;</tt>.
+     * 
+     * @param namingConvention
+     *            One of {@link #AUTO_DETECT_NAMING_CONVENTION}, {@link #LEGACY_NAMING_CONVENTION}, and
+     *            {@link #CAMEL_CASE_NAMING_CONVENTION}. If it's {@link #AUTO_DETECT_NAMING_CONVENTION} then the union
+     *            of the names in all the naming conventions is returned. 
+     * 
+     * @since 2.3.24
+     */
+    public Set<String> getSupportedBuiltInDirectiveNames(int namingConvention) {
+        if (namingConvention == AUTO_DETECT_NAMING_CONVENTION) {
+            return _CoreAPI.ALL_BUILT_IN_DIRECTIVE_NAMES;
+        } else if (namingConvention == LEGACY_NAMING_CONVENTION) {
+            return _CoreAPI.LEGACY_BUILT_IN_DIRECTIVE_NAMES;
+        } else if (namingConvention == CAMEL_CASE_NAMING_CONVENTION) {
+            return _CoreAPI.CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES;
+        } else {
+            throw new IllegalArgumentException("Unsupported naming convention constant: " + namingConvention);
+        }
+    }
+    
     private static String getRequiredVersionProperty(Properties vp, String properyName) {
         String s = vp.getProperty(properyName);
         if (s == null) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/72927166/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 6318f75..9c888d2 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26986,6 +26986,22 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Added an overload to
+              <literal>Configuration.getSupportedBuiltInNames</literal> and
+              <literal>Configuration.getSupportedBuiltInDirectiveNames</literal>
+              that has a <literal>namingConvention</literal> parameter. This
+              is useful for tooling as since 2.3.23 we support both camel case
+              naming convention (like
+              <literal><replaceable>s</replaceable>?upperCase</literal>) and
+              the legacy one (like
+              <literal><replaceable>s</replaceable>?upper_case</literal>).
+              Furthermore the old 0 argument overload will now utilize
+              <literal>Configuration.getNamingConvention()</literal> to only
+              return the relevant names if it's not
+              <literal>AUTO_DETECT_NAMING_CONVENTION</literal>.</para>
+            </listitem>
+
+            <listitem>
               <para>Internal reworking to simplify the AST (the
               <literal>TemplateElement</literal> structure). The API related
               technically public API was marked as internal for a good while.
@@ -27356,6 +27372,22 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 </listitem>
               </itemizedlist>
             </listitem>
+
+            <listitem>
+              <para>Added an overload to
+              <literal>Configuration.getSupportedBuiltInNames</literal> and
+              <literal>Configuration.getSupportedBuiltInDirectiveNames</literal>
+              that has a <literal>namingConvention</literal> parameter. This
+              is useful for tooling as since 2.3.23 we support both camel case
+              naming convention (like
+              <literal><replaceable>s</replaceable>?upperCase</literal>) and
+              the legacy one (like
+              <literal><replaceable>s</replaceable>?upper_case</literal>).
+              Furthermore the old 0 argument overload will now utilize
+              <literal>Configuration.getNamingConvention()</literal> to only
+              return the relevant names if it's not
+              <literal>AUTO_DETECT_NAMING_CONVENTION</literal>.</para>
+            </listitem>
           </itemizedlist>
         </section>
       </section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/72927166/src/test/java/freemarker/core/CamelCaseTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/CamelCaseTest.java b/src/test/java/freemarker/core/CamelCaseTest.java
index ece5730..16232c1 100644
--- a/src/test/java/freemarker/core/CamelCaseTest.java
+++ b/src/test/java/freemarker/core/CamelCaseTest.java
@@ -256,8 +256,8 @@ public class CamelCaseTest extends TemplateTest {
         assertContainsBothNamingStyles(getConfiguration().getSupportedBuiltInNames(), new NamePairAssertion() {
 
             public void assertPair(String name1, String name2) {
-                BuiltIn bi1  = (BuiltIn) BuiltIn.builtins.get(name1);
-                BuiltIn bi2 = (BuiltIn) BuiltIn.builtins.get(name2);
+                BuiltIn bi1  = (BuiltIn) BuiltIn.BUILT_INS_BY_NAME.get(name1);
+                BuiltIn bi2 = (BuiltIn) BuiltIn.BUILT_INS_BY_NAME.get(name2);
                 assertTrue("\"" + name1 + "\" and \"" + name2 + "\" doesn't belong to the same BI object.",
                         bi1 == bi2);
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/72927166/src/test/java/freemarker/template/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index 9e69d90..39ee7b6 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -32,6 +32,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 
 import org.junit.Test;
@@ -1640,6 +1641,46 @@ public class ConfigurationTest extends TestCase {
         }
     }
     
+    @Test
+    public void testGetSupportedBuiltInDirectiveNames() {
+        Configuration cfg = new Configuration();
+        
+        Set<String> allNames = cfg.getSupportedBuiltInDirectiveNames(Configuration.AUTO_DETECT_NAMING_CONVENTION);
+        Set<String> lNames = cfg.getSupportedBuiltInDirectiveNames(Configuration.LEGACY_NAMING_CONVENTION);
+        Set<String> cNames = cfg.getSupportedBuiltInDirectiveNames(Configuration.CAMEL_CASE_NAMING_CONVENTION);
+        
+        checkNamingConventionNameSets(allNames, lNames, cNames);
+        
+        for (String name : cNames) {
+            assertThat(name.toLowerCase(), isIn(lNames));
+        }
+    }
+
+    @Test
+    public void testGetSupportedBuiltInNames() {
+        Configuration cfg = new Configuration();
+        
+        Set<String> allNames = cfg.getSupportedBuiltInNames(Configuration.AUTO_DETECT_NAMING_CONVENTION);
+        Set<String> lNames = cfg.getSupportedBuiltInNames(Configuration.LEGACY_NAMING_CONVENTION);
+        Set<String> cNames = cfg.getSupportedBuiltInNames(Configuration.CAMEL_CASE_NAMING_CONVENTION);
+        
+        checkNamingConventionNameSets(allNames, lNames, cNames);
+    }
+
+    private void checkNamingConventionNameSets(Set<String> allNames, Set<String> lNames, Set<String> cNames) {
+        for (String name : lNames) {
+            assertThat(allNames, hasItem(name));
+            assertTrue("Should be all-lowercase: " + name, name.equals(name.toLowerCase()));
+        }
+        for (String name : cNames) {
+            assertThat(allNames, hasItem(name));
+        }
+        for (String name : allNames) {
+            assertThat(name, anyOf(isIn(lNames), isIn(cNames)));
+        }
+        assertEquals(lNames.size(), cNames.size());
+    }
+    
     @SuppressWarnings("boxing")
     private void assertStartsWith(List<String> list, List<String> headList) {
         int index = 0;


[10/35] incubator-freemarker git commit: XMLOutputFormat uses application/xml instead of text/xml

Posted by dd...@apache.org.
XMLOutputFormat uses application/xml instead of text/xml


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/7b0a1c41
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/7b0a1c41
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/7b0a1c41

Branch: refs/heads/2.3
Commit: 7b0a1c414a21df7eaf189fcb8048c5932a6ac7d9
Parents: aa53f15
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 18:19:07 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 18:19:07 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/XMLOutputFormat.java            | 2 +-
 src/manual/en_US/book.xml                                     | 7 ++++++-
 .../java/freemarker/core/CombinedMarkupOutputFormatTest.java  | 2 +-
 src/test/java/freemarker/core/XMLOutputFormatTest.java        | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7b0a1c41/src/main/java/freemarker/core/XMLOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/XMLOutputFormat.java b/src/main/java/freemarker/core/XMLOutputFormat.java
index 41b0a6f..9c45b7d 100644
--- a/src/main/java/freemarker/core/XMLOutputFormat.java
+++ b/src/main/java/freemarker/core/XMLOutputFormat.java
@@ -47,7 +47,7 @@ public final class XMLOutputFormat extends CommonMarkupOutputFormat<TemplateXMLO
 
     @Override
     public String getMimeType() {
-        return "text/xml";
+        return "application/xml";
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7b0a1c41/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index acfead4..b997455 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -5334,7 +5334,7 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
                 <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
                 <literal>&amp;apos;</literal></td>
 
-                <td><literal>text/xml</literal></td>
+                <td><literal>application/xml</literal></td>
 
                 <td><literal>XMLOutputFormat.INSTANCE</literal></td>
               </tr>
@@ -26458,6 +26458,11 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para><literal>XMLOutputFormat</literal> now uses
+              application/xml MIME type instead of text/xml MIME type</para>
+            </listitem>
+
+            <listitem>
               <para>Added new built-in: <literal>is_markup_output</literal>,
               returns <literal>true</literal> if the value is of type
               <quote>markup output</quote>.</para>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7b0a1c41/src/test/java/freemarker/core/CombinedMarkupOutputFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/CombinedMarkupOutputFormatTest.java b/src/test/java/freemarker/core/CombinedMarkupOutputFormatTest.java
index dc7dace..fd2ce64 100644
--- a/src/test/java/freemarker/core/CombinedMarkupOutputFormatTest.java
+++ b/src/test/java/freemarker/core/CombinedMarkupOutputFormatTest.java
@@ -187,7 +187,7 @@ public class CombinedMarkupOutputFormatTest {
     @Test
     public void testGetMimeType() {
         assertEquals("text/html", HTML_RTF.getMimeType());
-        assertEquals("text/xml", XML_XML.getMimeType());
+        assertEquals("application/xml", XML_XML.getMimeType());
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7b0a1c41/src/test/java/freemarker/core/XMLOutputFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/XMLOutputFormatTest.java b/src/test/java/freemarker/core/XMLOutputFormatTest.java
index 4b65415..f9377d5 100644
--- a/src/test/java/freemarker/core/XMLOutputFormatTest.java
+++ b/src/test/java/freemarker/core/XMLOutputFormatTest.java
@@ -54,7 +54,7 @@ public class XMLOutputFormatTest {
     
     @Test
     public void testGetMimeType() {
-        assertEquals("text/xml", INSTANCE.getMimeType());
+        assertEquals("application/xml", INSTANCE.getMimeType());
     }
     
 }


[26/35] incubator-freemarker git commit: (Removed unused class)

Posted by dd...@apache.org.
(Removed unused class)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/95859c38
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/95859c38
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/95859c38

Branch: refs/heads/2.3
Commit: 95859c384f13a13fad8c8042a6f11970cca04952
Parents: 177b6a1
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 22:38:18 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 22:38:18 2015 +0100

----------------------------------------------------------------------
 .../freemarker/core/StackTraceVisibility.java   | 26 --------------------
 1 file changed, 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/95859c38/src/main/java/freemarker/core/StackTraceVisibility.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/StackTraceVisibility.java b/src/main/java/freemarker/core/StackTraceVisibility.java
deleted file mode 100644
index 7083246..0000000
--- a/src/main/java/freemarker/core/StackTraceVisibility.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package freemarker.core;
-
-
-public enum StackTraceVisibility {
-    
-    ALWAYS, WHEN_ON_TOP, NEVER
-
-}


[25/35] incubator-freemarker git commit: Added missing copyright comments to some new files.

Posted by dd...@apache.org.
Added missing copyright comments to some new files.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/177b6a19
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/177b6a19
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/177b6a19

Branch: refs/heads/2.3
Commit: 177b6a19fe611d866da0b5772a020c75b76a6678
Parents: 0245962
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 22:37:19 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 22:37:19 2015 +0100

----------------------------------------------------------------------
 .../java/freemarker/core/CSSOutputFormat.java     | 18 ++++++++++++++++++
 .../java/freemarker/core/JSONOutputFormat.java    | 18 ++++++++++++++++++
 .../freemarker/core/JavaScriptOutputFormat.java   | 18 ++++++++++++++++++
 .../java/freemarker/core/LocalContextStack.java   | 18 ++++++++++++++++++
 .../freemarker/core/StackTraceVisibility.java     | 18 ++++++++++++++++++
 .../core/TemplateElementArrayBuilder.java         | 18 ++++++++++++++++++
 .../freemarker/core/TemplateElementsToVisit.java  | 18 ++++++++++++++++++
 .../freemarker/core/CoercionToTextualTest.java    | 18 ++++++++++++++++++
 .../freemarker/core/IncludeAndImportTest.java     | 18 ++++++++++++++++++
 .../java/freemarker/core/IteratorIssuesTest.java  | 18 ++++++++++++++++++
 src/test/java/freemarker/ext/dom/DOMTest.java     | 18 ++++++++++++++++++
 .../freemarker/manual/CustomFormatsExample.java   | 18 ++++++++++++++++++
 .../UnitAwareTemplateNumberFormatFactory.java     | 18 ++++++++++++++++++
 .../manual/UnitAwareTemplateNumberModel.java      | 18 ++++++++++++++++++
 14 files changed, 252 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/CSSOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/CSSOutputFormat.java b/src/main/java/freemarker/core/CSSOutputFormat.java
index e60e1c5..6b2cf3c 100644
--- a/src/main/java/freemarker/core/CSSOutputFormat.java
+++ b/src/main/java/freemarker/core/CSSOutputFormat.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/JSONOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/JSONOutputFormat.java b/src/main/java/freemarker/core/JSONOutputFormat.java
index 7b0d9fe..8577198 100644
--- a/src/main/java/freemarker/core/JSONOutputFormat.java
+++ b/src/main/java/freemarker/core/JSONOutputFormat.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/JavaScriptOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/JavaScriptOutputFormat.java b/src/main/java/freemarker/core/JavaScriptOutputFormat.java
index a6375af..c766af9 100644
--- a/src/main/java/freemarker/core/JavaScriptOutputFormat.java
+++ b/src/main/java/freemarker/core/JavaScriptOutputFormat.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/LocalContextStack.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/LocalContextStack.java b/src/main/java/freemarker/core/LocalContextStack.java
index 5f556bf..c22a09f 100644
--- a/src/main/java/freemarker/core/LocalContextStack.java
+++ b/src/main/java/freemarker/core/LocalContextStack.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/StackTraceVisibility.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/StackTraceVisibility.java b/src/main/java/freemarker/core/StackTraceVisibility.java
index 6fcd877..7083246 100644
--- a/src/main/java/freemarker/core/StackTraceVisibility.java
+++ b/src/main/java/freemarker/core/StackTraceVisibility.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/TemplateElementArrayBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateElementArrayBuilder.java b/src/main/java/freemarker/core/TemplateElementArrayBuilder.java
index e44f12e..0126c19 100644
--- a/src/main/java/freemarker/core/TemplateElementArrayBuilder.java
+++ b/src/main/java/freemarker/core/TemplateElementArrayBuilder.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 import freemarker.template.utility.CollectionUtils;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/main/java/freemarker/core/TemplateElementsToVisit.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateElementsToVisit.java b/src/main/java/freemarker/core/TemplateElementsToVisit.java
index 6159f13..0b96988 100644
--- a/src/main/java/freemarker/core/TemplateElementsToVisit.java
+++ b/src/main/java/freemarker/core/TemplateElementsToVisit.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 import java.util.Collection;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/core/CoercionToTextualTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/CoercionToTextualTest.java b/src/test/java/freemarker/core/CoercionToTextualTest.java
index c35ace6..7b5b23b 100644
--- a/src/test/java/freemarker/core/CoercionToTextualTest.java
+++ b/src/test/java/freemarker/core/CoercionToTextualTest.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 import java.io.IOException;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/core/IncludeAndImportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/IncludeAndImportTest.java b/src/test/java/freemarker/core/IncludeAndImportTest.java
index 6cd9d32..6123e9a 100644
--- a/src/test/java/freemarker/core/IncludeAndImportTest.java
+++ b/src/test/java/freemarker/core/IncludeAndImportTest.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 import java.io.IOException;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/core/IteratorIssuesTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/IteratorIssuesTest.java b/src/test/java/freemarker/core/IteratorIssuesTest.java
index 453da4a..0c43158 100644
--- a/src/test/java/freemarker/core/IteratorIssuesTest.java
+++ b/src/test/java/freemarker/core/IteratorIssuesTest.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.core;
 
 import java.util.Arrays;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/ext/dom/DOMTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/dom/DOMTest.java b/src/test/java/freemarker/ext/dom/DOMTest.java
index 59f1392..4a96a83 100644
--- a/src/test/java/freemarker/ext/dom/DOMTest.java
+++ b/src/test/java/freemarker/ext/dom/DOMTest.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.ext.dom;
 
 import static org.hamcrest.Matchers.*;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/manual/CustomFormatsExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/CustomFormatsExample.java b/src/test/java/freemarker/manual/CustomFormatsExample.java
index 31de217..e438b54 100644
--- a/src/test/java/freemarker/manual/CustomFormatsExample.java
+++ b/src/test/java/freemarker/manual/CustomFormatsExample.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.manual;
 
 import java.io.IOException;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java b/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
index df179d4..c737653 100644
--- a/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
+++ b/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.manual;
 
 import java.util.Locale;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/177b6a19/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java b/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
index fc58431..99a453d 100644
--- a/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
+++ b/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.manual;
 
 import freemarker.template.TemplateModelException;


[18/35] incubator-freemarker git commit: (Manual adjustments in formatting related parts)

Posted by dd...@apache.org.
(Manual adjustments in formatting related parts)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/ea391539
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/ea391539
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/ea391539

Branch: refs/heads/2.3
Commit: ea39153956c0860927ef516e3eeed232d5dc89c1
Parents: f112ed6
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 26 19:59:19 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Dec 26 19:59:19 2015 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 64 ++++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ea391539/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index b68ff4c..51fae1f 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -15003,21 +15003,22 @@ rif: foo XYr baar</programlisting>
             <secondary>number</secondary>
           </indexterm>
 
-          <para>Converts a number to a string. It uses the default format that
-          the programmer has specified via the
+          <para>Converts a number to a string. In its simplest form
+          (<literal><replaceable>expression</replaceable>?string</literal>) it
+          uses the default format that the programmer has specified via the
           <literal>number_format</literal> and the <literal>locale</literal>
-          settings. You can also specify a number format explicitly with this
-          built-in, as it will be shown later.</para>
+          configuration settings. You can also specify a number format
+          explicitly with this built-in, as it will be shown later.</para>
 
           <para>There are four predefined number formats:
           <literal>computer</literal>, <literal>currency</literal>,
           <literal>number</literal>, and <literal>percent</literal>. The exact
           meaning of these is locale (nationality) specific, and is controlled
-          by the Java platform installation, rather than by FreeMarker, except
-          for <literal>computer</literal>, which uses the same formatting as
-          <link linkend="ref_builtin_c">the <literal>c</literal>
-          built-in</link>. There can also be programmer-defined formats, whose
-          name starts with <literal>@</literal> (programmers <link
+          by the Java platform installation, not by FreeMarker, except for
+          <literal>computer</literal>, which uses the same formatting as <link
+          linkend="ref_builtin_c">the <literal>c</literal> built-in</link>.
+          There can also be programmer-defined formats, whose name starts with
+          <literal>@</literal> (programmers <link
           linkend="pgui_config_custom_formats">see more here...</link>). You
           can use these predefined formats like this:</para>
 
@@ -15039,8 +15040,9 @@ $42.00
 42</programlisting>
 
           <para>The output of first three expressions is identical because the
-          first two expressions use the default format, which is "number"
-          here. You can change this default using a setting:</para>
+          first two expressions use the default format, which is
+          <quote>number</quote> here. You can change this default using a
+          setting:</para>
 
           <programlisting role="template">&lt;#setting number_format="currency"&gt;
 &lt;#assign x=42&gt;
@@ -15058,20 +15060,23 @@ $42.00
 $42.00
 4,200%</programlisting>
 
-          <para>since the default number format was set to "currency".</para>
+          <para>since the default number format was set to
+          <quote>currency</quote>.</para>
 
           <para>You can also refer to named custom formats that were defined
           when configuring FreeMarker (programmers <link
           linkend="pgui_config_custom_formats">see more here</link>),
           like:</para>
 
-          <programlisting role="template">${x?strong.@price}
-${x?strong.@weight}</programlisting>
+          <programlisting role="template">${x?string.@price}
+${x?string.@weight}</programlisting>
 
           <para>where the custom format names were <quote>price</quote> and
-          <quote>weight</quote>. Note that hence the templates can just refer
-          to the application-domain meaning, and the exact format can be
-          specified outside the templates, on a single central place.</para>
+          <quote>weight</quote>. This way the templates can just refer to the
+          application-domain meaning, and the exact format can be specified
+          outside the templates, on a single central place. (Programmers can
+          read about <link linkend="pgui_config_custom_formats">defining such
+          named formats here...</link>)</para>
 
           <para>Beside named formats, you can specify number format patterns
           directly, using the <link
@@ -15803,28 +15808,28 @@ ${openingTime?string.short}
 ${openingTime?string.medium}
 ${openingTime?string.long}
 ${openingTime?string.full}
-${openingTime?string.xs}
-${openingTime?string.iso}
+${openingTime?string.xs} &lt;#-- XSD xs:time --&gt;
+${openingTime?string.iso} &lt;#-- ISO 8601 time --&gt;
 
 ${nextDiscountDay?string.short}
 ${nextDiscountDay?string.medium}
 ${nextDiscountDay?string.long}
 ${nextDiscountDay?string.full}
-${nextDiscountDay?string.xs}
-${nextDiscountDay?string.iso}
+${nextDiscountDay?string.xs} &lt;#-- XSD xs:date --&gt;
+${nextDiscountDay?string.iso} &lt;#-- ISO 8601 date --&gt;
 
 ${lastUpdated?string.short}
 ${lastUpdated?string.medium}
 ${lastUpdated?string.long}
 ${lastUpdated?string.full}
 ${lastUpdated?string.medium_short} &lt;#-- medium date, short time --&gt;
-${lastUpdated?string.xs}
-${lastUpdated?string.iso}
+${lastUpdated?string.xs} &lt;#-- XSD xs:dateTime --&gt;
+${lastUpdated?string.iso} &lt;#-- ISO 8601 combined date and time --&gt;
 
-&lt;#-- <link linkend="pgui_config_custom_formats">Programmer-defined formats</link> (starts with @ + letter): --&gt;
-${lastUpdated?string.@lastMod}
+&lt;#-- <link linkend="pgui_config_custom_formats">Programmer-defined named format</link> (@ + name): --&gt;
+${lastUpdated?string.@fileDate}
 
-&lt;#-- More advanced ISO 8601-related formats: --&gt;
+&lt;#-- Advanced ISO 8601 and XSD formatting: --&gt;
 ${lastUpdated?string.iso_m_u}
 ${lastUpdated?string.xs_ms_nz}
 
@@ -15870,9 +15875,12 @@ Tue, Apr 8, '03
 2003</programlisting>
 
           <para>Note that with custom formats like in
-          <literal>lastUpdated?string.@lastMod</literal> above, templates can
+          <literal>lastUpdated?string.@fileDate</literal> above, templates can
           just refer to the application-domain meaning, and the exact format
-          can be specified outside the templates, on a central place.</para>
+          can be specified outside the templates, on a central place.
+          (Programmers can read about <link
+          linkend="pgui_config_custom_formats">defining such named formats
+          here...</link>)</para>
 
           <warning>
             <para>Unfortunately, because of the limitations of the Java


[24/35] incubator-freemarker git commit: Two freemarker.ext.dom xmlns prefix outputting bugs fixed:

Posted by dd...@apache.org.
Two freemarker.ext.dom xmlns prefix outputting bugs fixed:

- Bug fixed: The @@qname of elements that belong to the XML namespace declared as the default via <#ftl ns_prefixes={'D':'...', ... }> no longer starts with D:, instead they just start with no name space prefix.
- Bug fixed: In the markup returned by the @@markup key, when there were multiple namespaces for which there was no prefix associated with via <#ftl ns_prefixes=...>, all those namespaces were assigned to the same auto-generated xmlns prefix (usually a). Now they will get a, b, c, etc. prefixes.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/02459623
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/02459623
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/02459623

Branch: refs/heads/2.3
Commit: 02459623e11efc5ddce66e6a8310c8f628272102
Parents: 33ba278
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 22:35:43 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 22:35:43 2015 +0100

----------------------------------------------------------------------
 .../java/freemarker/ext/dom/ElementModel.java   |   2 +-
 .../java/freemarker/ext/dom/NodeOutputter.java  |  39 +++---
 src/manual/en_US/book.xml                       | 118 ++++++++++++++-----
 src/test/java/freemarker/ext/dom/DOMTest.java   |  31 +++++
 src/test/java/freemarker/test/TemplateTest.java |  21 +++-
 5 files changed, 153 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/main/java/freemarker/ext/dom/ElementModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/dom/ElementModel.java b/src/main/java/freemarker/ext/dom/ElementModel.java
index a0f13fa..fb6fccd 100644
--- a/src/main/java/freemarker/ext/dom/ElementModel.java
+++ b/src/main/java/freemarker/ext/dom/ElementModel.java
@@ -145,7 +145,7 @@ class ElementModel extends NodeModel implements TemplateScalarModel {
         String defaultNS = env.getDefaultNS();
         String prefix;
         if (defaultNS != null && defaultNS.equals(nsURI)) {
-            prefix = Template.DEFAULT_NAMESPACE_PREFIX;
+            prefix = "";
         } else {
             prefix = env.getPrefixForNamespace(nsURI);
             

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/main/java/freemarker/ext/dom/NodeOutputter.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/dom/NodeOutputter.java b/src/main/java/freemarker/ext/dom/NodeOutputter.java
index cd59f2b..e4417a2 100644
--- a/src/main/java/freemarker/ext/dom/NodeOutputter.java
+++ b/src/main/java/freemarker/ext/dom/NodeOutputter.java
@@ -19,8 +19,8 @@
  
 package freemarker.ext.dom;
 
-import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
@@ -30,6 +30,7 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import freemarker.core.BugException;
 import freemarker.core.Environment;
 import freemarker.template.Template;
 import freemarker.template.utility.StringUtil;
@@ -41,8 +42,9 @@ class NodeOutputter {
     private String defaultNS;
     private boolean hasDefaultNS;
     private boolean explicitDefaultNSPrefix;
-    private HashMap namespacesToPrefixLookup = new HashMap();
+    private LinkedHashMap<String, String> namespacesToPrefixLookup = new LinkedHashMap<String, String>();
     private String namespaceDecl;
+    int nextGeneratedPrefixNumber = 1;
     
     NodeOutputter(Node node) {
         if (node instanceof Element) {
@@ -72,6 +74,15 @@ class NodeOutputter {
         String nsURI = n.getNamespaceURI();
         if (nsURI != null && nsURI.length() > 0) {
             String prefix = env.getPrefixForNamespace(nsURI);
+            if (prefix == null) {
+                prefix = namespacesToPrefixLookup.get(nsURI);
+                if (prefix == null) {
+                    // Assign a generated prefix:
+                    do {
+                        prefix = StringUtil.toLowerABC(nextGeneratedPrefixNumber++);
+                    } while (env.getNamespaceForPrefix(prefix) != null);
+                }
+            }
             namespacesToPrefixLookup.put(nsURI, prefix);
         } else if (hasDefaultNS && n.getNodeType() == Node.ELEMENT_NODE) {
             namespacesToPrefixLookup.put(defaultNS, Template.DEFAULT_NAMESPACE_PREFIX); 
@@ -93,28 +104,14 @@ class NodeOutputter {
             buf.append(defaultNS);
             buf.append("\"");
         }
-        for (Iterator it = namespacesToPrefixLookup.keySet().iterator(); it.hasNext(); ) {
-            String nsURI = (String) it.next();
+        for (Iterator<String> it = namespacesToPrefixLookup.keySet().iterator(); it.hasNext(); ) {
+            String nsURI = it.next();
             if (nsURI == null || nsURI.length() == 0) {
                 continue;
             }
-            String prefix = (String) namespacesToPrefixLookup.get(nsURI);
+            String prefix = namespacesToPrefixLookup.get(nsURI);
             if (prefix == null) {
-                // Okay, let's auto-assign a prefix.
-                // Should we do this??? (REVISIT)
-                for (int i = 0; i < 26; i++) {
-                    char[] cc = new char[1];
-                    cc[0] = (char) ('a' + i);
-                    prefix = new String(cc);
-                    if (env.getNamespaceForPrefix(prefix) == null) {
-                        break;
-                    }
-                    prefix = null;
-                }
-                if (prefix == null) {
-                    throw new RuntimeException("This will almost never happen!");
-                }
-                namespacesToPrefixLookup.put(nsURI, prefix);
+                throw new BugException("No xmlns prefix was associated to URI: " + nsURI);
             }
             buf.append(" xmlns");
             if (prefix.length() > 0) {
@@ -133,7 +130,7 @@ class NodeOutputter {
         if (nsURI == null || nsURI.length() == 0) {
             buf.append(n.getNodeName());
         } else {
-            String prefix = (String) namespacesToPrefixLookup.get(nsURI);
+            String prefix = namespacesToPrefixLookup.get(nsURI);
             if (prefix == null) {
                 //REVISIT!
                 buf.append(n.getNodeName());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index ba8c1b1..6318f75 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26928,22 +26928,49 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
-              <para>Bug fixed: XPath queries that has only contained
-              characters that are valid in XML element names and has also
-              contained <literal>::</literal> (which is valid in names in
-              namespace-unware documents), like
-              <literal>e['following-sibling::foo']</literal>, were interpreted
-              as literal element names (giving 0 hits) rather than as XPath
-              expressions. Note that there were no such problem with
-              <literal>e['following-sibling::*']</literal> for example, as
-              it's not a valid XML element name according the XML
-              specification. This fix can actually break applications that has
-              processed namespace unaware XML that use <literal>::</literal>
-              as part of element or attribute names, but such an application
-              is highly unlikely, unlike running into the fixed problem.
-              (Unfortunately, using
-              <literal>incompatible_improvements</literal> wasn't technically
-              possible here.)</para>
+              <para>Fixes in the XML processing feature
+              (<literal>freemarker.ext.dom</literal>):</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para>Bug fixed: XPath queries that has only contained
+                  characters that are valid in XML element names and has also
+                  contained <literal>::</literal> (which is valid in names in
+                  namespace-unware documents), like
+                  <literal>e['following-sibling::foo']</literal>, were
+                  interpreted as literal element names (giving 0 hits) rather
+                  than as XPath expressions. Note that there were no such
+                  problem with <literal>e['following-sibling::*']</literal>
+                  for example, as it's not a valid XML element name according
+                  the XML specification. This fix can actually break
+                  applications that has processed namespace unaware XML that
+                  use <literal>::</literal> as part of element or attribute
+                  names, but such an application is highly unlikely, unlike
+                  running into the fixed problem. (Unfortunately, using
+                  <literal>incompatible_improvements</literal> wasn't
+                  technically possible here.)</para>
+                </listitem>
+
+                <listitem>
+                  <para>Bug fixed: The <literal>@@qname</literal> of elements
+                  that belong to the XML namespace declared as the default via
+                  <literal>&lt;#ftl ns_prefixes={'D':'...', ...
+                  }&gt;</literal> no longer starts with <literal>D:</literal>,
+                  instead they just start with no name space prefix.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Bug fixed: In the markup returned by the
+                  <literal>@@markup</literal> key, when there were multiple
+                  namespaces for which there was no prefix associated with via
+                  <literal>&lt;#ftl
+                  ns_prefixes=<replaceable>...</replaceable>&gt;</literal>,
+                  all those namespaces were assigned to the same
+                  auto-generated <literal>xmlns</literal> prefix (usually
+                  <quote>a</quote>). Now they will get <quote>a</quote>,
+                  <quote>b</quote>, <quote>c</quote>, etc. prefixes.</para>
+                </listitem>
+              </itemizedlist>
             </listitem>
 
             <listitem>
@@ -27285,22 +27312,49 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
-              <para>Bug fixed: XPath queries that has only contained
-              characters that are valid in XML element names and has also
-              contained <literal>::</literal> (which is valid in names in
-              namespace-unware documents), like
-              <literal>e['following-sibling::foo']</literal>, were interpreted
-              as literal element names (giving 0 hits) rather than as XPath
-              expressions. Note that there were no such problem with
-              <literal>e['following-sibling::*']</literal> for example, as
-              it's not a valid XML element name according the XML
-              specification. This fix can actually break applications that has
-              processed namespace unaware XML that use <literal>::</literal>
-              as part of element or attribute names, but such an application
-              is highly unlikely, unlike running into the fixed problem.
-              (Unfortunately, using
-              <literal>incompatible_improvements</literal> wasn't technically
-              possible here.)</para>
+              <para>Fixes in the XML processing feature
+              (<literal>freemarker.ext.dom</literal>):</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para>Bug fixed: XPath queries that has only contained
+                  characters that are valid in XML element names and has also
+                  contained <literal>::</literal> (which is valid in names in
+                  namespace-unware documents), like
+                  <literal>e['following-sibling::foo']</literal>, were
+                  interpreted as literal element names (giving 0 hits) rather
+                  than as XPath expressions. Note that there were no such
+                  problem with <literal>e['following-sibling::*']</literal>
+                  for example, as it's not a valid XML element name according
+                  the XML specification. This fix can actually break
+                  applications that has processed namespace unaware XML that
+                  use <literal>::</literal> as part of element or attribute
+                  names, but such an application is highly unlikely, unlike
+                  running into the fixed problem. (Unfortunately, using
+                  <literal>incompatible_improvements</literal> wasn't
+                  technically possible here.)</para>
+                </listitem>
+
+                <listitem>
+                  <para>Bug fixed: The <literal>@@qname</literal> of elements
+                  that belong to the XML namespace declared as the default via
+                  <literal>&lt;#ftl ns_prefixes={'D':'...', ...
+                  }&gt;</literal> no longer starts with <literal>D:</literal>,
+                  instead they just start with no name space prefix.</para>
+                </listitem>
+
+                <listitem>
+                  <para>Bug fixed: In the markup returned by the
+                  <literal>@@markup</literal> key, when there were multiple
+                  namespaces for which there was no prefix associated with via
+                  <literal>&lt;#ftl
+                  ns_prefixes=<replaceable>...</replaceable>&gt;</literal>,
+                  all those namespaces were assigned to the same
+                  auto-generated <literal>xmlns</literal> prefix (usually
+                  <quote>a</quote>). Now they will get <quote>a</quote>,
+                  <quote>b</quote>, <quote>c</quote>, etc. prefixes.</para>
+                </listitem>
+              </itemizedlist>
             </listitem>
           </itemizedlist>
         </section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/test/java/freemarker/ext/dom/DOMTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/dom/DOMTest.java b/src/test/java/freemarker/ext/dom/DOMTest.java
index 182ac31..59f1392 100644
--- a/src/test/java/freemarker/ext/dom/DOMTest.java
+++ b/src/test/java/freemarker/ext/dom/DOMTest.java
@@ -28,6 +28,37 @@ public class DOMTest extends TemplateTest {
     }
 
     @Test
+    public void xmlnsPrefixes() throws Exception {
+        addDocToDataModel("<root xmlns='http://example.com/ns1' xmlns:ns2='http://example.com/ns2'>"
+                + "<a>A</a><ns2:b>B</ns2:b><c a1='1' ns2:a2='2'/></root>");
+
+        String ftlHeader = "<#ftl ns_prefixes={'D':'http://example.com/ns1', 'n2':'http://example.com/ns2'}>";
+        
+        // @@markup:
+        assertOutput("${doc.@@markup}",
+                "<a:root xmlns:a=\"http://example.com/ns1\" xmlns:b=\"http://example.com/ns2\">"
+                + "<a:a>A</a:a><b:b>B</b:b><a:c a1=\"1\" b:a2=\"2\" />"
+                + "</a:root>");
+        assertOutput(ftlHeader
+                + "${doc.@@markup}",
+                "<root xmlns=\"http://example.com/ns1\" xmlns:n2=\"http://example.com/ns2\">"
+                + "<a>A</a><n2:b>B</n2:b><c a1=\"1\" n2:a2=\"2\" /></root>");
+        assertOutput("<#ftl ns_prefixes={'D':'http://example.com/ns1'}>"
+                + "${doc.@@markup}",
+                "<root xmlns=\"http://example.com/ns1\" xmlns:a=\"http://example.com/ns2\">"
+                + "<a>A</a><a:b>B</a:b><c a1=\"1\" a:a2=\"2\" /></root>");
+        
+        // 
+        assertOutput("${doc?children[0].@@qname!'null'}", "null");
+        assertOutput("${doc?children[0]?children[1].@@qname!'null'}", "null");
+        assertOutput(ftlHeader + "${doc?children[0].@@qname}", "root");
+        assertOutput(ftlHeader + "${doc?children[0]?children[1].@@qname}", "n2:b");
+        // Unfortunately these include the xmlns attributes, but that would be non-BC to fix now:
+        assertThat(getOutput(ftlHeader + "${doc?children[0].@@start_tag}"), startsWith("<root"));
+        assertThat(getOutput(ftlHeader + "${doc?children[0]?children[1].@@start_tag}"), startsWith("<n2:b"));
+    }
+    
+    @Test
     public void namespaceUnaware() throws Exception {
         addNSUnawareDocToDataModel("<root><x:a>A</x:a><:>B</:><xyz::c>C</xyz::c></root>");
         assertOutput("${doc.root['x:a']}", "A");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/test/java/freemarker/test/TemplateTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/TemplateTest.java b/src/test/java/freemarker/test/TemplateTest.java
index 6047e2e..719ca7c 100644
--- a/src/test/java/freemarker/test/TemplateTest.java
+++ b/src/test/java/freemarker/test/TemplateTest.java
@@ -69,8 +69,12 @@ public abstract class TemplateTest {
     }
 
     protected void assertOutput(String ftl, String expectedOut) throws IOException, TemplateException {
+        assertOutput(createTemplate(ftl), expectedOut, false);
+    }
+
+    private Template createTemplate(String ftl) throws IOException {
         Template t = new Template(null, ftl, getConfiguration());
-        assertOutput(t, expectedOut, false);
+        return t;
     }
 
     protected void assertOutputForNamed(String name, String expectedOut) throws IOException, TemplateException {
@@ -101,9 +105,7 @@ public abstract class TemplateTest {
     
     protected void assertOutput(Template t, String expectedOut, boolean normalizeNewlines)
             throws TemplateException, IOException {
-        StringWriter out = new StringWriter();
-        t.process(getDataModel(), out);
-        String actualOut = out.toString();
+        String actualOut = getOutput(t);
         
         if (normalizeNewlines) {
             expectedOut = normalizeNewLines(expectedOut);
@@ -111,6 +113,17 @@ public abstract class TemplateTest {
         }
         assertEquals(expectedOut, actualOut);
     }
+
+    protected String getOutput(String ftl) throws IOException, TemplateException {
+        return getOutput(createTemplate(ftl));
+    }
+    
+    protected String getOutput(Template t) throws TemplateException, IOException {
+        StringWriter out = new StringWriter();
+        t.process(getDataModel(), out);
+        String actualOut = out.toString();
+        return actualOut;
+    }
     
     protected Configuration createConfiguration() throws Exception {
         return new Configuration(Configuration.VERSION_2_3_0);


[12/35] incubator-freemarker git commit: XHTML output format is now available by "XHTML" name by default

Posted by dd...@apache.org.
XHTML output format is now available by "XHTML" name by default


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/62f03d80
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/62f03d80
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/62f03d80

Branch: refs/heads/2.3
Commit: 62f03d80b800dc8f64ebbd0498c35f03aa3f4f48
Parents: 2944148
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 18:28:42 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 18:28:42 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/template/Configuration.java |  2 ++
 src/manual/en_US/book.xml                            | 14 ++++++++++++++
 2 files changed, 16 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62f03d80/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 4199458..0b9d5c3 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -72,6 +72,7 @@ import freemarker.core.TemplateConfiguration;
 import freemarker.core.TemplateMarkupOutputModel;
 import freemarker.core.UndefinedOutputFormat;
 import freemarker.core.UnregisteredOutputFormatException;
+import freemarker.core.XHTMLOutputFormat;
 import freemarker.core.XMLOutputFormat;
 import freemarker.core._CoreAPI;
 import freemarker.core._DelayedJQuote;
@@ -339,6 +340,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         STANDARD_OUTPUT_FORMATS = new HashMap<String, OutputFormat>();
         STANDARD_OUTPUT_FORMATS.put(UndefinedOutputFormat.INSTANCE.getName(), UndefinedOutputFormat.INSTANCE);
         STANDARD_OUTPUT_FORMATS.put(HTMLOutputFormat.INSTANCE.getName(), HTMLOutputFormat.INSTANCE);
+        STANDARD_OUTPUT_FORMATS.put(XHTMLOutputFormat.INSTANCE.getName(), XHTMLOutputFormat.INSTANCE);
         STANDARD_OUTPUT_FORMATS.put(XMLOutputFormat.INSTANCE.getName(), XMLOutputFormat.INSTANCE);
         STANDARD_OUTPUT_FORMATS.put(RTFOutputFormat.INSTANCE.getName(), RTFOutputFormat.INSTANCE);
         STANDARD_OUTPUT_FORMATS.put(PlainTextOutputFormat.INSTANCE.getName(), PlainTextOutputFormat.INSTANCE);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62f03d80/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 295f043..18d3f9e 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -5322,6 +5322,20 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
 
                 <td><literal>HTMLOutputFormat.INSTANCE</literal></td>
               </tr>
+
+              <tr>
+                <td><literal>XHTML</literal></td>
+
+                <td>Escapes <literal>&lt;</literal>, <literal>&gt;</literal>,
+                <literal>&amp;</literal>, <literal>"</literal>,
+                <literal>'</literal> as <literal>&amp;lt;</literal>,
+                <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;#39;</literal></td>
+
+                <td><literal>application/xhtml+xml</literal></td>
+
+                <td><literal>XHTMLOutputFormat.INSTANCE</literal></td>
+              </tr>
             </tbody>
 
             <tbody>


[17/35] incubator-freemarker git commit: Added custom formatter examples to the Manual. Fixed/updated JavaDoc and Manual number/date formatting related parts (mostly).

Posted by dd...@apache.org.
Added custom formatter examples to the Manual. Fixed/updated JavaDoc and Manual number/date formatting related parts (mostly).


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/f112ed6c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/f112ed6c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/f112ed6c

Branch: refs/heads/2.3
Commit: f112ed6ceb84eec5ada63ded39e0efcc2ee546bb
Parents: bec1430
Author: ddekany <dd...@apache.org>
Authored: Thu Dec 24 02:05:11 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Thu Dec 24 02:05:11 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/Configurable.java |   8 +-
 src/main/java/freemarker/core/Environment.java  |   4 +-
 .../core/TemplateDateFormatFactory.java         |   2 +-
 .../core/TemplateNumberFormatFactory.java       |   2 +-
 .../java/freemarker/template/Configuration.java |  16 +-
 src/manual/en_US/book.xml                       | 621 ++++++++++++++++++-
 .../core/BaseNTemplateNumberFormatFactory.java  |  21 +-
 .../EpochMillisTemplateDateFormatFactory.java   |  12 +-
 .../freemarker/manual/CustomFormatsExample.java |  73 +++
 .../UnitAwareTemplateNumberFormatFactory.java   |  62 ++
 .../manual/UnitAwareTemplateNumberModel.java    |  25 +
 .../manual/CustomFormatsExample-alias1.ftlh     |   4 +
 .../manual/CustomFormatsExample-alias1.ftlh.out |   4 +
 .../manual/CustomFormatsExample-alias2.ftlh     |   1 +
 .../manual/CustomFormatsExample-alias2.ftlh.out |   1 +
 .../manual/CustomFormatsExample-modelAware.ftlh |   2 +
 .../CustomFormatsExample-modelAware.ftlh.out    |   2 +
 17 files changed, 807 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index 9c82428..adba746 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -722,9 +722,9 @@ public class Configurable {
      *   <li>{@code "computer"}: The number format used by FTL's {@code c} built-in (like in {@code someNumber?c}).</li>
      *   <li>{@link java.text.DecimalFormat} pattern (like {@code "0.##"}). This syntax has a FreeMarker-specific
      *       extension, so that you can specify options like the rounding mode and the symbols used in this string. For
-     *       example, {@code ",000;; rnd=hu grp=_"} will format numbers like {@code ",000"} would, but with half-up
-     *       rounding mode, and {@code _} as the group separator. See more about "extended Java decimal format" in the
-     *       FreeMarker Manual.
+     *       example, {@code ",000;; roundingMode=halfUp groupingSeparator=_"} will format numbers like {@code ",000"}
+     *       would, but with half-up rounding mode, and {@code _} as the group separator. See more about "extended Java
+     *       decimal format" in the FreeMarker Manual.
      *       </li>
      *   <li>If the string starts with {@code @} character followed by a letter then it's interpreted as a custom number
      *       format, but only if either {@link Configuration#getIncompatibleImprovements()} is at least 2.3.24, or
@@ -779,7 +779,7 @@ public class Configurable {
      * 
      * @param customNumberFormats
      *            Can't be {@code null}. The name must start with an UNICODE letter, and can only contain UNICODE
-     *            letters and digits.
+     *            letters and digits (not {@code _}).
      * 
      * @since 2.3.24
      */

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index ef7a301..5ebf855 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -1501,7 +1501,7 @@ public final class Environment extends Configurable {
     
     /**
      * Gets a {@link TemplateDateFormat} for the specified parameters. This is mostly meant to be used by
-     * {@link TemplateDateFormatFactory} implementations to delegate to a format based on a specific format string. It's
+     * {@link TemplateDateFormatFactory} implementations to delegate to a format based on a specific format string. It
      * works well for that, as its parameters are the same low level values as the parameters of
      * {@link TemplateDateFormatFactory#get(String, int, Locale, TimeZone, boolean, Environment)}. For other tasks
      * consider the other overloads of this method.
@@ -1635,7 +1635,7 @@ public final class Environment extends Configurable {
     /**
      * Used to get the {@link TemplateDateFormat} according the date/time/datetime format settings, for the current
      * locale and time zone. See {@link #getTemplateDateFormat(String, int, Locale, TimeZone, boolean)} for the meaning
-     * of some if the parameters.
+     * of some of the parameters.
      */
     private TemplateDateFormat getTemplateDateFormat(int dateType, boolean useSQLDTTZ, boolean zonelessInput)
             throws TemplateValueFormatException {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/main/java/freemarker/core/TemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateDateFormatFactory.java b/src/main/java/freemarker/core/TemplateDateFormatFactory.java
index 23b88e0..9edda85 100644
--- a/src/main/java/freemarker/core/TemplateDateFormatFactory.java
+++ b/src/main/java/freemarker/core/TemplateDateFormatFactory.java
@@ -59,7 +59,7 @@ public abstract class TemplateDateFormatFactory extends TemplateValueFormatFacto
      *            The locale to format for. Not {@code null}. The resulting format should be bound to this locale
      *            forever (i.e. locale changes in the {@link Environment} must not be followed).
      * @param timeZone
-     *            The time zone to format for. Not {@code null}. The resulting format should be bound to this time zone
+     *            The time zone to format for. Not {@code null}. The resulting format must be bound to this time zone
      *            forever (i.e. time zone changes in the {@link Environment} must not be followed).
      * @param zonelessInput
      *            Indicates that the input Java {@link Date} is not from a time zone aware source. When this is

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateNumberFormatFactory.java b/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
index 9a404d3..e0d0bc6 100644
--- a/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
+++ b/src/main/java/freemarker/core/TemplateNumberFormatFactory.java
@@ -48,7 +48,7 @@ public abstract class TemplateNumberFormatFactory extends TemplateValueFormatFac
      *            {@code "1, 2"} (and {@code "@fooBar"} selects the factory). The format of this string is up to the
      *            {@link TemplateNumberFormatFactory} implementation. Not {@code null}, often an empty string.
      * @param locale
-     *            The locale to format for. Not {@code null}. The resulting format should be bound to this locale
+     *            The locale to format for. Not {@code null}. The resulting format must be bound to this locale
      *            forever (i.e. locale changes in the {@link Environment} must not be followed).
      * @param env
      *            The runtime environment from which the formatting was called. This is mostly meant to be used for

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 7226ef2..a913cb7 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -1801,14 +1801,14 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     
     /**
      * Sets the default output format. Usually, you should leave this on its default, which is
-     * {@link UndefinedOutputFormat#INSTANCE}, and then use standard file extensions like "ftlh" (for HTML output) and
-     * ensure that {@link #setRecognizeStandardFileExtensions(boolean)} is {@code true} (see the description of standard
-     * file extensions there too). Where that approach doesn't fit, like you have no control over the file extensions,
-     * templates can be associated to output formats with patterns matching their name (their path) using
-     * {@link #setTemplateConfigurations(TemplateConfigurationFactory)}. Last not least, if all templates will have the
-     * same output format, you may use {@link #setOutputFormat(OutputFormat)} to set a value like
-     * {@link HTMLOutputFormat#INSTANCE}, {@link XMLOutputFormat#INSTANCE}, etc. Also note templates can specify their
-     * own output format like {@code <#ftl output_format="HTML">}, which overrides any configuration settings. 
+     * {@link UndefinedOutputFormat#INSTANCE}, and then use standard file extensions like "ftlh" (for HTML) or "ftlx"
+     * (for XML) and ensure that {@link #setRecognizeStandardFileExtensions(boolean)} is {@code true} (see more there).
+     * Where you can't use standard the file extensions, templates still can be associated to output formats with
+     * patterns matching their name (their path) using {@link #setTemplateConfigurations(TemplateConfigurationFactory)}.
+     * But if all templates will have the same output format, you may use {@link #setOutputFormat(OutputFormat)} after
+     * all, to set a value like {@link HTMLOutputFormat#INSTANCE}, {@link XMLOutputFormat#INSTANCE}, etc. Also note
+     * that templates can specify their own output format like {@code 
+     * <#ftl output_format="HTML">}, which overrides any configuration settings.
      * 
      * <p>
      * The output format is mostly important because of auto-escaping (see {@link #setAutoEscapingPolicy(int)}), but

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index b25ca0c..b68ff4c 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -4119,7 +4119,7 @@ ${("green " + "mouse")?upper_case}  &lt;#-- GREEN MOUSE --&gt;
           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 don't have to deal with it (but he can
+          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
@@ -4168,8 +4168,8 @@ ${("green " + "mouse")?upper_case}  &lt;#-- GREEN MOUSE --&gt;
 
           <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; you don't have to deal
-          with it (but if you care, <link
+          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
@@ -9163,30 +9163,594 @@ cfg.setTemplateConfigurations(
       <section xml:id="pgui_config_custom_formats">
         <title>Custom number and date/time formats</title>
 
-        <para>FreeMarker allows you to define your own number and
-        date/time/datetime formatter algorithms by implementing
-        <literal>freemarker.core.TemplateNumberFormatFactory</literal> and
-        <literal>freemarker.core.TemplateDateFormatFactory</literal>. These
-        formats can be registered with the
-        <literal>custom_number_formats</literal> and
-        <literal>custom_date_formats</literal> configuration settings. After
-        that, anywhere where you can specify formats with a
-        <literal>String</literal>, now you can refer to your custom format as
-        <literal>"@<replaceable>name</replaceable>"</literal>. So for example,
-        if you have registered your number format implementation with name
-        <literal>"smart"</literal>, then you could set the
-        <literal>number_format</literal> setting
-        (<literal>Configurable.setNumberFormat(String)</literal>) to
-        <literal>"@smart"</literal>, or issue
-        <literal>${n?string.@smart}</literal> or <literal>&lt;#setting
-        number_format="@smart"&gt;</literal> in a template.</para>
-
-        <para>[TODO] What other applications exist (aliasing, model-aware
-        formatters)</para>
-
-        <para>[TODO] Simple complete example</para>
-
-        <para>[TODO] Complex formatter example (base N with fallback)</para>
+        <section>
+          <title>Overview</title>
+
+          <para>FreeMarker allows you to define your own number and
+          date/time/datetime formats, and associate a name to them. This
+          mechanism has several applications:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para>Custom formatter algorithms: You can use your own
+              formatter algorithm instead of relying on those provided by
+              FreeMarker. For this, implement
+              <literal>freemarker.core.TemplateNumberFormatFactory</literal>
+              or <literal>freemarker.core.TemplateDateFormatFactory</literal>.
+              You will find a few examples of this <link
+              linkend="pgui_config_custom_formats_ex_cust_alg_simple">below</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Aliasing: You can give application-specific names (like
+              <quote>price</quote>, <quote>weight</quote>,
+              <quote>fileDate</quote>, <quote>logEventTime</quote>, etc.) to
+              other formats by using
+              <literal>AliasTemplateNumberFormatFactory</literal> and
+              <literal>AliasTemplateDateFormatFactory</literal>. Thus
+              templates can just refer to that name, like in
+              <literal>${lastModified?string.@fileDate}</literal>, instead of
+              specifying the format directly. Thus the formats can be
+              specified on a single central place (where you configure
+              FreeMarker), instead of being specified repeatedly in templates.
+              Also thus template authors don't have to enter complex and hard
+              to remember formatting patterns. <link
+              linkend="pgui_config_custom_formats_ex_alias">See example
+              below</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Model-sensitive formatting: Applications can put custom
+              <literal>freemarker.TemplateModel</literal>-s into the
+              data-model instead of dropping plain values (like
+              <literal>int</literal>-s, <literal>double</literal>-s, etc.)
+              into it, to attach rendering-related information to the value.
+              Custom formatters can utilize this information (for example, to
+              show the unit after numbers), as they receive the
+              <literal>TemplateModel</literal> itself, not the wrapped raw
+              value. <link
+              linkend="pgui_config_custom_formats_ex_model_aware">See example
+              below</link>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Format that prints markup instead of plain text: You might
+              want to use HTML tags (or other markup) in the formatted values,
+              such as coloring negative numbers to red or using HTML
+              <literal>sup</literal> element for exponents. This is possible
+              if you write a custom format as shown in previous cases, but
+              override the <literal>format</literal> method in the formatter
+              class so that it returns a
+              <literal>TemplateMarkupOutputModel</literal> instead of a
+              <literal>String</literal>. (You shouldn't just return the markup
+              as <literal>String</literal>, as then it might will be escaped;
+              see <link
+              linkend="dgui_misc_autoescaping">auto-escaping</link>.)</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>Custom formats can be registered with the
+          <literal>custom_number_formats</literal> and
+          <literal>custom_date_formats</literal> configuration settings. After
+          that, anywhere where you can specify formats with a
+          <literal>String</literal>, now you can refer to your custom format
+          as <literal>"@<replaceable>name</replaceable>"</literal>. So for
+          example, if you have registered your number format implementation
+          with name <literal>"smart"</literal>, then you could set the
+          <literal>number_format</literal> setting
+          (<literal>Configurable.setNumberFormat(String)</literal>) to
+          <literal>"@smart"</literal>, or issue
+          <literal>${n?string.@smart}</literal> or <literal>&lt;#setting
+          number_format="@smart"&gt;</literal> in a template. Furthermore, you
+          can define parameters for your custom format, like <literal>"@smart
+          2"</literal>, and the interpretation of the parameters is up to your
+          formatter implementation.</para>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_cust_alg_simple">
+          <title>Simple custom number format example</title>
+
+          <para>This custom number format shows numbers in hexadecimal
+          form:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import java.util.Locale;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+import freemarker.template.utility.NumberUtil;
+
+public class HexTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    public static final HexTemplateNumberFormatFactory INSTANCE
+            = new HexTemplateNumberFormatFactory();
+    
+    private HexTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws InvalidFormatParametersException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return HexTemplateNumberFormat.INSTANCE;
+    }
+
+    private static class HexTemplateNumberFormat extends TemplateNumberFormat {
+
+        private static final HexTemplateNumberFormat INSTANCE = new HexTemplateNumberFormat();
+        
+        private HexTemplateNumberFormat() { }
+        
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws UnformattableValueException, TemplateModelException {
+            Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
+            try {
+                return Integer.toHexString(NumberUtil.toIntExact(n));
+            } catch (ArithmeticException e) {
+                throw new UnformattableValueException(n + " doesn't fit into an int");
+            }
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        public String getDescription() {
+            return "hexadecimal int";
+        }
+        
+    }
+
+}</programlisting>
+
+          <para>We register the above format with name
+          <quote>hex</quote>:</para>
+
+          <programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
+Configuration cfg = ...;
+...
+Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats = ...;
+...
+customNumberFormats.put("hex", HexTemplateNumberFormatFactory.INSTANCE);
+...
+cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
+
+          <para>Now we can use this format in templates:</para>
+
+          <programlisting role="template">${x?string.@hex}</programlisting>
+
+          <para>or even set it as the default number format:</para>
+
+          <programlisting role="unspecified">cfg.setNumberFormat("@hex");</programlisting>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_cust_algo_advanced">
+          <title>Advanced custom number format example</title>
+
+          <para>This is a more complex custom number format that shows how to
+          deal with parameters in the format string, also how to delegate to
+          another format:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import java.util.Locale;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+import freemarker.template.utility.NumberUtil;
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Shows a number in base N number system. Can only format numbers that fit into an {@code int},
+ * however, optionally you can specify a fallback format. This format has one required parameter,
+ * the numerical system base. That can be optionally followed by "|" and a fallback format.
+ */
+public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    public static final BaseNTemplateNumberFormatFactory INSTANCE
+            = new BaseNTemplateNumberFormatFactory();
+    
+    private BaseNTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws InvalidFormatParametersException {
+        TemplateNumberFormat fallbackFormat;
+        {
+            int barIdx = params.indexOf('|');
+            if (barIdx != -1) {
+                String fallbackFormatStr = params.substring(barIdx + 1);
+                params = params.substring(0, barIdx);
+                try {
+                    fallbackFormat = env.getTemplateNumberFormat(fallbackFormatStr, locale);
+                } catch (TemplateValueFormatException e) {
+                    throw new InvalidFormatParametersException(
+                            "Couldn't get the fallback number format (specified after the \"|\"), "
+                            + StringUtil.jQuote(fallbackFormatStr) + ". Reason: " + e.getMessage(),
+                            e);
+                }
+            } else {
+                fallbackFormat = null;
+            }
+        }
+        
+        int base;
+        try {
+            base = Integer.parseInt(params);
+        } catch (NumberFormatException e) {
+            if (params.length() == 0) {
+                throw new InvalidFormatParametersException(
+                        "A format parameter is required to specify the numerical system base.");
+            }
+            throw new InvalidFormatParametersException(
+                    "The format paramter must be an integer, but was (shown quoted): "
+                    + StringUtil.jQuote(params));
+        }
+        if (base &lt; 2) {
+            throw new InvalidFormatParametersException("A base must be at least 2.");
+        }
+        return new BaseNTemplateNumberFormat(base, fallbackFormat);
+    }
+
+    private static class BaseNTemplateNumberFormat extends TemplateNumberFormat {
+
+        private final int base;
+        private final TemplateNumberFormat fallbackFormat;
+        
+        private BaseNTemplateNumberFormat(int base, TemplateNumberFormat fallbackFormat) {
+            this.base = base;
+            this.fallbackFormat = fallbackFormat;
+        }
+        
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws TemplateModelException, TemplateValueFormatException {
+            Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
+            try {
+                return Integer.toString(NumberUtil.toIntExact(n), base);
+            } catch (ArithmeticException e) {
+                if (fallbackFormat == null) {
+                    throw new UnformattableValueException(
+                            n + " doesn't fit into an int, and there was no fallback format "
+                            + "specified.");
+                } else {
+                    return fallbackFormat.formatToPlainText(numberModel);
+                }
+            }
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        public String getDescription() {
+            return "base " + base;
+        }
+        
+    }
+
+}</programlisting>
+
+          <para>We register the above format with name
+          <quote>base</quote>:</para>
+
+          <programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
+Configuration cfg = ...;
+...
+Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats = ...;
+...
+customNumberFormats.put("hex", BaseNTemplateNumberFormatFactory.INSTANCE);
+...
+cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
+
+          <para>Now we can use this format in templates:</para>
+
+          <programlisting role="template">${x?string.@base_8}</programlisting>
+
+          <para>Above there the parameter string was <literal>"8"</literal>,
+          as FreeMarker allows separating that from the format name with
+          <literal>_</literal> instead of whitespace, so that you don't have
+          to write the longer
+          <literal><replaceable>n</replaceable>?string["@base 8"]</literal>
+          form.</para>
+
+          <para>Of course, we could also set this as the default number format
+          like:</para>
+
+          <programlisting role="unspecified">cfg.setNumberFormat("@base 8");</programlisting>
+
+          <para>Here's an example of using the a fallback number format (which
+          is <literal>"0.0###"</literal>):</para>
+
+          <programlisting role="unspecified">cfg.setNumberFormat("@base 8|0.0###");</programlisting>
+
+          <para>Note that this functionality, with the <literal>|</literal>
+          syntax and all, is purely implemented in the example code
+          earlier.</para>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_cust_algo_date">
+          <title>Custom date/time format example</title>
+
+          <para>This simple date format formats the date/time value to the
+          milliseconds since the epoch:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import freemarker.template.TemplateDateModel;
+import freemarker.template.TemplateModelException;
+
+public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFactory {
+
+    public static final EpochMillisTemplateDateFormatFactory INSTANCE
+            = new EpochMillisTemplateDateFormatFactory();
+    
+    private EpochMillisTemplateDateFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateDateFormat get(String params, int dateType,
+            Locale locale, TimeZone timeZone, boolean zonelessInput,
+            Environment env)
+            throws InvalidFormatParametersException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return EpochMillisTemplateDateFormat.INSTANCE;
+    }
+
+    private static class EpochMillisTemplateDateFormat extends TemplateDateFormat {
+
+        private static final EpochMillisTemplateDateFormat INSTANCE
+                = new EpochMillisTemplateDateFormat();
+        
+        private EpochMillisTemplateDateFormat() { }
+        
+        @Override
+        public String formatToPlainText(TemplateDateModel dateModel)
+                throws UnformattableValueException, TemplateModelException {
+            return String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime());
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        public boolean isTimeZoneBound() {
+            return false;
+        }
+
+        @Override
+        public Date parse(String s, int dateType) throws UnparsableValueException {
+            try {
+                return new Date(Long.parseLong(s));
+            } catch (NumberFormatException e) {
+                throw new UnparsableValueException("Malformed long");
+            }
+        }
+
+        @Override
+        public String getDescription() {
+            return "millis since the epoch";
+        }
+        
+    }
+
+}</programlisting>
+
+          <para>We register the above format with name
+          <quote>epoch</quote>:</para>
+
+          <programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
+Configuration cfg = ...;
+...
+Map&lt;String, TemplateDateFormatFactory&gt; customDateFormats = ...;
+...
+customDateFormats.put("epoch", EpochMillisTemplateDateFormatFactory.INSTANCE);
+...
+cfg.setCustomDateFormats(customDateFormats);</programlisting>
+
+          <para>Now we can use this format in templates:</para>
+
+          <programlisting role="template">${t?string.@epoch}</programlisting>
+
+          <para>Of course, we could also set this as the default date-time
+          format like:</para>
+
+          <programlisting role="unspecified">cfg.setDateTimeFormat("@epoch");</programlisting>
+
+          <para>For a more complex that for example uses format parameters,
+          refer to the <link
+          linkend="pgui_config_custom_formats_ex_cust_algo_advanced">advanced
+          number format example</link>. Doing that with date formats is very
+          similar.</para>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_alias">
+          <title>Alias format example</title>
+
+          <para>In this example we specify some number formats and date
+          formats that are aliases to another format:</para>
+
+          <programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
+Configuration cfg = ...;
+
+Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats
+        = new HashMap&lt;String, TemplateNumberFormatFactory&gt;();
+customNumberFormats.put("price", new AliasTemplateNumberFormatFactory(",000.00"));
+customNumberFormats.put("weight",
+        new AliasTemplateNumberFormatFactory("0.##;; roundingMode=halfUp"));
+cfg.setCustomNumberFormats(customNumberFormats);
+
+Map&lt;String, TemplateDateFormatFactory&gt; customDateFormats
+        = new HashMap&lt;String, TemplateDateFormatFactory&gt;();
+customDateFormats.put("fileDate", new AliasTemplateDateFormatFactory("dd/MMM/yy hh:mm a"));
+customDateFormats.put("logEventTime", new AliasTemplateDateFormatFactory("iso ms u"));
+cfg.setCustomDateFormats(customDateFormats);</programlisting>
+
+          <para>So now you can do this in a template:</para>
+
+          <programlisting role="template">${product.price?string.@price}
+${product.weight?string.@weight}
+${lastModified?string.@fileDate}
+${lastError.timestamp?string.@logEventTime}</programlisting>
+
+          <para>Note that the constructor parameter of
+          <literal>AliasTemplateNumberFormatFactory</literal> can naturally
+          refer to a custom format too:</para>
+
+          <programlisting role="unspecified">Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats
+        = new HashMap&lt;String, TemplateNumberFormatFactory&gt;();
+customNumberFormats.put("base", BaseNTemplateNumberFormatFactory.INSTANCE);
+customNumberFormats.put("oct", new AliasTemplateNumberFormatFactory("@base 8"));
+cfg.setCustomNumberFormats(customNumberFormats);</programlisting>
+
+          <para>So now
+          <literal><replaceable>n</replaceable>?string.@oct</literal> will
+          format the number to octal form.</para>
+        </section>
+
+        <section xml:id="pgui_config_custom_formats_ex_model_aware">
+          <title>Model-aware format example</title>
+
+          <para>In this example we specify a number format that automatically
+          show the unit after the number if that was put into the data-model
+          as <literal>UnitAwareTemplateNumberModel</literal>. First let's see
+          <literal>UnitAwareTemplateNumberModel</literal>:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+public class UnitAwareTemplateNumberModel implements TemplateNumberModel {
+
+    private final Number value;
+    private final String unit;
+    
+    public UnitAwareTemplateNumberModel(Number value, String unit) {
+        this.value = value;
+        this.unit = unit;
+    }
+
+    @Override
+    public Number getAsNumber() throws TemplateModelException {
+        return value;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+}</programlisting>
+
+          <para>When you fill the data-model, you could do something like
+          this:</para>
+
+          <programlisting role="unspecified">Map&lt;String, Object&gt; dataModel = new HashMap&lt;&gt;();
+dataModel.put("weight", new UnitAwareTemplateNumberModel(1.5, "kg"));
+// Rather than just: dataModel.put("weight", 1.5);</programlisting>
+
+          <para>Then if we have this in the template:</para>
+
+          <programlisting role="template">${weight}</programlisting>
+
+          <para>we want to see this:</para>
+
+          <programlisting role="output">1.5 kg</programlisting>
+
+          <para>To achieve that, we define this custom number format:</para>
+
+          <programlisting role="unspecified">package com.example;
+
+import java.util.Locale;
+
+import freemarker.core.Environment;
+import freemarker.core.TemplateNumberFormat;
+import freemarker.core.TemplateNumberFormatFactory;
+import freemarker.core.TemplateValueFormatException;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+/**
+ * A number format that takes any other number format as parameter (specified as a string, as
+ * usual in FreeMarker), then if the model is a {@link UnitAwareTemplateNumberModel}, it  shows
+ * the unit after the number formatted with the other format, otherwise it just shows the formatted
+ * number without unit.
+ */
+public class UnitAwareTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    public static final UnitAwareTemplateNumberFormatFactory INSTANCE
+            = new UnitAwareTemplateNumberFormatFactory();
+
+    private UnitAwareTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws TemplateValueFormatException {
+        return new UnitAwareNumberFormat(env.getTemplateNumberFormat(params, locale));
+    }
+
+    private static class UnitAwareNumberFormat extends TemplateNumberFormat {
+
+        private final TemplateNumberFormat innerFormat;
+
+        private UnitAwareNumberFormat(TemplateNumberFormat innerFormat) {
+            this.innerFormat = innerFormat;
+        }
+
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws TemplateModelException, TemplateValueFormatException {
+            String innerResult = innerFormat.formatToPlainText(numberModel);
+            return numberModel instanceof UnitAwareTemplateNumberModel
+                    ? innerResult + " " + ((UnitAwareTemplateNumberModel) numberModel).getUnit()
+                    : innerResult;
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return innerFormat.isLocaleBound();
+        }
+
+        @Override
+        public String getDescription() {
+            return "unit-aware " + innerFormat.getDescription();
+        }
+
+    }
+
+}</programlisting>
+
+          <para>Finally, we set the above custom format as the default number
+          format:</para>
+
+          <programlisting role="unspecified">// Where you initalize the application-wide Configuration singleton:
+Configuration cfg = ...;
+
+Map&lt;String, TemplateNumberFormatFactory&gt; customNumberFormats = new HashMap&lt;&gt;();
+customNumberFormats.put("ua", UnitAwareTemplateNumberFormatFactory.INSTANCE);
+cfg.setCustomNumberFormats(customNumberFormats);
+
+// Note: "0.####;; roundingMode=halfUp" is a standard format specified in FreeMarker.
+cfg.setNumberFormat("@ua 0.####;; roundingMode=halfUp");</programlisting>
+        </section>
       </section>
 
       <section xml:id="pgui_config_incompatible_improvements">
@@ -15346,7 +15910,8 @@ Tue, Apr 8, '03
           </note>
 
           <para>To prevent misunderstandings, the format need not be a string
-          literal, it can be a variable or any other expression, like in
+          literal, it can be a variable or any other expression as far as it
+          evaluates to a string. For example, it can be like
           <literal>"<replaceable>...</replaceable>"?string[myFormat]</literal>.</para>
 
           <para>See also: <link

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/java/freemarker/core/BaseNTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/BaseNTemplateNumberFormatFactory.java b/src/test/java/freemarker/core/BaseNTemplateNumberFormatFactory.java
index 3639a38..a669bc8 100644
--- a/src/test/java/freemarker/core/BaseNTemplateNumberFormatFactory.java
+++ b/src/test/java/freemarker/core/BaseNTemplateNumberFormatFactory.java
@@ -25,9 +25,15 @@ 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();
+    public static final BaseNTemplateNumberFormatFactory INSTANCE
+            = new BaseNTemplateNumberFormatFactory();
     
     private BaseNTemplateNumberFormatFactory() {
         // Defined to decrease visibility
@@ -61,10 +67,14 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
         } catch (NumberFormatException e) {
             if (params.length() == 0) {
                 throw new InvalidFormatParametersException(
-                        "A format parameter is required, which specifies the numerical system base.");
+                        "A format parameter is required to specify the numerical system base.");
             }
             throw new InvalidFormatParametersException(
-                    "The format paramter must be an integer, but was (shown quoted): " + StringUtil.jQuote(params));
+                    "The format paramter must be an integer, but was (shown quoted): "
+                    + StringUtil.jQuote(params));
+        }
+        if (base < 2) {
+            throw new InvalidFormatParametersException("A base must be at least 2.");
         }
         return new BaseNTemplateNumberFormat(base, fallbackFormat);
     }
@@ -88,7 +98,8 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
             } catch (ArithmeticException e) {
                 if (fallbackFormat == null) {
                     throw new UnformattableValueException(
-                            n + " doesn't fit into an int, and there was no fallback format specified.");
+                            n + " doesn't fit into an int, and there was no fallback format "
+                            + "specified.");
                 } else {
                     return fallbackFormat.formatToPlainText(numberModel);
                 }
@@ -102,7 +113,7 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
 
         @Override
         public String getDescription() {
-            return "hexadecimal int";
+            return "base " + base;
         }
         
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/java/freemarker/core/EpochMillisTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/EpochMillisTemplateDateFormatFactory.java b/src/test/java/freemarker/core/EpochMillisTemplateDateFormatFactory.java
index bbf5cd5..33fbcc3 100644
--- a/src/test/java/freemarker/core/EpochMillisTemplateDateFormatFactory.java
+++ b/src/test/java/freemarker/core/EpochMillisTemplateDateFormatFactory.java
@@ -27,22 +27,26 @@ import freemarker.template.TemplateModelException;
 
 public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFactory {
 
-    public static final EpochMillisTemplateDateFormatFactory INSTANCE = new EpochMillisTemplateDateFormatFactory();
+    public static final EpochMillisTemplateDateFormatFactory INSTANCE
+            = new EpochMillisTemplateDateFormatFactory();
     
     private EpochMillisTemplateDateFormatFactory() {
         // Defined to decrease visibility
     }
     
     @Override
-    public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput,
-            Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException {
+    public TemplateDateFormat get(String params, int dateType,
+            Locale locale, TimeZone timeZone, boolean zonelessInput,
+            Environment env)
+            throws InvalidFormatParametersException {
         TemplateFormatUtil.checkHasNoParameters(params);
         return EpochMillisTemplateDateFormat.INSTANCE;
     }
 
     private static class EpochMillisTemplateDateFormat extends TemplateDateFormat {
 
-        private static final EpochMillisTemplateDateFormat INSTANCE = new EpochMillisTemplateDateFormat();
+        private static final EpochMillisTemplateDateFormat INSTANCE
+                = new EpochMillisTemplateDateFormat();
         
         private EpochMillisTemplateDateFormat() { }
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/java/freemarker/manual/CustomFormatsExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/CustomFormatsExample.java b/src/test/java/freemarker/manual/CustomFormatsExample.java
new file mode 100644
index 0000000..31de217
--- /dev/null
+++ b/src/test/java/freemarker/manual/CustomFormatsExample.java
@@ -0,0 +1,73 @@
+package freemarker.manual;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import freemarker.core.AliasTemplateDateFormatFactory;
+import freemarker.core.AliasTemplateNumberFormatFactory;
+import freemarker.core.BaseNTemplateNumberFormatFactory;
+import freemarker.core.TemplateDateFormatFactory;
+import freemarker.core.TemplateNumberFormatFactory;
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+
+@SuppressWarnings("boxing")
+public class CustomFormatsExample extends ExamplesTest {
+
+    @Test
+    public void aliases1() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+
+        Map<String, TemplateNumberFormatFactory> customNumberFormats
+                = new HashMap<String, TemplateNumberFormatFactory>();
+        customNumberFormats.put("price", new AliasTemplateNumberFormatFactory(",000.00"));
+        customNumberFormats.put("weight", new AliasTemplateNumberFormatFactory("0.##;; roundingMode=halfUp"));
+        cfg.setCustomNumberFormats(customNumberFormats);
+
+        Map<String, TemplateDateFormatFactory> customDateFormats
+                = new HashMap<String, TemplateDateFormatFactory>();
+        customDateFormats.put("fileDate", new AliasTemplateDateFormatFactory("dd/MMM/yy hh:mm a"));
+        customDateFormats.put("logEventTime", new AliasTemplateDateFormatFactory("iso ms u"));
+        cfg.setCustomDateFormats(customDateFormats);
+
+        addToDataModel("p", 10000);
+        addToDataModel("w", 10.305);
+        addToDataModel("fd", new Date(1450904944213L));
+        addToDataModel("let", new Date(1450904944213L));
+        
+        assertOutputForNamed("CustomFormatsExample-alias1.ftlh");
+    }
+
+    @Test
+    public void aliases2() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+
+        Map<String, TemplateNumberFormatFactory> customNumberFormats
+                = new HashMap<String, TemplateNumberFormatFactory>();
+        customNumberFormats.put("base", BaseNTemplateNumberFormatFactory.INSTANCE);
+        customNumberFormats.put("oct", new AliasTemplateNumberFormatFactory("@base 8"));
+        cfg.setCustomNumberFormats(customNumberFormats);
+        
+        assertOutputForNamed("CustomFormatsExample-alias2.ftlh");
+    }
+
+    @Test
+    public void modelAware() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+
+        Map<String, TemplateNumberFormatFactory> customNumberFormats
+                = new HashMap<String, TemplateNumberFormatFactory>();
+        customNumberFormats.put("ua", UnitAwareTemplateNumberFormatFactory.INSTANCE);
+        cfg.setCustomNumberFormats(customNumberFormats);
+        cfg.setNumberFormat("@ua 0.####;; roundingMode=halfUp");
+
+        addToDataModel("weight", new UnitAwareTemplateNumberModel(1.5, "kg"));
+        
+        assertOutputForNamed("CustomFormatsExample-modelAware.ftlh");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java b/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
new file mode 100644
index 0000000..df179d4
--- /dev/null
+++ b/src/test/java/freemarker/manual/UnitAwareTemplateNumberFormatFactory.java
@@ -0,0 +1,62 @@
+package freemarker.manual;
+
+import java.util.Locale;
+
+import freemarker.core.Environment;
+import freemarker.core.TemplateNumberFormat;
+import freemarker.core.TemplateNumberFormatFactory;
+import freemarker.core.TemplateValueFormatException;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+/**
+ * A number format that takes any other number format as parameter (specified as a string, as
+ * usual in FreeMarker), then if the model is a {@link UnitAwareTemplateNumberModel}, it  shows
+ * the unit after the number formatted with the other format, otherwise it just shows the formatted
+ * number without unit.
+ */
+public class UnitAwareTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
+
+    public static final UnitAwareTemplateNumberFormatFactory INSTANCE
+            = new UnitAwareTemplateNumberFormatFactory();
+
+    private UnitAwareTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment env)
+            throws TemplateValueFormatException {
+        return new UnitAwareNumberFormat(env.getTemplateNumberFormat(params, locale));
+    }
+
+    private static class UnitAwareNumberFormat extends TemplateNumberFormat {
+
+        private final TemplateNumberFormat innerFormat;
+
+        private UnitAwareNumberFormat(TemplateNumberFormat innerFormat) {
+            this.innerFormat = innerFormat;
+        }
+
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws TemplateModelException, TemplateValueFormatException {
+            String innerResult = innerFormat.formatToPlainText(numberModel);
+            return numberModel instanceof UnitAwareTemplateNumberModel
+                    ? innerResult + " " + ((UnitAwareTemplateNumberModel) numberModel).getUnit()
+                    : innerResult;
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return innerFormat.isLocaleBound();
+        }
+
+        @Override
+        public String getDescription() {
+            return "unit-aware " + innerFormat.getDescription();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java b/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
new file mode 100644
index 0000000..fc58431
--- /dev/null
+++ b/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
@@ -0,0 +1,25 @@
+package freemarker.manual;
+
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+public class UnitAwareTemplateNumberModel implements TemplateNumberModel {
+
+    private final Number value;
+    private final String unit;
+    
+    public UnitAwareTemplateNumberModel(Number value, String unit) {
+        this.value = value;
+        this.unit = unit;
+    }
+
+    @Override
+    public Number getAsNumber() throws TemplateModelException {
+        return value;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh b/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh
new file mode 100644
index 0000000..abf6dfe
--- /dev/null
+++ b/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh
@@ -0,0 +1,4 @@
+${p?string.@price}
+${w?string.@weight}
+${fd?string.@fileDate}
+${let?datetime?string.@logEventTime}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh.out
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh.out b/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh.out
new file mode 100644
index 0000000..a15bd01
--- /dev/null
+++ b/src/test/resources/freemarker/manual/CustomFormatsExample-alias1.ftlh.out
@@ -0,0 +1,4 @@
+10,000.00
+10.31
+23/Dec/15 10:09 PM
+2015-12-23T21:09:04.213Z

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh b/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh
new file mode 100644
index 0000000..ae64acb
--- /dev/null
+++ b/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh
@@ -0,0 +1 @@
+${10?string.@oct}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh.out
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh.out b/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh.out
new file mode 100644
index 0000000..3cacc0b
--- /dev/null
+++ b/src/test/resources/freemarker/manual/CustomFormatsExample-alias2.ftlh.out
@@ -0,0 +1 @@
+12
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh b/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh
new file mode 100644
index 0000000..49ce264
--- /dev/null
+++ b/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh
@@ -0,0 +1,2 @@
+${10.12356}
+${weight}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f112ed6c/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh.out
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh.out b/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh.out
new file mode 100644
index 0000000..22e0890
--- /dev/null
+++ b/src/test/resources/freemarker/manual/CustomFormatsExample-modelAware.ftlh.out
@@ -0,0 +1,2 @@
+10.1236
+1.5 kg
\ No newline at end of file


[05/35] incubator-freemarker git commit: Made place for the Chinese manual.

Posted by dd...@apache.org.
Made place for the Chinese manual.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/731be2c2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/731be2c2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/731be2c2

Branch: refs/heads/2.3
Commit: 731be2c28e51d71e5027c6fd4ddda68c3af81b05
Parents: 41b6f83
Author: ddekany <dd...@apache.org>
Authored: Sun Dec 20 14:05:48 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 20 14:05:48 2015 +0100

----------------------------------------------------------------------
 build.xml                                       |    22 +-
 src/manual/book.xml                             | 37479 -----------------
 src/manual/docgen-help/editors-readme.txt       |   105 -
 src/manual/docgen-misc/googleAnalytics.html     |     9 -
 .../figures/model2sketch_with_alpha.png         |   Bin 61463 -> 0 bytes
 .../figures/odg-convert-howto.txt               |    24 -
 .../docgen-originals/figures/overview.odg       |   Bin 11939 -> 0 bytes
 .../figures/tree_with_alpha.png                 |   Bin 10304 -> 0 bytes
 src/manual/docgen.cjson                         |   112 -
 src/manual/en_US/book.xml                       | 37479 +++++++++++++++++
 src/manual/en_US/docgen-help/editors-readme.txt |   105 +
 .../en_US/docgen-misc/googleAnalytics.html      |     9 +
 .../figures/model2sketch_with_alpha.png         |   Bin 0 -> 61463 bytes
 .../figures/odg-convert-howto.txt               |    24 +
 .../en_US/docgen-originals/figures/overview.odg |   Bin 0 -> 11939 bytes
 .../figures/tree_with_alpha.png                 |   Bin 0 -> 10304 bytes
 src/manual/en_US/docgen.cjson                   |   112 +
 src/manual/en_US/favicon.png                    |   Bin 0 -> 1291 bytes
 src/manual/en_US/figures/model2sketch.png       |   Bin 0 -> 21425 bytes
 src/manual/en_US/figures/overview.png           |   Bin 0 -> 11837 bytes
 src/manual/en_US/figures/tree.png               |   Bin 0 -> 4699 bytes
 src/manual/en_US/logo.png                       |   Bin 0 -> 10134 bytes
 src/manual/favicon.png                          |   Bin 1291 -> 0 bytes
 src/manual/figures/model2sketch.png             |   Bin 21425 -> 0 bytes
 src/manual/figures/overview.png                 |   Bin 11837 -> 0 bytes
 src/manual/figures/tree.png                     |   Bin 4699 -> 0 bytes
 src/manual/logo.png                             |   Bin 10134 -> 0 bytes
 src/manual/zh_CN/placeholder.txt                |     5 +
 28 files changed, 37752 insertions(+), 37733 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index 999c88b..aa42db9 100644
--- a/build.xml
+++ b/build.xml
@@ -548,6 +548,7 @@
   
   <macrodef name="manual" uri="http://freemarker.org/util">
     <attribute name="offline" />
+    <attribute name="locale" />
     <sequential>
       <ivy:cachepath conf="manual" pathid="ivy.dep" />
       <taskdef resource="org/freemarker/docgen/antlib.properties"
@@ -556,20 +557,28 @@
       />
       
       <docgen:transform
-        srcdir="src/manual" destdir="build/manual"
+        srcdir="src/manual/@{locale}" destdir="build/manual/@{locale}"
         offline="@{offline}"
       />
     </sequential>
   </macrodef>
   
   <target name="manualOffline" depends="init" description="Build the Manual for offline use" >
-    <u:manual offline="true" />
+    <u:manual offline="true" locale="en_US" />
   </target>
 
   <target name="manualFreemarkerOrg" depends="init" description="Build the Manual to be upload to freemarker.org" >
-    <u:manual offline="false" />
+    <u:manual offline="false" locale="en_US" />
+  </target>
+  
+  <target name="manualOffline_zh_CN" depends="init" description="Build the Manual for offline use" >
+    <u:manual offline="true" locale="zh_CN" />
   </target>
 
+  <target name="manualFreemarkerOrg_zh_CN" depends="init" description="Build the Manual to be upload to freemarker.org" >
+    <u:manual offline="false" locale="zh_CN" />
+  </target>
+  
   <!-- ====================== -->
   <!-- Examples               -->
   <!-- ====================== -->
@@ -680,8 +689,13 @@
     <copy todir="${dist.dir}/">
       <fileset dir="src/dist/" />
     </copy>
+    <!--
+      The US English Manual is the source of any translations and this it's the
+      only one that is guaranteed to be up to date when doing the release, so we only pack
+      that into it.
+    -->
     <copy todir="${dist.dir}/documentation/_html" includeEmptyDirs="no">
-      <fileset dir="build/manual" />
+      <fileset dir="build/manual/en-US" />
     </copy>
     <copy todir="${dist.dir}/documentation/_html/api" includeEmptyDirs="no">
       <fileset dir="build/api" />


[35/35] incubator-freemarker git commit: Merge remote-tracking branch 'origin/2.3-gae' into 2.3

Posted by dd...@apache.org.
Merge remote-tracking branch 'origin/2.3-gae' into 2.3


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/f0695c39
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/f0695c39
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/f0695c39

Branch: refs/heads/2.3
Commit: f0695c39a6044653f115ebbbada44873d216dfe7
Parents: ad73f5f be2d799
Author: ddekany <dd...@apache.org>
Authored: Wed Dec 30 19:09:37 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Wed Dec 30 19:09:37 2015 +0100

----------------------------------------------------------------------
 .gitignore                                      |    23 +-
 build.xml                                       |    22 +-
 src/main/java/freemarker/core/BuiltIn.java      |    31 +-
 .../core/BuiltInsForMultipleTypes.java          |     7 +-
 .../freemarker/core/BuiltInsForStringsMisc.java |     3 +-
 .../java/freemarker/core/CSSOutputFormat.java   |    52 +
 src/main/java/freemarker/core/Configurable.java |    19 +-
 src/main/java/freemarker/core/Environment.java  |    15 +-
 .../java/freemarker/core/HTMLOutputFormat.java  |     4 +-
 src/main/java/freemarker/core/Interpret.java    |     3 +-
 .../java/freemarker/core/JSONOutputFormat.java  |    52 +
 .../freemarker/core/JavaScriptOutputFormat.java |    53 +
 .../java/freemarker/core/LocalContextStack.java |    18 +
 .../freemarker/core/MarkupOutputFormat.java     |    26 +-
 src/main/java/freemarker/core/OutputFormat.java |    35 +-
 .../core/OutputFormatBoundBuiltIn.java          |     4 +-
 .../freemarker/core/PlainTextOutputFormat.java  |     8 +-
 .../java/freemarker/core/RTFOutputFormat.java   |     6 +-
 .../freemarker/core/StackTraceVisibility.java   |     8 -
 .../freemarker/core/TemplateConfiguration.java  |     4 +-
 .../core/TemplateDateFormatFactory.java         |     2 +-
 .../core/TemplateElementArrayBuilder.java       |    18 +
 .../core/TemplateElementsToVisit.java           |    18 +
 .../core/TemplateMarkupOutputModel.java         |    15 +-
 .../core/TemplateNumberFormatFactory.java       |     2 +-
 .../java/freemarker/core/XHTMLOutputFormat.java |     4 +-
 .../java/freemarker/core/XMLOutputFormat.java   |    10 +-
 src/main/java/freemarker/core/_CoreAPI.java     |   145 +-
 .../core/_ObjectBuilderSettingEvaluator.java    |   123 +-
 ..._ParserConfigurationWithInheritedFormat.java |    10 +-
 .../java/freemarker/ext/dom/ElementModel.java   |     2 +-
 .../java/freemarker/ext/dom/NodeListModel.java  |     5 +
 src/main/java/freemarker/ext/dom/NodeModel.java |     6 +-
 .../java/freemarker/ext/dom/NodeOutputter.java  |    39 +-
 .../java/freemarker/template/Configuration.java |   136 +-
 .../freemarker/template/utility/StringUtil.java |    27 +-
 src/main/javacc/FTL.jj                          |     8 +-
 src/manual/book.xml                             | 37479 ----------------
 src/manual/docgen-help/editors-readme.txt       |   105 -
 src/manual/docgen-misc/googleAnalytics.html     |     9 -
 .../figures/model2sketch_with_alpha.png         |   Bin 61463 -> 0 bytes
 .../figures/odg-convert-howto.txt               |    24 -
 .../docgen-originals/figures/overview.odg       |   Bin 11939 -> 0 bytes
 .../figures/tree_with_alpha.png                 |   Bin 10304 -> 0 bytes
 src/manual/docgen.cjson                         |   112 -
 src/manual/en_US/book.xml                       | 38413 +++++++++++++++++
 src/manual/en_US/docgen-help/editors-readme.txt |   105 +
 .../en_US/docgen-misc/googleAnalytics.html      |     9 +
 .../figures/model2sketch_with_alpha.png         |   Bin 0 -> 61463 bytes
 .../figures/odg-convert-howto.txt               |    24 +
 .../en_US/docgen-originals/figures/overview.odg |   Bin 0 -> 11939 bytes
 .../figures/tree_with_alpha.png                 |   Bin 0 -> 10304 bytes
 src/manual/en_US/docgen.cjson                   |   112 +
 src/manual/en_US/favicon.png                    |   Bin 0 -> 1291 bytes
 src/manual/en_US/figures/model2sketch.png       |   Bin 0 -> 21425 bytes
 src/manual/en_US/figures/overview.png           |   Bin 0 -> 11837 bytes
 src/manual/en_US/figures/tree.png               |   Bin 0 -> 4699 bytes
 src/manual/en_US/logo.png                       |   Bin 0 -> 10134 bytes
 src/manual/favicon.png                          |   Bin 1291 -> 0 bytes
 src/manual/figures/model2sketch.png             |   Bin 21425 -> 0 bytes
 src/manual/figures/overview.png                 |   Bin 11837 -> 0 bytes
 src/manual/figures/tree.png                     |   Bin 4699 -> 0 bytes
 src/manual/logo.png                             |   Bin 10134 -> 0 bytes
 src/manual/zh_CN/placeholder.txt                |     5 +
 .../core/BaseNTemplateNumberFormatFactory.java  |    21 +-
 .../java/freemarker/core/CamelCaseTest.java     |     4 +-
 .../freemarker/core/CoercionToTextualTest.java  |    18 +
 .../core/CombinedMarkupOutputFormatTest.java    |     2 +-
 .../EpochMillisTemplateDateFormatFactory.java   |    12 +-
 .../freemarker/core/IncludeAndImportTest.java   |    99 +
 .../freemarker/core/IteratorIssuesTest.java     |    18 +
 .../core/ObjectBuilderSettingsTest.java         |    50 +
 .../java/freemarker/core/OutputFormatTest.java  |    22 +
 .../freemarker/core/RTFOutputFormatTest.java    |     2 +-
 .../freemarker/core/XMLOutputFormatTest.java    |     2 +-
 src/test/java/freemarker/ext/dom/DOMTest.java   |   110 +
 .../ext/servlet/FreemarkerServletTest.java      |    55 +
 .../freemarker/manual/CustomFormatsExample.java |    91 +
 .../manual/GettingStartedExample.java           |    67 +
 src/test/java/freemarker/manual/Product.java    |    49 +
 .../UnitAwareTemplateNumberFormatFactory.java   |    80 +
 .../manual/UnitAwareTemplateNumberModel.java    |    43 +
 .../freemarker/template/ConfigurationTest.java  |    41 +
 src/test/java/freemarker/test/TemplateTest.java |    21 +-
 .../manual/CustomFormatsExample-alias1.ftlh     |     4 +
 .../manual/CustomFormatsExample-alias1.ftlh.out |     4 +
 .../manual/CustomFormatsExample-alias2.ftlh     |     1 +
 .../manual/CustomFormatsExample-alias2.ftlh.out |     1 +
 .../manual/CustomFormatsExample-modelAware.ftlh |     2 +
 .../CustomFormatsExample-modelAware.ftlh.out    |     2 +
 src/test/resources/freemarker/manual/test.ftlh  |    10 +
 .../test/templatesuite/expected/interpret.txt   |     2 +
 .../expected/type-builtins-ici-2.3.24.txt       |    15 +
 .../test/templatesuite/templates/interpret.ftl  |     2 +
 .../freemarker/test/templatesuite/testcases.xml |     5 +-
 95 files changed, 40234 insertions(+), 37981 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f0695c39/build.xml
----------------------------------------------------------------------


[34/35] incubator-freemarker git commit: (Manual typo)

Posted by dd...@apache.org.
(Manual typo)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/be2d7994
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/be2d7994
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/be2d7994

Branch: refs/heads/2.3
Commit: be2d7994ca6194565b4484d3556d1b0c3d2f8bb8
Parents: 3a62ff8
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 19:35:15 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 19:35:15 2015 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be2d7994/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 8f43a97..665826f 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -6366,8 +6366,8 @@ public class Product {
         <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
+        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>
 


[16/35] incubator-freemarker git commit: New output formats were in the wrong source directory

Posted by dd...@apache.org.
New output formats were in the wrong source directory


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/bec1430b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/bec1430b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/bec1430b

Branch: refs/heads/2.3
Commit: bec1430b44ec205f08c8045825c8a0b10a7f87ab
Parents: 7051e55
Author: ddekany <dd...@apache.org>
Authored: Thu Dec 24 01:56:07 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Thu Dec 24 01:56:07 2015 +0100

----------------------------------------------------------------------
 .../java/freemarker/core/CSSOutputFormat.java   | 34 +++++++++++++++++++
 .../java/freemarker/core/JSONOutputFormat.java  | 34 +++++++++++++++++++
 .../freemarker/core/JavaScriptOutputFormat.java | 35 ++++++++++++++++++++
 .../java/freemarker/core/CSSOutputFormat.java   | 34 -------------------
 .../java/freemarker/core/JSONOutputFormat.java  | 34 -------------------
 .../freemarker/core/JavaScriptOutputFormat.java | 35 --------------------
 6 files changed, 103 insertions(+), 103 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bec1430b/src/main/java/freemarker/core/CSSOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/CSSOutputFormat.java b/src/main/java/freemarker/core/CSSOutputFormat.java
new file mode 100644
index 0000000..e60e1c5
--- /dev/null
+++ b/src/main/java/freemarker/core/CSSOutputFormat.java
@@ -0,0 +1,34 @@
+package freemarker.core;
+
+/**
+ * Represents the CSS output format (MIME type "text/css", name "CSS"). This format doesn't support escaping.
+ * 
+ * @since 2.3.24
+ */
+public class CSSOutputFormat extends OutputFormat {
+
+    /**
+     * The only instance (singleton) of this {@link OutputFormat}.
+     */
+    public static final CSSOutputFormat INSTANCE = new CSSOutputFormat();
+    
+    private CSSOutputFormat() {
+        // Only to decrease visibility
+    }
+    
+    @Override
+    public String getName() {
+        return "CSS";
+    }
+
+    @Override
+    public String getMimeType() {
+        return "text/css";
+    }
+
+    @Override
+    public boolean isOutputFormatMixingAllowed() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bec1430b/src/main/java/freemarker/core/JSONOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/JSONOutputFormat.java b/src/main/java/freemarker/core/JSONOutputFormat.java
new file mode 100644
index 0000000..7b0d9fe
--- /dev/null
+++ b/src/main/java/freemarker/core/JSONOutputFormat.java
@@ -0,0 +1,34 @@
+package freemarker.core;
+
+/**
+ * Represents the JSON output format (MIME type "application/json", name "JSON"). This format doesn't support escaping.
+ * 
+ * @since 2.3.24
+ */
+public class JSONOutputFormat extends OutputFormat {
+
+    /**
+     * The only instance (singleton) of this {@link OutputFormat}.
+     */
+    public static final JSONOutputFormat INSTANCE = new JSONOutputFormat();
+    
+    private JSONOutputFormat() {
+        // Only to decrease visibility
+    }
+    
+    @Override
+    public String getName() {
+        return "JSON";
+    }
+
+    @Override
+    public String getMimeType() {
+        return "application/json";
+    }
+
+    @Override
+    public boolean isOutputFormatMixingAllowed() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bec1430b/src/main/java/freemarker/core/JavaScriptOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/JavaScriptOutputFormat.java b/src/main/java/freemarker/core/JavaScriptOutputFormat.java
new file mode 100644
index 0000000..a6375af
--- /dev/null
+++ b/src/main/java/freemarker/core/JavaScriptOutputFormat.java
@@ -0,0 +1,35 @@
+package freemarker.core;
+
+/**
+ * Represents the JavaScript output format (MIME type "application/javascript", name "JavaScript"). This format doesn't
+ * support escaping.
+ * 
+ * @since 2.3.24
+ */
+public class JavaScriptOutputFormat extends OutputFormat {
+
+    /**
+     * The only instance (singleton) of this {@link OutputFormat}.
+     */
+    public static final JavaScriptOutputFormat INSTANCE = new JavaScriptOutputFormat();
+    
+    private JavaScriptOutputFormat() {
+        // Only to decrease visibility
+    }
+    
+    @Override
+    public String getName() {
+        return "JavaScript";
+    }
+
+    @Override
+    public String getMimeType() {
+        return "application/javascript";
+    }
+
+    @Override
+    public boolean isOutputFormatMixingAllowed() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bec1430b/src/test/java/freemarker/core/CSSOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/CSSOutputFormat.java b/src/test/java/freemarker/core/CSSOutputFormat.java
deleted file mode 100644
index e60e1c5..0000000
--- a/src/test/java/freemarker/core/CSSOutputFormat.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package freemarker.core;
-
-/**
- * Represents the CSS output format (MIME type "text/css", name "CSS"). This format doesn't support escaping.
- * 
- * @since 2.3.24
- */
-public class CSSOutputFormat extends OutputFormat {
-
-    /**
-     * The only instance (singleton) of this {@link OutputFormat}.
-     */
-    public static final CSSOutputFormat INSTANCE = new CSSOutputFormat();
-    
-    private CSSOutputFormat() {
-        // Only to decrease visibility
-    }
-    
-    @Override
-    public String getName() {
-        return "CSS";
-    }
-
-    @Override
-    public String getMimeType() {
-        return "text/css";
-    }
-
-    @Override
-    public boolean isOutputFormatMixingAllowed() {
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bec1430b/src/test/java/freemarker/core/JSONOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/JSONOutputFormat.java b/src/test/java/freemarker/core/JSONOutputFormat.java
deleted file mode 100644
index 7b0d9fe..0000000
--- a/src/test/java/freemarker/core/JSONOutputFormat.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package freemarker.core;
-
-/**
- * Represents the JSON output format (MIME type "application/json", name "JSON"). This format doesn't support escaping.
- * 
- * @since 2.3.24
- */
-public class JSONOutputFormat extends OutputFormat {
-
-    /**
-     * The only instance (singleton) of this {@link OutputFormat}.
-     */
-    public static final JSONOutputFormat INSTANCE = new JSONOutputFormat();
-    
-    private JSONOutputFormat() {
-        // Only to decrease visibility
-    }
-    
-    @Override
-    public String getName() {
-        return "JSON";
-    }
-
-    @Override
-    public String getMimeType() {
-        return "application/json";
-    }
-
-    @Override
-    public boolean isOutputFormatMixingAllowed() {
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bec1430b/src/test/java/freemarker/core/JavaScriptOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/JavaScriptOutputFormat.java b/src/test/java/freemarker/core/JavaScriptOutputFormat.java
deleted file mode 100644
index a6375af..0000000
--- a/src/test/java/freemarker/core/JavaScriptOutputFormat.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package freemarker.core;
-
-/**
- * Represents the JavaScript output format (MIME type "application/javascript", name "JavaScript"). This format doesn't
- * support escaping.
- * 
- * @since 2.3.24
- */
-public class JavaScriptOutputFormat extends OutputFormat {
-
-    /**
-     * The only instance (singleton) of this {@link OutputFormat}.
-     */
-    public static final JavaScriptOutputFormat INSTANCE = new JavaScriptOutputFormat();
-    
-    private JavaScriptOutputFormat() {
-        // Only to decrease visibility
-    }
-    
-    @Override
-    public String getName() {
-        return "JavaScript";
-    }
-
-    @Override
-    public String getMimeType() {
-        return "application/javascript";
-    }
-
-    @Override
-    public boolean isOutputFormatMixingAllowed() {
-        return false;
-    }
-
-}


[08/35] incubator-freemarker git commit: (More test for public static fields access in configuration strings)

Posted by dd...@apache.org.
(More test for public static fields access in configuration strings)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/d5c2d143
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/d5c2d143
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/d5c2d143

Branch: refs/heads/2.3
Commit: d5c2d14366140460877e106b54e10544c40547bf
Parents: 0020e66
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 02:28:10 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 02:28:10 2015 +0100

----------------------------------------------------------------------
 src/test/java/freemarker/core/ObjectBuilderSettingsTest.java | 7 +++++++
 1 file changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d5c2d143/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java b/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
index 4276c7a..57648ec 100644
--- a/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
+++ b/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
@@ -951,6 +951,13 @@ public class ObjectBuilderSettingsTest {
             assertThat(e.getMessage(),
                     containsString("freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST"));
         }
+        try {
+            assertEqualsEvaled(123, "java.lang.String(freemarker.core.ObjectBuilderSettingsTest$TestBean5.INSTANCE)");
+            fail();
+        } catch (_ObjectBuilderSettingEvaluationException e) {
+            assertThat(e.getMessage(),
+                    containsString("freemarker.core.ObjectBuilderSettingsTest$TestBean5()"));
+        }
     }
     
     private void assertEqualsEvaled(Object expectedValue, String s)


[30/35] incubator-freemarker git commit: Manual: Updated getting started example to use bean for latestProduct, and to use ftlh template extension.

Posted by dd...@apache.org.
Manual: Updated getting started example to use bean for latestProduct, and to use ftlh template extension.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/7dfa6642
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/7dfa6642
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/7dfa6642

Branch: refs/heads/2.3
Commit: 7dfa6642807583d26a52a8a27b6421e7cda0457c
Parents: 56b5f6e
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 17:11:34 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 17:11:34 2015 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml                       | 154 +++++++++++++------
 .../manual/GettingStartedExample.java           |  49 ++++++
 src/test/java/freemarker/manual/Product.java    |  31 ++++
 src/test/resources/freemarker/manual/test.ftlh  |  10 ++
 4 files changed, 194 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7dfa6642/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 092d18b..145eb3c 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -6288,10 +6288,10 @@ cfg.setLogTemplateExceptions(false);</programlisting>
           <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>getProperty()</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
+            <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>
@@ -6312,66 +6312,74 @@ cfg.setLogTemplateExceptions(false);</programlisting>
 
         <para>This Java code fragment that builds this data-model:</para>
 
-        <programlisting role="unspecified">// Create the root hash
+        <programlisting role="unspecified">// Create the root hash. We use a Map here, but it could be a JavaBean too.
 Map&lt;String, Object&gt; root = new HashMap&lt;&gt;();
-// Put string ``user'' into the root
+
+// Put string "user" into the root
 root.put("user", "Big Joe");
-// Create the hash for ``latestProduct''
-Map&lt;String, Object&gt; latest = new HashMap&lt;&gt;();
+
+// 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);
-// put ``url'' and ``name'' into latest
-latest.put("url", "products/greenmouse.html");
-latest.put("name", "green mouse");</programlisting>
+</programlisting>
 
-        <para>In real applications, instead of <literal>Map</literal>-s, you
-        will often use application-specific classes that has
+        <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 you have a
-        class similar to this:</para>
+        methods as prescribed by the JavaBeans specification. Like the above
+        <literal>Product</literal> class could be something like:</para>
 
-        <programlisting role="unspecified">public class Product {
+        <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;
     }
-    
-    ...
-    
-}</programlisting>
-
-        <para>and you add an instance of it to the data-model somehow like
-        this:</para>
 
-        <programlisting role="unspecified">Product latestProducts = getLatestProductFromDatabaseOrSomething();
-root.put("latestProduct", latestProduct);</programlisting>
+    public void setName(String name) {
+        this.name = name;
+    }
 
-        <para>The template will be the same as if
-        <literal>latestProduct</literal> was a <literal>Map</literal>, like
-        <literal>${latestProduct.name}</literal> works in both cases.</para>
+}</programlisting>
 
-        <para>The root itself need not be a <literal>Map</literal> either. It
-        could be an object with <literal>getUser()</literal> and
+        <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 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
+          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>
@@ -6392,21 +6400,21 @@ root.put("latestProduct", latestProduct);</programlisting>
         template instance you can get it with its
         <literal>getTemplate</literal> method. Store <link
         linkend="example.first">the example template</link> in the
-        <literal>test.ftl</literal> file of the <link
+        <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.ftl");</programlisting>
+        <programlisting role="unspecified">Template temp = cfg.getTemplate("test.ftlh");</programlisting>
 
         <para>When you call this, it will create a <literal>Template</literal>
-        instance corresponds to <literal>test.ftl</literal>, by reading
-        <literal><replaceable>/where/you/store/templates/</replaceable>test.ftl</literal>
+        instance corresponds to <literal>test.ftlh</literal>, by reading
+        <literal><replaceable>/where/you/store/templates/</replaceable>test.ftlh</literal>
         and parsing (compile) it. The <literal>Template</literal> instance
         stores the template in the parsed form, and not as text.</para>
 
         <para><literal>Configuration</literal> caches
         <literal>Template</literal> instances, so when you get
-        <literal>test.ftl</literal> again, it probably won't read and parse
+        <literal>test.ftlh</literal> again, 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>
@@ -6453,7 +6461,7 @@ temp.process(root, out);</programlisting>
         <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.ftl</literal> file is accessed only while 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>
@@ -6480,7 +6488,7 @@ public class Test {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_24);
         cfg.setDirectoryForTemplateLoading(new File("<replaceable>/where/you/store/templates</replaceable>"));
         cfg.setDefaultEncoding("UTF-8");
-        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW);
+        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
         cfg.setLogTemplateExceptions(false);
 
         /* ------------------------------------------------------------------------ */    
@@ -6489,13 +6497,13 @@ public class Test {
         /* Create a data-model */
         Map root = new HashMap();
         root.put("user", "Big Joe");
-        Map latest = new HashMap();
+        Product latest = new Product();
+        latest.setUrl("products/greenmouse.html");
+        latest.setName("green mouse");
         root.put("latestProduct", latest);
-        latest.put("url", "products/greenmouse.html");
-        latest.put("name", "green mouse");
 
         /* Get the template (uses cache internally) */
-        Template temp = cfg.getTemplate("test.ftl");
+        Template temp = cfg.getTemplate("test.ftlh");
 
         /* Merge data-model with template */
         Writer out = new OutputStreamWriter(System.out);
@@ -6509,6 +6517,52 @@ public class Test {
           <para>I have suppressed the exceptions for the sake of simplicity.
           Don't do it in real products.</para>
         </note>
+
+        <para>For the sake completeness, here's the the Product class used in
+        the data model:</para>
+
+        <programlisting role="unspecified">/**
+ * Product bean; note that it must be a public class!
+ */
+public class Product {
+
+    private String url;
+    private String name;
+
+    // As per the JavaBeans spec., this defines the "url" bean property
+    // It must be public!
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    // As per the JavaBean spec., this defines the "name" bean property
+    // It must be public!
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+}</programlisting>
+
+        <para>and the template:</para>
+
+        <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome ${user}!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
       </section>
     </chapter>
 
@@ -8623,7 +8677,7 @@ cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());</programlisti
 
           <para>will print this:</para>
 
-          <programlisting role="output">a[ERROR: Expression badVar is undefined on line 1, column 7 in test.ftl.]b</programlisting>
+          <programlisting role="output">a[ERROR: Expression badVar is undefined on line 1, column 7 in test.ftlh.]b</programlisting>
 
           <para>Note that the error occurred in the <literal>if</literal>
           start-tag (<literal>&lt;#if badVar&gt;</literal>), but the whole
@@ -8667,7 +8721,7 @@ b
 
           <programlisting role="output">a
   Foo
-  [ERROR: Expression badVar is undefined on line 4, column 5 in test.ftl.]
+  [ERROR: Expression badVar is undefined on line 4, column 5 in test.ftlh.]
   Bar
 c</programlisting>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7dfa6642/src/test/java/freemarker/manual/GettingStartedExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/GettingStartedExample.java b/src/test/java/freemarker/manual/GettingStartedExample.java
new file mode 100644
index 0000000..3e54c6c
--- /dev/null
+++ b/src/test/java/freemarker/manual/GettingStartedExample.java
@@ -0,0 +1,49 @@
+package freemarker.manual;
+
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
+
+public class GettingStartedExample {
+
+    @Test
+    public void main() 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_24);
+        cfg.setClassForTemplateLoading(GettingStartedExample.class, "");
+        cfg.setDefaultEncoding("UTF-8");
+        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+        cfg.setLogTemplateExceptions(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.
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7dfa6642/src/test/java/freemarker/manual/Product.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/Product.java b/src/test/java/freemarker/manual/Product.java
new file mode 100644
index 0000000..67d2cc6
--- /dev/null
+++ b/src/test/java/freemarker/manual/Product.java
@@ -0,0 +1,31 @@
+package freemarker.manual;
+
+/**
+ * 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;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7dfa6642/src/test/resources/freemarker/manual/test.ftlh
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/test.ftlh b/src/test/resources/freemarker/manual/test.ftlh
new file mode 100644
index 0000000..890b827
--- /dev/null
+++ b/src/test/resources/freemarker/manual/test.ftlh
@@ -0,0 +1,10 @@
+<html>
+<head>
+  <title>Welcome!</title>
+</head>
+<body>
+  <h1>Welcome ${user}!</h1>
+  <p>Our latest product:
+  <a href="${latestProduct.url}">${latestProduct.name}</a>!
+</body>
+</html>
\ No newline at end of file


[14/35] incubator-freemarker git commit: Added some non-escaping OutputFormat-s, just for the MIME type (that for example FreemarkerServlet can utilize); Updated/fixed OutputFormat-related JavaDocs and Manual parts.

Posted by dd...@apache.org.
Added some non-escaping OutputFormat-s, just for the MIME type (that for example FreemarkerServlet can utilize); Updated/fixed OutputFormat-related JavaDocs and Manual parts.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/2153e230
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/2153e230
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/2153e230

Branch: refs/heads/2.3
Commit: 2153e2309e49dd1f94cfd26f35377f62137e8306
Parents: d9f6b44
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 22 18:13:12 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 22 18:13:12 2015 +0100

----------------------------------------------------------------------
 .../java/freemarker/core/HTMLOutputFormat.java  |  4 +-
 .../freemarker/core/PlainTextOutputFormat.java  |  8 +--
 .../java/freemarker/core/RTFOutputFormat.java   |  4 +-
 .../java/freemarker/core/XHTMLOutputFormat.java |  4 +-
 .../java/freemarker/core/XMLOutputFormat.java   |  8 +--
 .../java/freemarker/template/Configuration.java |  6 +++
 src/manual/en_US/book.xml                       | 44 +++++++++++++++-
 .../java/freemarker/core/CSSOutputFormat.java   | 34 ++++++++++++
 .../java/freemarker/core/JSONOutputFormat.java  | 34 ++++++++++++
 .../freemarker/core/JavaScriptOutputFormat.java | 35 +++++++++++++
 .../ext/servlet/FreemarkerServletTest.java      | 55 ++++++++++++++++++++
 11 files changed, 222 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/HTMLOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/HTMLOutputFormat.java b/src/main/java/freemarker/core/HTMLOutputFormat.java
index 2adb5af..542b33a 100644
--- a/src/main/java/freemarker/core/HTMLOutputFormat.java
+++ b/src/main/java/freemarker/core/HTMLOutputFormat.java
@@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException;
 import freemarker.template.utility.StringUtil;
 
 /**
- * Represents the HTML output format.
+ * Represents the HTML output format (MIME type "text/html", name "HTML"). This format escapes by default (via
+ * {@link StringUtil#XHTMLEnc(String)}). The {@code ?html}, {@code ?xhtml} and {@code ?xml} built-ins silently bypass
+ * template output values of the type produced by this output format ({@link TemplateHTMLOutputModel}).
  * 
  * @since 2.3.24
  */

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/PlainTextOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/PlainTextOutputFormat.java b/src/main/java/freemarker/core/PlainTextOutputFormat.java
index 4321a39..82ac31b 100644
--- a/src/main/java/freemarker/core/PlainTextOutputFormat.java
+++ b/src/main/java/freemarker/core/PlainTextOutputFormat.java
@@ -19,12 +19,8 @@
 package freemarker.core;
 
 /**
- * Represents the plain text output format. Plain text is text without any characters with special meaning. As such, it
- * doesn't support escaping.
- * 
- * <p>
- * String literals in FTL expressions use this output format, which has importance when <code>${...}</code> is used
- * inside them.
+ * Represents the plain text output format (MIME type "text/plain", name "plainText"). This format doesn't support
+ * escaping. This format doesn't allow mixing in template output values of other output formats.
  * 
  * <p>
  * The main difference from {@link UndefinedOutputFormat} is that this format doesn't allow inserting values of another

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/RTFOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/RTFOutputFormat.java b/src/main/java/freemarker/core/RTFOutputFormat.java
index 86eb103..9aef2a7 100644
--- a/src/main/java/freemarker/core/RTFOutputFormat.java
+++ b/src/main/java/freemarker/core/RTFOutputFormat.java
@@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException;
 import freemarker.template.utility.StringUtil;
 
 /**
- * Represents the HTML output format.
+ * Represents the Rich Text Format output format (MIME type "application/rtf", name "RTF"). This format escapes by
+ * default (via {@link StringUtil#RTFEnc(String)}). The {@code ?rtf} built-in silently bypasses template output values
+ * of the type produced by this output format ({@link TemplateRTFOutputModel}).
  * 
  * @since 2.3.24
  */

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/XHTMLOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/XHTMLOutputFormat.java b/src/main/java/freemarker/core/XHTMLOutputFormat.java
index e14f597..432a5ff 100644
--- a/src/main/java/freemarker/core/XHTMLOutputFormat.java
+++ b/src/main/java/freemarker/core/XHTMLOutputFormat.java
@@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException;
 import freemarker.template.utility.StringUtil;
 
 /**
- * Represents the XHTML output format.
+ * Represents the XML output format (MIME type "application/xhtml+xml", name "XHTML"). This format escapes by default
+ * (via {@link StringUtil#XHTMLEnc(String)}). The {@code ?xml} built-in silently bypasses template output values of the
+ * type produced by this output format ({@link TemplateXHTMLOutputModel}).
  * 
  * @since 2.3.24
  */

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/XMLOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/XMLOutputFormat.java b/src/main/java/freemarker/core/XMLOutputFormat.java
index 9c45b7d..90fed02 100644
--- a/src/main/java/freemarker/core/XMLOutputFormat.java
+++ b/src/main/java/freemarker/core/XMLOutputFormat.java
@@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException;
 import freemarker.template.utility.StringUtil;
 
 /**
- * Represents the XML output format.
+ * Represents the XML output format (MIME type "application/xml", name "XML"). This format escapes by default (via
+ * {@link StringUtil#XMLEnc(String)}). The {@code ?html}, {@code ?xhtml} and {@code ?xml} built-ins silently bypass
+ * template output values of the type produced by this output format ({@link TemplateXHTMLOutputModel}).
  * 
  * @since 2.3.24
  */
@@ -35,11 +37,11 @@ public final class XMLOutputFormat extends CommonMarkupOutputFormat<TemplateXMLO
      * The only instance (singleton) of this {@link OutputFormat}.
      */
     public static final XMLOutputFormat INSTANCE = new XMLOutputFormat();
-    
+
     private XMLOutputFormat() {
         // Only to decrease visibility
     }
-    
+
     @Override
     public String getName() {
         return "XML";

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 0b9d5c3..4fd347c 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -58,10 +58,13 @@ import freemarker.cache.TemplateLookupStrategy;
 import freemarker.cache.TemplateNameFormat;
 import freemarker.cache.URLTemplateLoader;
 import freemarker.core.BugException;
+import freemarker.core.CSSOutputFormat;
 import freemarker.core.CombinedMarkupOutputFormat;
 import freemarker.core.Configurable;
 import freemarker.core.Environment;
 import freemarker.core.HTMLOutputFormat;
+import freemarker.core.JSONOutputFormat;
+import freemarker.core.JavaScriptOutputFormat;
 import freemarker.core.MarkupOutputFormat;
 import freemarker.core.OutputFormat;
 import freemarker.core.ParseException;
@@ -344,6 +347,9 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         STANDARD_OUTPUT_FORMATS.put(XMLOutputFormat.INSTANCE.getName(), XMLOutputFormat.INSTANCE);
         STANDARD_OUTPUT_FORMATS.put(RTFOutputFormat.INSTANCE.getName(), RTFOutputFormat.INSTANCE);
         STANDARD_OUTPUT_FORMATS.put(PlainTextOutputFormat.INSTANCE.getName(), PlainTextOutputFormat.INSTANCE);
+        STANDARD_OUTPUT_FORMATS.put(CSSOutputFormat.INSTANCE.getName(), CSSOutputFormat.INSTANCE);
+        STANDARD_OUTPUT_FORMATS.put(JavaScriptOutputFormat.INSTANCE.getName(), JavaScriptOutputFormat.INSTANCE);
+        STANDARD_OUTPUT_FORMATS.put(JSONOutputFormat.INSTANCE.getName(), JSONOutputFormat.INSTANCE);
     }
     
     public static final int AUTO_DETECT_TAG_SYNTAX = 0;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 4f6340a..b25ca0c 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -5383,13 +5383,42 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
               <tr>
                 <td><literal>plainText</literal></td>
 
-                <td>Doesn't escape. Doesn't accept markup output values from
-                other output formats.</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>
 
@@ -26482,6 +26511,17 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Added non-escaping formats (just for the MIME type):
+              <literal>JavaScriptOutputFormat</literal>,
+              <literal>JSONOutputFormat</literal>,
+              <literal>CSSOutputFormat</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Added JavaScriptOutput</para>
+            </listitem>
+
+            <listitem>
               <para>Added new built-in: <literal>is_markup_output</literal>,
               returns <literal>true</literal> if the value is of type
               <quote>markup output</quote>.</para>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/core/CSSOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/CSSOutputFormat.java b/src/test/java/freemarker/core/CSSOutputFormat.java
new file mode 100644
index 0000000..e60e1c5
--- /dev/null
+++ b/src/test/java/freemarker/core/CSSOutputFormat.java
@@ -0,0 +1,34 @@
+package freemarker.core;
+
+/**
+ * Represents the CSS output format (MIME type "text/css", name "CSS"). This format doesn't support escaping.
+ * 
+ * @since 2.3.24
+ */
+public class CSSOutputFormat extends OutputFormat {
+
+    /**
+     * The only instance (singleton) of this {@link OutputFormat}.
+     */
+    public static final CSSOutputFormat INSTANCE = new CSSOutputFormat();
+    
+    private CSSOutputFormat() {
+        // Only to decrease visibility
+    }
+    
+    @Override
+    public String getName() {
+        return "CSS";
+    }
+
+    @Override
+    public String getMimeType() {
+        return "text/css";
+    }
+
+    @Override
+    public boolean isOutputFormatMixingAllowed() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/core/JSONOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/JSONOutputFormat.java b/src/test/java/freemarker/core/JSONOutputFormat.java
new file mode 100644
index 0000000..7b0d9fe
--- /dev/null
+++ b/src/test/java/freemarker/core/JSONOutputFormat.java
@@ -0,0 +1,34 @@
+package freemarker.core;
+
+/**
+ * Represents the JSON output format (MIME type "application/json", name "JSON"). This format doesn't support escaping.
+ * 
+ * @since 2.3.24
+ */
+public class JSONOutputFormat extends OutputFormat {
+
+    /**
+     * The only instance (singleton) of this {@link OutputFormat}.
+     */
+    public static final JSONOutputFormat INSTANCE = new JSONOutputFormat();
+    
+    private JSONOutputFormat() {
+        // Only to decrease visibility
+    }
+    
+    @Override
+    public String getName() {
+        return "JSON";
+    }
+
+    @Override
+    public String getMimeType() {
+        return "application/json";
+    }
+
+    @Override
+    public boolean isOutputFormatMixingAllowed() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/core/JavaScriptOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/JavaScriptOutputFormat.java b/src/test/java/freemarker/core/JavaScriptOutputFormat.java
new file mode 100644
index 0000000..a6375af
--- /dev/null
+++ b/src/test/java/freemarker/core/JavaScriptOutputFormat.java
@@ -0,0 +1,35 @@
+package freemarker.core;
+
+/**
+ * Represents the JavaScript output format (MIME type "application/javascript", name "JavaScript"). This format doesn't
+ * support escaping.
+ * 
+ * @since 2.3.24
+ */
+public class JavaScriptOutputFormat extends OutputFormat {
+
+    /**
+     * The only instance (singleton) of this {@link OutputFormat}.
+     */
+    public static final JavaScriptOutputFormat INSTANCE = new JavaScriptOutputFormat();
+    
+    private JavaScriptOutputFormat() {
+        // Only to decrease visibility
+    }
+    
+    @Override
+    public String getName() {
+        return "JavaScript";
+    }
+
+    @Override
+    public String getMimeType() {
+        return "application/javascript";
+    }
+
+    @Override
+    public boolean isOutputFormatMixingAllowed() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
index 0e9f539..396e4ca 100644
--- a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
+++ b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
@@ -57,6 +57,14 @@ public class FreemarkerServletTest {
     private static final String FOO_FTL = "foo.ftl";
     private static final String FOO_SRC_UTF8_FTL = "foo-src-utf8.ftl";
     private static final String FOO_OUT_UTF8_FTL = "foo-out-utf8.ftl";
+    private static final String STD_OUTPUT_FORMAT_HTML_FTL = "stdOutputFormatHTML.ftl";
+    private static final String STD_OUTPUT_FORMAT_XML_FTL = "stdOutputFormatXML.ftl";
+    private static final String STD_OUTPUT_FORMAT_XHTML_FTL = "stdOutputFormatXHTML.ftl";
+    private static final String STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL = "stdOutputFormatJavaScript.ftl";
+    private static final String STD_OUTPUT_FORMAT_JSON_FTL = "stdOutputFormatJSON.ftl";
+    private static final String STD_OUTPUT_FORMAT_CSS_FTL = "stdOutputFormatCSS.ftl";
+    private static final String STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL = "stdOutputFormatPlainText.ftl";
+    private static final String STD_OUTPUT_FORMAT_RTF_FTL = "stdOutputFormatRTF.ftl";
 
     private static final Locale DEFAULT_LOCALE = Locale.US;
     private static final String CFG_DEFAULT_ENCODING = "US-ASCII";
@@ -154,6 +162,42 @@ public class FreemarkerServletTest {
     }
 
     @Test
+    public void testStandardContentType() throws Exception {
+        assertResponseContentTypeEquals(
+                "text/html; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_HTML_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "application/xhtml+xml; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_XHTML_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "application/xml; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_XML_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "application/javascript; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "application/json; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_JSON_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "text/css; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_CSS_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "text/plain; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, null); // <- request
+        assertResponseContentTypeEquals(
+                "application/rtf; charset=UTF-8", // <- expected
+                null, null, // <- init-params
+                STD_OUTPUT_FORMAT_RTF_FTL, null); // <- request
+    }
+    
+    @Test
     public void testResponseLocaleInitParams() throws Exception {
         assertTemplateLocaleEquals(
                 DEFAULT_LOCALE, // <- expected template locale
@@ -524,12 +568,23 @@ public class FreemarkerServletTest {
             // Override default template loader
             if (templatePath.equals("class://")) {
                 StringTemplateLoader tl = new StringTemplateLoader();
+                
                 tl.putTemplate(FOO_FTL, "foo");
                 tl.putTemplate(FOO_SRC_UTF8_FTL, "foo");
                 tl.putTemplate(FOO_OUT_UTF8_FTL, "foo");
                 tl.putTemplate(CONTENT_TYPE_ATTR_FTL, "<#ftl attributes={ 'content_type': 'text/plain' }>foo");
                 tl.putTemplate(CONTENT_TYPE_ATTR_WITH_CHARSET_FTL, "<#ftl attributes={ 'content_type': 'text/plain; charset=UTF-8' }>foo");
                 tl.putTemplate(OUTPUT_FORMAT_HEADER_FTL, "<#ftl outputFormat='plainText'>foo");
+                
+                tl.putTemplate(STD_OUTPUT_FORMAT_HTML_FTL, "<#ftl outputFormat='HTML'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_XHTML_FTL, "<#ftl outputFormat='XHTML'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_XML_FTL, "<#ftl outputFormat='XML'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, "<#ftl outputFormat='JavaScript'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_JSON_FTL, "<#ftl outputFormat='JSON'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_CSS_FTL, "<#ftl outputFormat='CSS'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, "<#ftl outputFormat='plainText'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_RTF_FTL, "<#ftl outputFormat='RTF'>");
+                
                 return tl;
             } else {
                 return super.createTemplateLoader(templatePath);


[22/35] incubator-freemarker git commit: Bug fixed, with incompatible_improvements set to 2.3.24: The #import directive meant to copy the library variable into a global variable if it's executed in the main namespace, but that haven't happened when the i

Posted by dd...@apache.org.
Bug fixed, with incompatible_improvements set to 2.3.24: The #import directive meant to copy the library variable into a global variable if it's executed in the main namespace, but that haven't happened when the imported template was already imported earlier in another namespace. (Also fixed some minor typos elsewhere, and added more import/include tests.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/55cb12e2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/55cb12e2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/55cb12e2

Branch: refs/heads/2.3
Commit: 55cb12e21fd92101b23a2fed112f1e77a2c4eb91
Parents: 576625f
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 00:46:49 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 00:46:49 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/Environment.java  |  7 +-
 .../java/freemarker/template/Configuration.java | 26 ++++++-
 src/manual/en_US/book.xml                       | 28 ++++++-
 .../freemarker/core/IncludeAndImportTest.java   | 81 ++++++++++++++++++++
 4 files changed, 136 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/55cb12e2/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 5ebf855..5ae1bf7 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -2421,7 +2421,7 @@ public final class Environment extends Configurable {
 
     /**
      * Same as {@link #getTemplateForInclusion(String, String, boolean, boolean)} with {@code false}
-     * {@code ignoreMissign} argument.
+     * {@code ignoreMissing} argument.
      */
     public Template getTemplateForInclusion(String name, String encoding, boolean parse)
             throws IOException {
@@ -2560,11 +2560,14 @@ public final class Environment extends Configurable {
         if (existingNamespace != null) {
             if (namespace != null) {
                 setVariable(namespace, existingNamespace);
+                if (isIcI2324OrLater() && currentNamespace == mainNamespace) {
+                    globalNamespace.put(namespace, existingNamespace);
+                }
             }
         } else {
             Namespace newNamespace = new Namespace(loadedTemplate);
             if (namespace != null) {
-                currentNamespace.put(namespace, newNamespace);
+                setVariable(namespace, newNamespace);
                 if (currentNamespace == mainNamespace) {
                     globalNamespace.put(namespace, newNamespace);
                 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/55cb12e2/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index a913cb7..bd7d46c 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -775,6 +775,11 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      *          {@code incompatibleImprovements} version number than that of the {@link Configuration}, if that's
      *          really what you want.)
      *       </li>
+     *       <li><p>
+     *          Fixed bug: The {@code #import} directive meant to copy the library variable into a global variable if
+     *          it's executed in the main namespace, but that haven't happened when the imported template was already
+     *          imported earlier in another namespace. 
+     *       </li>
      *     </ul>
      *   </li>
      * </ul>
@@ -2977,7 +2982,17 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     
     /**
      * Adds an invisible <code>#import <i>templateName</i> as <i>namespaceVarName</i></code> at the beginning of all
-     * templates. The order of the imports will be the same as the order in which they were added with this method.
+     * top-level templates (that is, to all templates that weren't included/imported from another template). While it
+     * only affects the top-level (main) template directly, as the imports there will create a global variable, the
+     * imports will be visible from the further imported templates too (though note that
+     * {@link #getIncompatibleImprovements()} set to 2.3.24 fixes a rarely surfacing bug here).
+     * 
+     * <p>
+     * The order of the imports will be the same as the order in which they were added with this method. Note that if
+     * there are also auto-includes ({@link #addAutoInclude(String)}), those inclusions will be executed after the
+     * auto-includes.
+     * 
+     * @see #setAutoImports(Map)
      */
     public void addAutoImport(String namespaceVarName, String templateName) {
         // "synchronized" is removed from the API as it's not safe to set anything after publishing the Configuration
@@ -3040,7 +3055,14 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     
     /**
      * Adds an invisible <code>#include <i>templateName</i> as <i>namespaceVarName</i></code> at the beginning of all
-     * templates. The order of the inclusions will be the same as the order in which they were added with this method.
+     * top-level templates (that is, to all templates that weren't included/imported from another template).
+     * 
+     * <p>
+     * The order of the inclusions will be the same as the order in which they were added with this method. Note that if
+     * there are also auto-imports ({@link #addAutoImport(String, String)}), those imports will be executed before the
+     * auto-includes, hence the library variables are accessible for the auto-includes.
+     * 
+     * @see #setAutoIncludes(List)
      */
     public void addAutoInclude(String templateName) {
         // "synchronized" is removed from the API as it's not safe to set anything after publishing the Configuration

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/55cb12e2/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 2745adb..a08d339 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -19527,7 +19527,9 @@ or
           by the caller of <literal>import</literal> (as if you would create
           it with <literal>assign</literal> directive), with the name given
           with the <literal><replaceable>hash</replaceable></literal>
-          parameter.</para>
+          parameter. If the import happens in the namespace of the main
+          template, the hash variable is also created in the global
+          namespace.</para>
 
           <para>If you call <literal>import</literal> with the same
           <literal><replaceable>path</replaceable></literal> for multiple
@@ -26915,6 +26917,17 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Bug fixed, with
+              <literal>incompatible_improvements</literal> set to 2.3.24
+              (<link linkend="topic.defaultObjectWrapperIcI">see how
+              here...</link>): The <literal>#import</literal> directive meant
+              to copy the library variable into a global variable if it's
+              executed in the main namespace, but that haven't happened when
+              the imported template was already imported earlier in another
+              namespace.</para>
+            </listitem>
+
+            <listitem>
               <para>Internal code cleanup: Mostly source code formatting, also
               many parser construction/setup cleanup</para>
             </listitem>
@@ -26951,7 +26964,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               but some might used these regardless to introspect templates.
               Earlier it had an <quote>embedded template</quote> parameter
               inside, now it has 0 (for purely static string literals), one or
-              multiple <quote>value part</quote>-ts, which are
+              more <quote>value part</quote>-s, which are
               <literal>String</literal>-s and
               <literal>Interpolation</literal>-s.</para>
             </listitem>
@@ -27240,6 +27253,17 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               context, but also the auto-escaping policy of it (basically, if
               auto-escapig is on or off).</para>
             </listitem>
+
+            <listitem>
+              <para>Bug fixed, with
+              <literal>incompatible_improvements</literal> set to 2.3.24
+              (<link linkend="topic.defaultObjectWrapperIcI">see how
+              here...</link>): The <literal>#import</literal> directive meant
+              to copy the library variable into a global variable if it's
+              executed in the main namespace, but that haven't happened when
+              the imported template was already imported earlier in another
+              namespace.</para>
+            </listitem>
           </itemizedlist>
         </section>
       </section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/55cb12e2/src/test/java/freemarker/core/IncludeAndImportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/IncludeAndImportTest.java b/src/test/java/freemarker/core/IncludeAndImportTest.java
new file mode 100644
index 0000000..6cd9d32
--- /dev/null
+++ b/src/test/java/freemarker/core/IncludeAndImportTest.java
@@ -0,0 +1,81 @@
+package freemarker.core;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import freemarker.cache.StringTemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import freemarker.test.TemplateTest;
+
+public class IncludeAndImportTest extends TemplateTest {
+
+    @Override
+    protected Configuration createConfiguration() throws Exception {
+        Configuration cfg = super.createConfiguration();
+        cfg.setTemplateLoader(new StringTemplateLoader());
+        return cfg;
+    }
+
+    @Before
+    public void setup() {
+        addTemplate("inc1.ftl", "[inc1]<#global inc1Cnt = (inc1Cnt!0) + 1><#global history = (history!) + 'I'>");
+        addTemplate("inc2.ftl", "[inc2]");
+        addTemplate("inc3.ftl", "[inc3]");
+        addTemplate("lib1.ftl", "<#global lib1Cnt = (lib1Cnt!0) + 1><#global history = (history!) + 'L1'>"
+                + "<#macro m>In lib1</#macro>");
+        addTemplate("lib2.ftl", "<#global history = (history!) + 'L2'>"
+                + "<#macro m>In lib2 (<@lib1.m/>)</#macro>");
+        addTemplate("lib3.ftl", "<#import 'lib1.ftl' as lib1>");
+    }
+
+    @Test
+    public void includeSameTwice() throws IOException, TemplateException {
+        assertOutput("<#include 'inc1.ftl'>${inc1Cnt}<#include 'inc1.ftl'>${inc1Cnt}", "[inc1]1[inc1]2");
+    }
+
+    @Test
+    public void importSameTwice() throws IOException, TemplateException {
+        assertOutput("<#import 'lib1.ftl' as i1>${lib1Cnt} <#import 'lib1.ftl' as i2>${lib1Cnt}", "1 1");
+    }
+
+    @Test
+    public void importInMainCreatesGlobal() throws IOException, TemplateException {
+        String ftl = "${.main.lib1???c} ${.globals.lib1???c}"
+                + "<#import 'lib1.ftl' as lib1> ${.main.lib1???c} ${.globals.lib1???c}";
+        String expectedOut = "false false true true";
+        assertOutput(ftl, expectedOut);
+        // No difference:
+        getConfiguration().setIncompatibleImprovements(Configuration.VERSION_2_3_24);
+        assertOutput(ftl, expectedOut);
+    }
+    
+    @Test
+    public void importInMainCreatesGlobalBugfix() throws IOException, TemplateException {
+        // An import in the main namespace should create a global variable, but there's a bug where that doesn't happen
+        // if the imported library was already initialized elsewhere.
+        String ftl = "<#import 'lib3.ftl' as lib3>${lib1Cnt} ${.main.lib1???c} ${.globals.lib1???c}, "
+        + "<#import 'lib1.ftl' as lib1>${lib1Cnt} ${.main.lib1???c} ${.globals.lib1???c}";
+        assertOutput(ftl, "1 false false, 1 true false");
+        // Activate bugfix:
+        getConfiguration().setIncompatibleImprovements(Configuration.VERSION_2_3_24);
+        assertOutput(ftl, "1 false false, 1 true true");
+    }
+
+    /**
+     * Tests the order of auto-includes and auto-imports, also that they only effect the main template directly.
+     */
+    @Test
+    public void autoIncludeAndAutoImport() throws IOException, TemplateException {
+        getConfiguration().addAutoInclude("inc1.ftl");
+        getConfiguration().addAutoInclude("inc2.ftl");
+        getConfiguration().addAutoImport("lib1", "lib1.ftl");
+        getConfiguration().addAutoImport("lib2", "lib2.ftl");
+        assertOutput(
+                "<#include 'inc3.ftl'>[main] ${inc1Cnt}, ${history}, <@lib1.m/>, <@lib2.m/>",
+                "[inc1][inc2][inc3][main] 1, L1L2I, In lib1, In lib2 (In lib1)");
+    }
+    
+}


[19/35] incubator-freemarker git commit: (Documentation typo fixes and small adjustments.)

Posted by dd...@apache.org.
(Documentation typo fixes and small adjustments.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/d3654bc3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/d3654bc3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/d3654bc3

Branch: refs/heads/2.3
Commit: d3654bc3eea27c2a9c7b2fbe43c7ec0a793df14b
Parents: ea39153
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 26 21:50:27 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Dec 26 21:50:27 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/Configurable.java | 5 +++--
 src/manual/en_US/book.xml                       | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d3654bc3/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index adba746..5594ba0 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -1536,8 +1536,9 @@ public class Configurable {
     /**
      * Sets a FreeMarker setting by a name and string value. If you can configure FreeMarker directly with Java (or
      * other programming language), you should use the dedicated setter methods instead (like
-     * {@link #setObjectWrapper(ObjectWrapper)}. This meant to be used if you get the settings from somewhere
-     * as text. Regardless, below you will find an overview of the settings available no matter how you set them. 
+     * {@link #setObjectWrapper(ObjectWrapper)}. This meant to be used only when you get settings from somewhere
+     * as {@link String}-{@link String} name-value pairs (typically, as a {@link Properties} object). Below you find an
+     * overview of the settings available.
      * 
      * <p>Note: As of FreeMarker 2.3.23, setting names can be written in camel case too. For example, instead of
      * {@code date_format} you can also use {@code dateFormat}. It's likely that camel case will become to the

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d3654bc3/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 51fae1f..555c8e4 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -8069,7 +8069,7 @@ myCfg.setDefaultEncoding("UTF-8");</programlisting>
           </listitem>
 
           <listitem>
-            <para><literal>Environment </literal>layer: There are two ways
+            <para><literal>Environment </literal>layer: There are two ways of
             doing it:</para>
 
             <itemizedlist>
@@ -17617,7 +17617,7 @@ Sorted by name.last:
             <primary>interpret built-in</primary>
           </indexterm>
 
-          <para>This built-in parser a string as an FTL template, and returns
+          <para>This built-in parses a string as an FTL template, and returns
           an user-defined directive that executes that template, just as if a
           template with that content were <link
           linkend="ref_directive_include"><literal>include</literal>-d</link>
@@ -17642,7 +17642,7 @@ Sorted by name.last:
           <literal>Configuration</literal> object, not from template that
           calls <literal>interpret</literal>. This also means that the
           previously auto-detected tag syntax or auto-detected naming
-          convention don't effect the parsing of the interpreted template.
+          convention doesn't effect the parsing of the interpreted template.
           This is consistent with how the <link
           linkend="ref_directive_include"><literal>include</literal>
           directive</link> works.</para>


[03/35] incubator-freemarker git commit: Made place for the Chinese manual.

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen-help/editors-readme.txt
----------------------------------------------------------------------
diff --git a/src/manual/docgen-help/editors-readme.txt b/src/manual/docgen-help/editors-readme.txt
deleted file mode 100644
index 5280d97..0000000
--- a/src/manual/docgen-help/editors-readme.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Guide to FreeMarker Manual for Editors
-======================================
-
-Non-technical
--------------
-
-- The Template Author's Guide is for Web designers. Assume that a
-  designer is not a programmer, (s)he doesn't even know what is Java.
-  Forget that FM is implemented in Java when you edit the Template
-  Author's Guide. Try to avoid technical writing.
-
-- In the Guide chapters, be careful not to mention things that were
-  not explained earlier. The Guide chapters should be understandable
-  if you read them continuously.
-
-- If you add a new topic or term, don't forget to add it to the Index.
-  Also, consider adding entries for it to the Glossary.
-
-- Don't use too sophisticated English. Use basic words and grammar.
-
-
-Technical
----------
-
-- For the editing use XXE (XMLmind XML Editor), with its default XML
-  *source* formatting settings (identation, max line length and like).
-  You should install the "DocBook 5 for Freemarker" addon, which you can
-  find inside the "docgen" top-level SVN module.
-
-- The HTML is generated with Docgen (docgen.jar), which will check some
-  of the rules described here. To invoke it, issue "ant manual" from
-  the root of the "freemarker" module. (Note: you may need to check out
-  and build "docgen" first.)
-
-- Understand all document conventions in the Preface chapter. Note that
-  all "programlisting"-s should have a "role" attribute with a value that
-  is either: "template", "dataModel", "output", "metaTemplate" or
-  "unspecified". (If you miss this, the XXE addon will show the
-  "programlisting" in red.)
-
-- Verbatim content in flow text:
-
-  * In flow text, all data object names, class names, FTL fragments,
-    HTML fragments, and all other verbatim content is inside "literal"
-    element.
-
-  * Use replaceable element inside literal element for replaceable
-    parts and meta-variables like:
-    <literal&lt;if <replaceable>condition</replaceable>></literal>
-    <literal><replaceable>templateDir</replaceable>/copyright.ftl</literal>
-
-- Hierarchy:
-
-  * The hierarchy should look like:
-
-      book -> part -> chapter -> section -> section -> section -> section
-
-    where the "part" and the "section"-s are optional.
-    Instead of chapter you may have "preface" or "appendix".
-
-  * Don't use "sect1", "sect2", etc. Instead nest "section"-s into each other,
-    but not deeper than 3 levels.
-
-  * Use "simplesect" if you want to divide up something visually, but
-    you don't want those sections to appear in the ToC, or go into their own
-    HTML page. "simplesect"-s can appear under all "section" nesting
-    levels, and they always look the same regardless of the "section"
-    nesting levels.
-
-- Lists:
-
-  * When you have list where the list items are short (a few words),
-    you should give spacing="compact" to the "itemizedlist" or
-    "orderedlist" element.
-
-  * Don't putting listings inside "para"-s. Put them between "para"-s instead.
-
-- Xrefs, id-s, links:
-
-  * id-s of parts, chapters, sections and similar elements must
-    contain US-ASCII lower case letters, US-ASCII numbers, and
-    underscore only. id-s of parts and chapters are used as the
-    filenames of HTML-s generated for that block.
-    When you find out the id, deduce it from the position in the ToC
-    hierarchy. The underscore is used as the separator between the path
-    steps.
-
-  * All other id-s must use prefix:
-    - example: E.g.: id="example.foreach"
-    - ref: Reference information...
-      * directive: about a directive. E.g.: "ref.directive.foreach"
-      * builtin
-    - gloss: Term in the Glossary
-    - topic: The recommended point of document in a certain topic
-      * designer: for designers.
-          E.g.: id="topic.designer.methodDataObject"
-      * programmer: for programmers
-      * or omit the secondary category if it is for everybody
-    - misc: Anything doesn't fit in the above categories
-
-  * When you refer to a part, chapter or section, often you should use
-    xref, not link. The xreflabel attribute of the link-end should not be set;
-    then it's deduced from the titles.
-
-- The "book" element must have this attribute: conformance="docgen"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen-misc/googleAnalytics.html
----------------------------------------------------------------------
diff --git a/src/manual/docgen-misc/googleAnalytics.html b/src/manual/docgen-misc/googleAnalytics.html
deleted file mode 100644
index bf440f2..0000000
--- a/src/manual/docgen-misc/googleAnalytics.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<script>
-  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
-
-  ga('create', 'UA-55420501-1', 'auto');
-  ga('send', 'pageview');
-</script>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen-originals/figures/model2sketch_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/docgen-originals/figures/model2sketch_with_alpha.png b/src/manual/docgen-originals/figures/model2sketch_with_alpha.png
deleted file mode 100644
index ce120cc..0000000
Binary files a/src/manual/docgen-originals/figures/model2sketch_with_alpha.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen-originals/figures/odg-convert-howto.txt
----------------------------------------------------------------------
diff --git a/src/manual/docgen-originals/figures/odg-convert-howto.txt b/src/manual/docgen-originals/figures/odg-convert-howto.txt
deleted file mode 100644
index 1db294c..0000000
--- a/src/manual/docgen-originals/figures/odg-convert-howto.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Converting to SVG:
-1. Open the ODG file with Libeoffice/OpenOffice Draw
-2. Ctrl+A to select all objects
-3. File/Export..., chose SVG format, and then tick "Selection"
-4. Check the result. If contour lines at the right and bottom edge of the
-   figure are partically clipped (stroke width is halved), set a stroke with
-   other than 0 for all shapes.
-   
-Converting to a decent quality (though non-transparent) PNG:
-1. Open the ODG file with Libeoffice/OpenOffice Draw
-2. Export to PDF
-3. Open PDF in Adobe Acrobat Reader
-4. Go to Adobe Acrobat Reader preferences and set it to not use subpixel
-   anti-aliasing, just normal anti-aliasing. They used to call this LCD vs
-   Monitor mode.
-5. Zoom in/out until you get the desired size in pixels, take a
-   screen shot, crop it in some image editor, save it as PNG.
-   
-Converting to transparent but somewhat ugly PNG:
-1. Convert to SVG as described earlier
-2. Use Apache Batik Rasterizer command line utility like:
-   $BARIK_INSTALLATION\batik-rasterizer-1.8.jar -dpi 72 -m image/png ${FIGURE}.svg
-   If Batik fails (as it doesn't support all SVG features), use Inkscape.
-   Of course avoid supixel anti-aliasing, as it's not device independent.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen-originals/figures/overview.odg
----------------------------------------------------------------------
diff --git a/src/manual/docgen-originals/figures/overview.odg b/src/manual/docgen-originals/figures/overview.odg
deleted file mode 100644
index 0533b7c..0000000
Binary files a/src/manual/docgen-originals/figures/overview.odg and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen-originals/figures/tree_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/docgen-originals/figures/tree_with_alpha.png b/src/manual/docgen-originals/figures/tree_with_alpha.png
deleted file mode 100644
index dc4fba8..0000000
Binary files a/src/manual/docgen-originals/figures/tree_with_alpha.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/docgen.cjson
----------------------------------------------------------------------
diff --git a/src/manual/docgen.cjson b/src/manual/docgen.cjson
deleted file mode 100644
index 221f349..0000000
--- a/src/manual/docgen.cjson
+++ /dev/null
@@ -1,112 +0,0 @@
-//charset: UTF-8
-
-deployUrl: "http://freemarker.org/docs/"
-onlineTrackerHTML: "docgen-misc/googleAnalytics.html"
-searchKey: "014728049242975963158:8awjt03uofm"
-validation: {
-  programlistingsRequireRole
-  // programlistingsRequireLanguage
-  maximumProgramlistingWidth: 100
-}
-showXXELogo
-generateEclipseTOC
-// eclipse: {
-//  link_to: "freemarker-toc.xml#ManualLink"
-// }
-
-removeNodesWhenOnline: [ "preface" ]
-
-copyrightHolder: "The FreeMarker Project"
-copyrightStartYear: 1999
-
-seoMeta: {
-  "dgui_quickstart": {
-    "title": "Getting Started with template writing"
-  }
-  "pgui_quickstart": {
-    "title": "Getting Started with the Java API"
-  }
-}
-
-logo: {
-  href: "http://freemarker.org"
-  src: logo.png,
-  alt: "FreeMarker"
-}
-
-olinks: {
-  homepage: "http://freemarker.org/"
-  api: "api/index.html"
-  
-  // Homepage links:
-  freemarkerdownload: "http://freemarker.org/freemarkerdownload.html"
-  contribute: "http://freemarker.org/contribute.html"
-  history: "http://freemarker.org/history.html"
-  what-is-freemarker: "id:preface"
-  mailing-lists: "http://freemarker.org/mailing-lists.html"
-  
-  // External URL-s:
-  onlineTemplateTester: "http://freemarker-online.kenshoo.com/"
-  twitter: "https://twitter.com/freemarker"
-  sourceforgeProject: "https://sourceforge.net/projects/freemarker/"
-  githubProject: "https://github.com/freemarker/freemarker"
-  newBugReport: "https://sourceforge.net/p/freemarker/bugs/new/"
-  newStackOverflowQuestion: "http://stackoverflow.com/questions/ask?tags=freemarker"
-}
-
-internalBookmarks: {
-  "Alpha. index": alphaidx
-  "Glossary": gloss
-  "Expressions": exp_cheatsheet
-  "?builtins": ref_builtins_alphaidx
-  "#directives": ref_directive_alphaidx
-  ".spec_vars": ref_specvar
-  "FAQ": app_faq
-}
-
-tabs: {
-  "Home": "olink:homepage"
-  "Manual": ""  // Empty => We are here
-  "Java API": "olink:api"
-}
-
-// Available icons:
-// .icon-heart
-// .icon-bug
-// .icon-download
-// .icon-star
-secondaryTabs: {
-  "Contribute": { class: "icon-heart", href: "olink:contribute" }
-  "Report a Bug": { class: "icon-bug", href: "olink:newBugReport" }
-  "Download": { class: "icon-download", href: "olink:freemarkerdownload" }
-}
-
-footerSiteMap: {
-  "Overview": {
-    "What is FreeMarker?": "olink:what-is-freemarker"
-    "Download": "olink:freemarkerdownload"
-    "Version history": "id:app_versions"
-    "About us": "olink:history"
-    "License": "id:app_license"
-  }
-  "Handy stuff": {
-    "Try template online": "olink:onlineTemplateTester"
-    "Expressions cheatsheet": "id:exp_cheatsheet"
-    "#directives": "id:ref_directive_alphaidx"
-    "?built_ins": "id:ref_builtins_alphaidx"
-    ".special_vars": "id:ref_specvar"
-  }
-  "Community": {
-    "FreeMarker on Github": "olink:githubProject"
-    "Follow us on Twitter": "olink:twitter"
-    "Report a bug": "olink:newBugReport"
-    "Ask a question": "olink:newStackOverflowQuestion"
-    "Mailing lists": "olink:mailing-lists"
-  }
-}
-
-socialLinks: {
-  "Github": { class: "github", href: "olink:githubProject" }
-  "Twitter": { class: "twitter", href: "olink:twitter" }
-  "Stack Overflow": { class: "stack-overflow", href: "olink:newStackOverflowQuestion" }
-}


[33/35] incubator-freemarker git commit: Bug fixed: With incompatible_improvements set to 2.3.24, m?is_sequence doesn't return true for Java methods wrapped by BeansWrapper and its subclasses (most notably DefaultObjectWrapper) anymore, as they only impl

Posted by dd...@apache.org.
Bug fixed: With incompatible_improvements set to 2.3.24, m?is_sequence doesn't return true for Java methods wrapped by BeansWrapper and its subclasses (most notably DefaultObjectWrapper) anymore, as they only implement the [index] operator, but not ?size, which causes <#list ...> to fail among others. (They shouldn't implement either, but this is historical heritage.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/3a62ff8e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/3a62ff8e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/3a62ff8e

Branch: refs/heads/2.3
Commit: 3a62ff8ecfc63bec8c43d4996ffa5839b9871a9e
Parents: 957264e
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 19:29:52 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 19:29:52 2015 +0100

----------------------------------------------------------------------
 .../core/BuiltInsForMultipleTypes.java          |  7 ++-
 src/main/java/freemarker/core/Environment.java  |  4 +-
 .../java/freemarker/template/Configuration.java |  5 ++
 src/manual/en_US/book.xml                       | 49 ++++++++++++++++++--
 .../expected/type-builtins-ici-2.3.24.txt       | 15 ++++++
 .../freemarker/test/templatesuite/testcases.xml |  5 +-
 6 files changed, 78 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3a62ff8e/src/main/java/freemarker/core/BuiltInsForMultipleTypes.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltInsForMultipleTypes.java b/src/main/java/freemarker/core/BuiltInsForMultipleTypes.java
index 861b370..81bcf59 100644
--- a/src/main/java/freemarker/core/BuiltInsForMultipleTypes.java
+++ b/src/main/java/freemarker/core/BuiltInsForMultipleTypes.java
@@ -436,7 +436,12 @@ class BuiltInsForMultipleTypes {
         TemplateModel _eval(Environment env) throws TemplateException {
             TemplateModel tm = target.eval(env);
             target.assertNonNull(tm, env);
-            return (tm instanceof TemplateSequenceModel) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
+            return (tm instanceof TemplateSequenceModel
+                        && (
+                            !(tm instanceof OverloadedMethodsModel || tm instanceof SimpleMethodModel)
+                            || !env.isIcI2324OrLater())
+                        )
+                        ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3a62ff8e/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 5ae1bf7..3d61aaa 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -92,7 +92,7 @@ import freemarker.template.utility.UndeclaredThrowableException;
  * {@link Template#createProcessingEnvironment(Object rootMap, Writer out, ObjectWrapper wrapper)}
  */
 public final class Environment extends Configurable {
-
+    
     private static final ThreadLocal threadEnv = new ThreadLocal();
 
     private static final Logger LOG = Logger.getLogger("freemarker.runtime");
@@ -2779,7 +2779,7 @@ public final class Environment extends Configurable {
         return configuration.getIncompatibleImprovements().intValue() < _TemplateAPI.VERSION_INT_2_3_22;
     }
 
-    private boolean isIcI2324OrLater() {
+    boolean isIcI2324OrLater() {
         return configuration.getIncompatibleImprovements().intValue() >= _TemplateAPI.VERSION_INT_2_3_24;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3a62ff8e/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 8be37db..82c46b3 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -780,6 +780,11 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      *          it's executed in the main namespace, but that haven't happened when the imported template was already
      *          imported earlier in another namespace. 
      *       </li>
+     *       <li><p>
+     *          {@code ?is_sequence} doesn't return {@code true} for Java methods wrapped by {@link BeansWrapper} and
+     *          its subclasses (most notably {@link DefaultObjectWrapper}) anymore, as they only implement the
+     *          {@code [index]} operator, but not {@code ?size}, which causes {@code <#list ...>} to fail among others.
+     *          (They shouldn't implement either, but this is historical heritage.)
      *     </ul>
      *   </li>
      * </ul>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3a62ff8e/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 145eb3c..8f43a97 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -17886,7 +17886,13 @@ Sorted by name.last:
               <tr>
                 <td><literal>is_sequence</literal></td>
 
-                <td>sequence</td>
+                <td>sequence (Historical quirk: Before <link
+                linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incompatible_improvements</literal></link>
+                2.3.24 it returns <literal>true</literal> for Java methods as
+                they implement the
+                <literal>[<replaceable>index</replaceable>]</literal>
+                operator, however, they fail on
+                <literal>?size</literal>.)</td>
               </tr>
 
               <tr>
@@ -17911,7 +17917,10 @@ Sorted by name.last:
               <tr>
                 <td><literal>is_indexable</literal></td>
 
-                <td>sequence</td>
+                <td>sequence (Historical quirk: it returns
+                <literal>true</literal> for Java methods as they implement the
+                <literal>[<replaceable>index</replaceable>]</literal>
+                operator.)</td>
               </tr>
 
               <tr>
@@ -26553,11 +26562,28 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
             <listitem>
               <para><literal>&lt;@</literal> and <literal>&lt;/@</literal> is
-              now allowed in String literals that contain
+              now allowed in string literals that contain
               <literal>${<replaceable>exp</replaceable>}</literal>, and will
               be part of the literal as is. Earlier it was a syntactical
               error.</para>
             </listitem>
+
+            <listitem>
+              <para>Bug fixed: With
+              <literal>incompatible_improvements</literal> set to 2.3.24
+              (<link linkend="topic.defaultObjectWrapperIcI">see how
+              here...</link>),
+              <literal><replaceable>m</replaceable>?is_sequence</literal>
+              doesn't return <literal>true</literal> for Java methods wrapped
+              by <literal>BeansWrapper</literal> and its subclasses (most
+              notably <literal>DefaultObjectWrapper</literal>) anymore, as
+              they only implement the
+              <literal>[<replaceable>index</replaceable>]</literal> operator,
+              but not <literal>?size</literal>, which causes
+              <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
+              to fail among others. (They shouldn't implement either, but this
+              is historical heritage.)</para>
+            </listitem>
           </itemizedlist>
         </section>
 
@@ -27448,6 +27474,23 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Bug fixed: With
+              <literal>incompatible_improvements</literal> set to 2.3.24
+              (<link linkend="topic.defaultObjectWrapperIcI">see how
+              here...</link>),
+              <literal><replaceable>m</replaceable>?is_sequence</literal>
+              doesn't return <literal>true</literal> for Java methods wrapped
+              by <literal>BeansWrapper</literal> and its subclasses (most
+              notably <literal>DefaultObjectWrapper</literal>) anymore, as
+              they only implement the
+              <literal>[<replaceable>index</replaceable>]</literal> operator,
+              but not <literal>?size</literal>, which causes
+              <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
+              to fail among others. (They shouldn't implement either, but this
+              is historical heritage.)</para>
+            </listitem>
+
+            <listitem>
               <para>Added an overload to
               <literal>Configuration.getSupportedBuiltInNames</literal> and
               <literal>Configuration.getSupportedBuiltInDirectiveNames</literal>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3a62ff8e/src/test/resources/freemarker/test/templatesuite/expected/type-builtins-ici-2.3.24.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/expected/type-builtins-ici-2.3.24.txt b/src/test/resources/freemarker/test/templatesuite/expected/type-builtins-ici-2.3.24.txt
new file mode 100644
index 0000000..b96f6f9
--- /dev/null
+++ b/src/test/resources/freemarker/test/templatesuite/expected/type-builtins-ici-2.3.24.txt
@@ -0,0 +1,15 @@
+StNuBoMeTaMaHaHxSeCoCxEnInDiNo
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
+0 0 0 0 0 1 0 0 0 0 0 0 0 1 0
+0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 1 0 0 1 1 0 0
+0 0 0 0 0 0 0 0 0 1 0 1 0 0 0
+0 0 0 0 0 0 0 0 0 1 1 1 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
+1 0 0 0 0 0 1 1 0 0 0 0 0 0 0
+0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
+0 0 0 1 0 0 0 0 0 0 0 0 1 0 0

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3a62ff8e/src/test/resources/freemarker/test/templatesuite/testcases.xml
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/testcases.xml b/src/test/resources/freemarker/test/templatesuite/testcases.xml
index 31d6606..4a6e539 100644
--- a/src/test/resources/freemarker/test/templatesuite/testcases.xml
+++ b/src/test/resources/freemarker/test/templatesuite/testcases.xml
@@ -186,7 +186,10 @@
       <setting incompatible_improvements="min, 2.3.20"/>
    </testCase>
    <testCase name="type-builtins[#endTN]-ici-2.3.21">
-   	  <setting incompatible_improvements="2.3.21, max"/>
+   	  <setting incompatible_improvements="2.3.21, 2.3.23"/>
+   </testCase>
+   <testCase name="type-builtins[#endTN]-ici-2.3.24">
+      <setting incompatible_improvements="2.3.24, max"/>
    </testCase>
    <testCase name="date-type-builtins" noOutput="true" />
    <testCase name="url" noOutput="true" />


[23/35] incubator-freemarker git commit: Bug fixed: XPath queries that has only contained characters that are valid in XML element names and has also contained :: (which is valid in names in namespace-unware documents), like e['following-sibling::foo'],

Posted by dd...@apache.org.
Bug fixed: XPath queries that has only contained characters that are valid in XML element names and has also contained :: (which is valid in names in namespace-unware documents), like e['following-sibling::foo'], were interpreted as literal element names (giving 0 hits) rather than as XPath expressions. Note that there were no such problem with e['following-sibling::*'] for example, as it's not a valid XML element name according the XML specification. This fix can actually break applications that has processed namespace unaware XML that use :: as part of element or attribute names, but such an application is highly unlikely, unlike running into the fixed problem. (Unfortunately, using incompatible_improvements wasn't technically possible here.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/33ba278f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/33ba278f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/33ba278f

Branch: refs/heads/2.3
Commit: 33ba278fdd7a26653d2f96f945c3e5e701a9acf5
Parents: 55cb12e
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 20:17:40 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 20:17:40 2015 +0100

----------------------------------------------------------------------
 .../java/freemarker/ext/dom/NodeListModel.java  |  5 ++
 src/main/java/freemarker/ext/dom/NodeModel.java |  6 ++-
 .../freemarker/template/utility/StringUtil.java | 27 +++++++---
 src/manual/en_US/book.xml                       | 40 +++++++++++++-
 src/test/java/freemarker/ext/dom/DOMTest.java   | 55 ++++++++++++++++++++
 5 files changed, 124 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/33ba278f/src/main/java/freemarker/ext/dom/NodeListModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/dom/NodeListModel.java b/src/main/java/freemarker/ext/dom/NodeListModel.java
index c0e85b9..22e555a 100644
--- a/src/main/java/freemarker/ext/dom/NodeListModel.java
+++ b/src/main/java/freemarker/ext/dom/NodeListModel.java
@@ -42,6 +42,11 @@ import freemarker.template.TemplateScalarModel;
 import freemarker.template.TemplateSequenceModel;
 import freemarker.template.utility.StringUtil;
 
+/**
+ * Used when the result set contains 0 or multiple nodes; shouldn't be used when you have exactly 1 node. For exactly 1
+ * node, use {@link NodeModel#wrap(Node)}, because {@link NodeModel} subclasses can have extra features building on that
+ * restriction, like single elements with text content can be used as FTL string-s.
+ */
 class NodeListModel extends SimpleSequence implements TemplateHashModel, _UnexpectedTypeErrorExplainerTemplateModel {
     
     NodeModel contextNode;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/33ba278f/src/main/java/freemarker/ext/dom/NodeModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/dom/NodeModel.java b/src/main/java/freemarker/ext/dom/NodeModel.java
index c0ade05..c338664 100644
--- a/src/main/java/freemarker/ext/dom/NodeModel.java
+++ b/src/main/java/freemarker/ext/dom/NodeModel.java
@@ -63,12 +63,16 @@ import freemarker.template.TemplateNumberModel;
 import freemarker.template.TemplateSequenceModel;
 
 /**
- * A base class for wrapping a W3C DOM Node as a FreeMarker template model.
+ * A base class for wrapping a single W3C DOM Node as a FreeMarker template model.
  * 
  * <p>
  * Note that {@link DefaultObjectWrapper} automatically wraps W3C DOM {@link Node}-s into this, so you may not need to
  * do that with this class manually. Though, before dropping the {@link Node}-s into the data-model, you may want to
  * apply {@link NodeModel#simplify(Node)} on them.
+ * 
+ * <p>
+ * Note that this class shouldn't be used to represent a result set of 0 or multiple nodes (we use {@link NodeListModel}
+ * then), but should be used to represent a node set of exactly 1 node.
  */
 abstract public class NodeModel
 implements TemplateNodeModel, TemplateHashModel, TemplateSequenceModel,

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/33ba278f/src/main/java/freemarker/template/utility/StringUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/StringUtil.java b/src/main/java/freemarker/template/utility/StringUtil.java
index 881bb3b..973c1f4 100644
--- a/src/main/java/freemarker/template/utility/StringUtil.java
+++ b/src/main/java/freemarker/template/utility/StringUtil.java
@@ -1653,18 +1653,31 @@ public class StringUtil {
     }
     
     /**
-     * @return whether the name is a valid XML tagname.
-     * (This routine might only be 99% accurate. Should maybe REVISIT) 
+     * Used internally by the XML DOM wrapper to check if the subvariable name is just an element name, or a more
+     * complex XPath expression.
+     * 
+     * @return whether the name is a valid XML tagname. (This routine might only be 99% accurate. Should maybe REVISIT)
+     * 
+     * @deprecated Don't use this outside FreeMarker; it's name if misleading, and it doesn't follow the XML specs.
      */
+    @Deprecated
     static public boolean isXMLID(String name) {
-        for (int i = 0; i < name.length(); i++) {
+        int ln = name.length();
+        for (int i = 0; i < ln; i++) {
             char c = name.charAt(i);
-            if (i == 0) {
-                if (c == '-' || c == '.' || Character.isDigit(c))
+            if (i == 0 && (c == '-' || c == '.' || Character.isDigit(c))) {
                     return false;
             }
-            if (!Character.isLetterOrDigit(c) && c != ':' && c != '_' && c != '-' && c != '.') {
-                return false;
+            if (!Character.isLetterOrDigit(c) && c != '_' && c != '-' && c != '.') {
+                if (c == ':') {
+                    if (i + 1 < ln && name.charAt(i + 1) == ':') {
+                        // "::" is used in XPath
+                        return false;
+                    }
+                    // We don't return here, as a lonely ":" is allowed.
+                } else {
+                    return false;
+                }
             }
         }
         return true;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/33ba278f/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index a08d339..ba8c1b1 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -7250,7 +7250,7 @@ public class RepeatDirective implements TemplateDirectiveModel {
           nested calls of the same directive, or directive objects used as
           shared variables accessed by multiple threads concurrently.</para>
 
-          <para>Unfortunatelly, <literal>TemplateDirectiveModel</literal>-s
+          <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>
@@ -26928,6 +26928,25 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Bug fixed: XPath queries that has only contained
+              characters that are valid in XML element names and has also
+              contained <literal>::</literal> (which is valid in names in
+              namespace-unware documents), like
+              <literal>e['following-sibling::foo']</literal>, were interpreted
+              as literal element names (giving 0 hits) rather than as XPath
+              expressions. Note that there were no such problem with
+              <literal>e['following-sibling::*']</literal> for example, as
+              it's not a valid XML element name according the XML
+              specification. This fix can actually break applications that has
+              processed namespace unaware XML that use <literal>::</literal>
+              as part of element or attribute names, but such an application
+              is highly unlikely, unlike running into the fixed problem.
+              (Unfortunately, using
+              <literal>incompatible_improvements</literal> wasn't technically
+              possible here.)</para>
+            </listitem>
+
+            <listitem>
               <para>Internal code cleanup: Mostly source code formatting, also
               many parser construction/setup cleanup</para>
             </listitem>
@@ -27264,6 +27283,25 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               the imported template was already imported earlier in another
               namespace.</para>
             </listitem>
+
+            <listitem>
+              <para>Bug fixed: XPath queries that has only contained
+              characters that are valid in XML element names and has also
+              contained <literal>::</literal> (which is valid in names in
+              namespace-unware documents), like
+              <literal>e['following-sibling::foo']</literal>, were interpreted
+              as literal element names (giving 0 hits) rather than as XPath
+              expressions. Note that there were no such problem with
+              <literal>e['following-sibling::*']</literal> for example, as
+              it's not a valid XML element name according the XML
+              specification. This fix can actually break applications that has
+              processed namespace unaware XML that use <literal>::</literal>
+              as part of element or attribute names, but such an application
+              is highly unlikely, unlike running into the fixed problem.
+              (Unfortunately, using
+              <literal>incompatible_improvements</literal> wasn't technically
+              possible here.)</para>
+            </listitem>
           </itemizedlist>
         </section>
       </section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/33ba278f/src/test/java/freemarker/ext/dom/DOMTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/dom/DOMTest.java b/src/test/java/freemarker/ext/dom/DOMTest.java
new file mode 100644
index 0000000..182ac31
--- /dev/null
+++ b/src/test/java/freemarker/ext/dom/DOMTest.java
@@ -0,0 +1,55 @@
+package freemarker.ext.dom;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import freemarker.template.TemplateException;
+import freemarker.test.TemplateTest;
+
+public class DOMTest extends TemplateTest {
+
+    @Test
+    public void xpathDetectionBugfix() throws Exception {
+        addDocToDataModel("<root><a>A</a><b>B</b><c>C</c></root>");
+        assertOutput("${doc.root.b['following-sibling::c']}", "C");
+        assertOutput("${doc.root.b['following-sibling::*']}", "C");
+    }
+
+    @Test
+    public void namespaceUnaware() throws Exception {
+        addNSUnawareDocToDataModel("<root><x:a>A</x:a><:>B</:><xyz::c>C</xyz::c></root>");
+        assertOutput("${doc.root['x:a']}", "A");
+        assertOutput("${doc.root[':']}", "B");
+        try {
+            assertOutput("${doc.root['xyz::c']}", "C");
+            fail();
+        } catch (TemplateException e) {
+            assertThat(e.getMessage(), containsString("xyz"));
+        }
+    }
+    
+    private void addDocToDataModel(String xml) throws SAXException, IOException, ParserConfigurationException {
+        addToDataModel("doc", NodeModel.parse(new InputSource(new StringReader(xml))));
+    }
+
+    private void addNSUnawareDocToDataModel(String xml) throws ParserConfigurationException, SAXException, IOException {
+        DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance();
+        newFactory.setNamespaceAware(false);
+        DocumentBuilder builder = newFactory.newDocumentBuilder();
+        Document doc = builder.parse(new InputSource(new StringReader(xml)));
+        addToDataModel("doc", doc);
+    }
+
+}


[21/35] incubator-freemarker git commit: (Added an ?interpret test)

Posted by dd...@apache.org.
(Added an ?interpret test)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/576625f5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/576625f5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/576625f5

Branch: refs/heads/2.3
Commit: 576625f559d3d86d98c85e30488b1eb5977c546d
Parents: 90fcfb9
Author: ddekany <dd...@apache.org>
Authored: Sun Dec 27 16:31:59 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 27 16:31:59 2015 +0100

----------------------------------------------------------------------
 .../resources/freemarker/test/templatesuite/expected/interpret.txt | 2 ++
 .../freemarker/test/templatesuite/templates/interpret.ftl          | 2 ++
 2 files changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/576625f5/src/test/resources/freemarker/test/templatesuite/expected/interpret.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/expected/interpret.txt b/src/test/resources/freemarker/test/templatesuite/expected/interpret.txt
index 8430235..4b93e22 100644
--- a/src/test/resources/freemarker/test/templatesuite/expected/interpret.txt
+++ b/src/test/resources/freemarker/test/templatesuite/expected/interpret.txt
@@ -1,3 +1,5 @@
 abcdef
 abcdef
 abcdef
+
+M
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/576625f5/src/test/resources/freemarker/test/templatesuite/templates/interpret.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/templates/interpret.ftl b/src/test/resources/freemarker/test/templatesuite/templates/interpret.ftl
index cc82c9d..46f6197 100644
--- a/src/test/resources/freemarker/test/templatesuite/templates/interpret.ftl
+++ b/src/test/resources/freemarker/test/templatesuite/templates/interpret.ftl
@@ -3,3 +3,5 @@
 <#transform templateSource?interpret>def</#transform>
 <#transform [templateSource]?interpret>def</#transform>
 <#transform [templateSource,"id"]?interpret>def</#transform>
+
+<#assign t = '<#macro m>M</#macro>'?interpret><@t /><@m/>
\ No newline at end of file


[07/35] incubator-freemarker git commit: Extending .gitignore with IntelliJ, OS X, and other common ignorables

Posted by dd...@apache.org.
Extending .gitignore with IntelliJ, OS X, and other common ignorables


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/0020e665
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/0020e665
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/0020e665

Branch: refs/heads/2.3
Commit: 0020e6653a024f17abbc333a197e92a24c0922ff
Parents: fe799f5
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 02:19:14 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 02:19:14 2015 +0100

----------------------------------------------------------------------
 .gitignore | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0020e665/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 9961665..3bc5db4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,5 +5,26 @@
 /archive/
 /ide-dependencies/
 
-src/manual/book.xml~
+/out/
+/bin/
+/target/
 
+.idea/
+*.iml
+*.iws
+*.ipr
+.idea_modules/
+
+*.tmp
+*.bak
+*.swp
+*~
+
+.gradle
+
+.DS_Store
+.AppleDouble
+.LSOverride
+
+.directory
+.Trash-*


[31/35] incubator-freemarker git commit: (Added missing copyright headers.)

Posted by dd...@apache.org.
(Added missing copyright headers.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/64c1b082
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/64c1b082
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/64c1b082

Branch: refs/heads/2.3
Commit: 64c1b0821a24455a94850f5f6e30b80455e653f2
Parents: 7dfa664
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 17:25:55 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 17:25:55 2015 +0100

----------------------------------------------------------------------
 .../freemarker/manual/GettingStartedExample.java  | 18 ++++++++++++++++++
 src/test/java/freemarker/manual/Product.java      | 18 ++++++++++++++++++
 2 files changed, 36 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/64c1b082/src/test/java/freemarker/manual/GettingStartedExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/GettingStartedExample.java b/src/test/java/freemarker/manual/GettingStartedExample.java
index 3e54c6c..af67eb1 100644
--- a/src/test/java/freemarker/manual/GettingStartedExample.java
+++ b/src/test/java/freemarker/manual/GettingStartedExample.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.manual;
 
 import java.io.OutputStreamWriter;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/64c1b082/src/test/java/freemarker/manual/Product.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/Product.java b/src/test/java/freemarker/manual/Product.java
index 67d2cc6..7f27456 100644
--- a/src/test/java/freemarker/manual/Product.java
+++ b/src/test/java/freemarker/manual/Product.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package freemarker.manual;
 
 /**


[15/35] incubator-freemarker git commit: More helpful JavaDoc for some OutputFormat-related parts.

Posted by dd...@apache.org.
More helpful JavaDoc for some OutputFormat-related parts.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/7051e55c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/7051e55c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/7051e55c

Branch: refs/heads/2.3
Commit: 7051e55cfffe244a9ef537c62ec71d45c9d569ad
Parents: 2153e23
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 22 22:17:39 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 22 22:17:39 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/template/Configuration.java | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7051e55c/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 4fd347c..7226ef2 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -1800,11 +1800,15 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
     
     /**
-     * Sets the (default) output format. Usually, you leave this on its default, which is
-     * {@link UndefinedOutputFormat#INSTANCE}, and then override it for individual templates based on their name (like
-     * based on their "file" extension) with {@link #setTemplateConfigurations(TemplateConfigurationFactory)}. This
-     * setting is also overridden by the standard file extensions; see them at
-     * {@link #setRecognizeStandardFileExtensions(boolean)}.
+     * Sets the default output format. Usually, you should leave this on its default, which is
+     * {@link UndefinedOutputFormat#INSTANCE}, and then use standard file extensions like "ftlh" (for HTML output) and
+     * ensure that {@link #setRecognizeStandardFileExtensions(boolean)} is {@code true} (see the description of standard
+     * file extensions there too). Where that approach doesn't fit, like you have no control over the file extensions,
+     * templates can be associated to output formats with patterns matching their name (their path) using
+     * {@link #setTemplateConfigurations(TemplateConfigurationFactory)}. Last not least, if all templates will have the
+     * same output format, you may use {@link #setOutputFormat(OutputFormat)} to set a value like
+     * {@link HTMLOutputFormat#INSTANCE}, {@link XMLOutputFormat#INSTANCE}, etc. Also note templates can specify their
+     * own output format like {@code <#ftl output_format="HTML">}, which overrides any configuration settings. 
      * 
      * <p>
      * The output format is mostly important because of auto-escaping (see {@link #setAutoEscapingPolicy(int)}), but


[32/35] incubator-freemarker git commit: (Fixed compilation error in FTL.jj-generated code)

Posted by dd...@apache.org.
(Fixed compilation error in FTL.jj-generated code)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/957264e7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/957264e7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/957264e7

Branch: refs/heads/2.3
Commit: 957264e7984803f8c4ae528ebf5dfd2405ac69de
Parents: 64c1b08
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 19:29:10 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 19:29:10 2015 +0100

----------------------------------------------------------------------
 src/main/javacc/FTL.jj | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/957264e7/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 9c858e8..b800eb4 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -860,7 +860,7 @@ TOKEN:
     <#CLOSE_TAG2 : (<BLANK>)* ("/")? (">" | "]")>
     |
     /*
-     * ATTENTION: Update _CoreAPI.BUILT_IN_DIRECTIVE_NAMES if you add new directives!
+     * ATTENTION: Update _CoreAPI.*_BUILT_IN_DIRECTIVE_NAMES if you add new directives!
      */
     <ATTEMPT : <START_TAG> "attempt" <CLOSE_TAG1>> { strictSyntaxCheck(matchedToken, DEFAULT); }
     |
@@ -1033,7 +1033,7 @@ TOKEN:
     <TRIVIAL_FTL_HEADER : ("<#ftl" | "[#ftl") ("/")? (">" | "]")> { ftlHeader(matchedToken); }
     |
     /*
-     * ATTENTION: Update _CoreAPI.BUILT_IN_DIRECTIVE_NAMES if you add new directives!
+     * ATTENTION: Update _CoreAPI.*_BUILT_IN_DIRECTIVE_NAMES if you add new directives!
      */
     <UNKNOWN_DIRECTIVE : ("[#" | "[/#" | "<#" | "</#") (["a"-"z", "A"-"Z", "_"])+>
     {
@@ -1060,7 +1060,7 @@ TOKEN:
                 // doesn't match any directive starter tokens, because that token requires whitespace after the
                 // name as it should be followed by parameters. For now we work this around so we don't report
                 // unknown directive:
-                if (_CoreAPI.BUILT_IN_DIRECTIVE_NAMES.contains(dn)) {
+                if (_CoreAPI.ALL_BUILT_IN_DIRECTIVE_NAMES.contains(dn)) {
                     throw new TokenMgrError(
                             "#" + dn + " is an existing directive, but the tag is malformed. " 
                             + " (See FreeMarker Manual / Directive Reference.)",


[06/35] incubator-freemarker git commit: In the mini-language used for configuring FreeMarker from java.util.Properties or other string-only sources (but not used inside templates): public static fields can be referred like com.example.MyClass.MY_CONSTAN

Posted by dd...@apache.org.
In the mini-language used for configuring FreeMarker from java.util.Properties or other string-only sources (but not used inside templates): public static fields can be referred like com.example.MyClass.MY_CONSTANT or Configuration.AUTO_DETECT_TAG_SYNTAX.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/fe799f5d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/fe799f5d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/fe799f5d

Branch: refs/heads/2.3
Commit: fe799f5d382fad7e35be634f660e73f62d6ec9e8
Parents: 731be2c
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 02:05:03 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 02:05:16 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/Configurable.java |   6 +-
 .../core/_ObjectBuilderSettingEvaluator.java    | 123 ++++++++++++++++---
 src/manual/en_US/book.xml                       |  18 ++-
 .../core/ObjectBuilderSettingsTest.java         |  43 +++++++
 4 files changed, 167 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fe799f5d/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index ba5d8c8..9c82428 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -1887,6 +1887,8 @@ public class Configurable {
      *            The keys and values can be any kind of expression, like even object builder expressions.
      *            The resulting Java object will be a {@link Map} that keeps the item order ({@link LinkedHashMap} as
      *            of this writing).
+     *        <li>A reference to a public static filed, like {@code Configuration.AUTO_DETECT_TAG_SYNTAX} or
+     *            {@code com.example.MyClass.MY_CONSTANT}.
      *        <li>An object builder expression. That is, object builder expressions can be nested into each other. 
      *      </ul>
      *   </li>
@@ -1901,13 +1903,13 @@ public class Configurable {
      *     can't be omitted for nested expressions.
      *   </li>
      *   <li>
-     *     <p>The following classes can be referred to with short class name instead of full qualified name:
+     *     <p>The following classes can be referred to with simple (unqualified) name instead of fully qualified name:
      *     {@link DefaultObjectWrapper}, {@link BeansWrapper}, {@link SimpleObjectWrapper}, {@link Locale},
      *     {@link TemplateConfiguration}, {@link PathGlobMatcher}, {@link FileNameGlobMatcher}, {@link PathRegexMatcher},
      *     {@link AndMatcher}, {@link OrMatcher}, {@link NotMatcher}, {@link ConditionalTemplateConfigurationFactory},
      *     {@link MergingTemplateConfigurationFactory}, {@link FirstMatchTemplateConfigurationFactory},
      *     {@link HTMLOutputFormat}, {@link XMLOutputFormat}, {@link RTFOutputFormat}, {@link PlainTextOutputFormat},
-     *     {@link UndefinedOutputFormat}.
+     *     {@link UndefinedOutputFormat}, {@link Configuration}.
      *   </li>
      *   <li>
      *     <p>{@link TimeZone} objects can be created like {@code TimeZone("UTC")}, despite that there's no a such

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fe799f5d/src/main/java/freemarker/core/_ObjectBuilderSettingEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_ObjectBuilderSettingEvaluator.java b/src/main/java/freemarker/core/_ObjectBuilderSettingEvaluator.java
index a1e1c22..afbb436 100644
--- a/src/main/java/freemarker/core/_ObjectBuilderSettingEvaluator.java
+++ b/src/main/java/freemarker/core/_ObjectBuilderSettingEvaluator.java
@@ -46,6 +46,7 @@ import freemarker.cache.OrMatcher;
 import freemarker.cache.PathGlobMatcher;
 import freemarker.cache.PathRegexMatcher;
 import freemarker.ext.beans.BeansWrapper;
+import freemarker.template.Configuration;
 import freemarker.template.DefaultObjectWrapper;
 import freemarker.template.SimpleObjectWrapper;
 import freemarker.template.TemplateHashModel;
@@ -75,7 +76,7 @@ public class _ObjectBuilderSettingEvaluator {
 
     private static final String BUILDER_CLASS_POSTFIX = "Builder";
 
-    private static Map/*<String,String>*/ SHORTHANDS;
+    private static Map<String,String> SHORTHANDS;
     
     private static final Object VOID = new Object();
 
@@ -165,9 +166,12 @@ public class _ObjectBuilderSettingEvaluator {
         int startPos = pos;
         
         BuilderCallExpression exp = new BuilderCallExpression();
+        // We need the canBeStaticField/mustBeStaticFiled complication to deal with legacy syntax where parentheses
+        // weren't required for constructor calls.
+        exp.canBeStaticField = true;
         
+        final String fetchedClassName = fetchClassName(optional);
         {
-            final String fetchedClassName = fetchClassName(optional);
             if (fetchedClassName == null) {
                 if (!optional) {
                     throw new _ObjectBuilderSettingEvaluationException("class name", src, pos);
@@ -178,6 +182,7 @@ public class _ObjectBuilderSettingEvaluator {
             if (!fetchedClassName.equals(exp.className)) {
                 // Before 2.3.21 only full-qualified class names were allowed
                 modernMode = true;
+                exp.canBeStaticField = false;
             }
         }
         
@@ -186,15 +191,17 @@ public class _ObjectBuilderSettingEvaluator {
         char openParen = fetchOptionalChar("(");
         // Only the top-level expression can omit the "(...)"
         if (openParen == 0 && !topLevel) {
-            if (!optional) {
-                throw new _ObjectBuilderSettingEvaluationException("(", src, pos);
+            if (fetchedClassName.indexOf('.') != -1) {
+                exp.mustBeStaticField = true;
+            } else {
+                pos = startPos;
+                return VOID;
             }
-            pos = startPos;
-            return VOID;
         }
     
         if (openParen != 0) {
             fetchParameterListInto(exp);
+            exp.canBeStaticField = false;
         }
         
         return exp;
@@ -683,8 +690,11 @@ public class _ObjectBuilderSettingEvaluator {
             
             addWithSimpleName(SHORTHANDS, Locale.class);
             SHORTHANDS.put("TimeZone", "freemarker.core._TimeZone");
+
+            // For accessing static fields:
+            addWithSimpleName(SHORTHANDS, Configuration.class);
         }
-        String fullClassName = (String) SHORTHANDS.get(className);
+        String fullClassName = SHORTHANDS.get(className);
         return fullClassName == null ? className : fullClassName;
     }
     
@@ -842,20 +852,41 @@ public class _ObjectBuilderSettingEvaluator {
     
     private class BuilderCallExpression extends ExpressionWithParameters {
         private String className;
+        private boolean canBeStaticField;
+        private boolean mustBeStaticField;
         
         @Override
         Object eval() throws _ObjectBuilderSettingEvaluationException {
+            if (mustBeStaticField) {
+                if (!canBeStaticField) {
+                    throw new BugException();
+                }
+                return getStaticFieldValue(className);
+            }
+            
             Class cl;
             
             if (!modernMode) {
                 try {
-                    return ClassUtil.forName(className).newInstance();
-                } catch (InstantiationException e) {
-                    throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
-                } catch (IllegalAccessException e) {
-                    throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
-                } catch (ClassNotFoundException e) {
-                    throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
+                    try {
+                        return ClassUtil.forName(className).newInstance();
+                    } catch (InstantiationException e) {
+                        throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
+                    } catch (IllegalAccessException e) {
+                        throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
+                    } catch (ClassNotFoundException e) {
+                        throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
+                    }
+                } catch (LegacyExceptionWrapperSettingEvaluationExpression e) {
+                    if (!canBeStaticField) {
+                        throw e;
+                    }
+                    // Silently try to interpret className as static filed, throw the original exception if that fails. 
+                    try {
+                        return getStaticFieldValue(className);
+                    } catch (_ObjectBuilderSettingEvaluationException e2) {
+                        throw e;
+                    }
                 }
             }
 
@@ -868,8 +899,23 @@ public class _ObjectBuilderSettingEvaluator {
                 try {
                     cl = ClassUtil.forName(className);
                 } catch (Exception e2) {
+                    boolean failedToGetAsStaticField;
+                    if (canBeStaticField) {
+                        // Try to interpret className as static filed: 
+                        try {
+                            return getStaticFieldValue(className);
+                        } catch (_ObjectBuilderSettingEvaluationException e3) {
+                            // Suppress it
+                            failedToGetAsStaticField = true;
+                        }
+                    } else {
+                        failedToGetAsStaticField = false;
+                    }
                     throw new _ObjectBuilderSettingEvaluationException(
-                            "Failed to get class " + StringUtil.jQuote(className) + ".", e2);
+                            "Failed to get class " + StringUtil.jQuote(className)
+                            + (failedToGetAsStaticField ? " (also failed to resolve name as static field)" : "")
+                            + ".",
+                            e2);
                 }
             }
             
@@ -908,6 +954,53 @@ public class _ObjectBuilderSettingEvaluator {
             return result;
         }
         
+        private Object getStaticFieldValue(String dottedName) throws _ObjectBuilderSettingEvaluationException {
+            int lastDotIdx = dottedName.lastIndexOf('.');
+            if (lastDotIdx == -1) {
+                throw new IllegalArgumentException();
+            }
+            String className = shorthandToFullQualified(dottedName.substring(0, lastDotIdx));
+            String fieldName = dottedName.substring(lastDotIdx + 1);
+
+            Class<?> cl;
+            try {
+                cl = ClassUtil.forName(className);
+            } catch (Exception e) {
+                throw new _ObjectBuilderSettingEvaluationException(
+                        "Failed to get field's parent class, " + StringUtil.jQuote(className) + ".",
+                        e);
+            }
+            
+            Field field;
+            try {
+                field = cl.getField(fieldName);
+            } catch (Exception e) {
+                throw new _ObjectBuilderSettingEvaluationException(
+                        "Failed to get field " + StringUtil.jQuote(fieldName) + " from class "
+                        + StringUtil.jQuote(className) + ".",
+                        e);
+            }
+            
+            if ((field.getModifiers() & Modifier.STATIC) == 0) {
+                throw new _ObjectBuilderSettingEvaluationException("Referred field isn't static: " + field);
+            }
+            if ((field.getModifiers() & Modifier.PUBLIC) == 0) {
+                throw new _ObjectBuilderSettingEvaluationException("Referred field isn't public: " + field);
+            }
+
+            if (field.getName().equals(INSTANCE_FIELD_NAME)) {
+                throw new _ObjectBuilderSettingEvaluationException(
+                        "The " + INSTANCE_FIELD_NAME + " field is only accessible through pseudo-constructor call: "
+                        + className + "()");
+            }
+            
+            try {
+                return field.get(null);
+            } catch (Exception e) {
+                throw new _ObjectBuilderSettingEvaluationException("Failed to get field value: " + field, e);
+            }
+        }
+
         private Object callConstructor(Class cl)
                 throws _ObjectBuilderSettingEvaluationException {
             if (hasNoParameters()) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fe799f5d/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index c561322..ce8137e 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26131,12 +26131,12 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
             <listitem>
               <para>Fixes and improvements in the <quote>object
-              builder</quote> syntax used for configuring FreeMarker from
-              <literal>java.util.Properties</literal> (or other string-only
-              sources). This is not to be confused with the template language
-              syntax, which has nothing to do with the <quote>object
-              builder</quote> syntax we are writing about here. The
-              improvements are:</para>
+              builder</quote> mini-language used for configuring FreeMarker
+              from <literal>java.util.Properties</literal> or other
+              string-only sources (not used in templates). This is not to be
+              confused with the template language syntax, which has nothing to
+              do with the <quote>object builder</quote> syntax we are writing
+              about here. The improvements are:</para>
 
               <itemizedlist>
                 <listitem>
@@ -26196,6 +26196,12 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <literal>BigDecimal</literal> and <literal>bi</literal> for
                   <literal>BigInteger</literal>.</para>
                 </listitem>
+
+                <listitem>
+                  <para>Public static fields can be referred, like
+                  <literal>com.example.MyClass.MY_CONSTANT</literal> or
+                  <literal>Configuration.AUTO_DETECT_TAG_SYNTAX</literal>.</para>
+                </listitem>
               </itemizedlist>
             </listitem>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fe799f5d/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java b/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
index b708314..4276c7a 100644
--- a/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
+++ b/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
@@ -913,6 +913,46 @@ public class ObjectBuilderSettingsTest {
                 "{ -1: -11, -0.5: -0.55, -0.1bd: -0.11bd }");
     }
     
+    @Test
+    public void testStaticFields() throws Exception {
+        {
+            TestBean1 res = (TestBean1) _ObjectBuilderSettingEvaluator.eval(
+                    "freemarker.core.ObjectBuilderSettingsTest$TestBean1("
+                    + "freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST, true)",
+                    Object.class, false, _SettingEvaluationEnvironment.getCurrent());
+            assertEquals(TestStaticFields.CONST, (int) res.i);
+        }
+        {
+            TestBean1 res = (TestBean1) _ObjectBuilderSettingEvaluator.eval(
+                    "freemarker.core.ObjectBuilderSettingsTest$TestBean1("
+                    + "p2 = freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST)",
+                    Object.class, false, _SettingEvaluationEnvironment.getCurrent());
+            assertEquals(TestStaticFields.CONST, res.getP2());
+        }
+        assertEqualsEvaled(123, "freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST");
+        
+        // With shorthand class name:
+        assertEqualsEvaled(Configuration.AUTO_DETECT_TAG_SYNTAX, "Configuration.AUTO_DETECT_TAG_SYNTAX");
+        
+        try {
+            _ObjectBuilderSettingEvaluator.eval(
+                    "freemarker.core.ObjectBuilderSettingsTest$TestBean1("
+                    + "p2 = freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST())",
+                    Object.class, false, _SettingEvaluationEnvironment.getCurrent());
+            fail();
+        } catch (_ObjectBuilderSettingEvaluationException e) {
+            assertThat(e.getMessage(),
+                    containsString("freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST"));
+        }
+        try {
+            assertEqualsEvaled(123, "freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST()");
+            fail();
+        } catch (_ObjectBuilderSettingEvaluationException e) {
+            assertThat(e.getMessage(),
+                    containsString("freemarker.core.ObjectBuilderSettingsTest$TestStaticFields.CONST"));
+        }
+    }
+    
     private void assertEqualsEvaled(Object expectedValue, String s)
             throws _ObjectBuilderSettingEvaluationException, ClassNotFoundException, InstantiationException,
             IllegalAccessException {
@@ -1352,6 +1392,9 @@ public class ObjectBuilderSettingsTest {
         
     }
     
+    public static class TestStaticFields {
+        public static final int CONST = 123;
+    }
     
     public static class DummyArithmeticEngine extends ArithmeticEngine {
         


[29/35] incubator-freemarker git commit: Manual: Adding cfg.setLogTemplateExceptions(false) to more places.

Posted by dd...@apache.org.
Manual: Adding cfg.setLogTemplateExceptions(false) to more places.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/56b5f6e3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/56b5f6e3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/56b5f6e3

Branch: refs/heads/2.3
Commit: 56b5f6e3f7836464bf35f7d145c762fe46c64f45
Parents: 7292716
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 29 11:57:25 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 29 11:57:25 2015 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/56b5f6e3/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 9c888d2..092d18b 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -6218,7 +6218,10 @@ cfg.setDefaultEncoding("UTF-8");
 
 // Sets how errors will appear.
 // During web page *development* TemplateExceptionHandler.HTML_DEBUG_HANDLER is better.
-cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);</programlisting>
+cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+
+// Don't log exceptions inside FreeMarker that it will thrown at you anyway:
+cfg.setLogTemplateExceptions(false);</programlisting>
 
         <para>From now you should use this <emphasis>single</emphasis>
         configuration instance (i.e., its a singleton). Note however that if a
@@ -6478,6 +6481,7 @@ public class Test {
         cfg.setDirectoryForTemplateLoading(new File("<replaceable>/where/you/store/templates</replaceable>"));
         cfg.setDefaultEncoding("UTF-8");
         cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW);
+        cfg.setLogTemplateExceptions(false);
 
         /* ------------------------------------------------------------------------ */    
         /* You usually do these for MULTIPLE TIMES in the application life-cycle:   */    
@@ -8708,6 +8712,22 @@ 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


[27/35] incubator-freemarker git commit: (Cleaned up and extended XML prefix outputting test a bit.)

Posted by dd...@apache.org.
(Cleaned up and extended XML prefix outputting test a bit.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/f20271e5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/f20271e5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/f20271e5

Branch: refs/heads/2.3
Commit: f20271e535792636988955d8591964cc812f91d0
Parents: 95859c3
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 22:44:08 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 22:44:08 2015 +0100

----------------------------------------------------------------------
 src/test/java/freemarker/ext/dom/DOMTest.java | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f20271e5/src/test/java/freemarker/ext/dom/DOMTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/dom/DOMTest.java b/src/test/java/freemarker/ext/dom/DOMTest.java
index 4a96a83..8079d90 100644
--- a/src/test/java/freemarker/ext/dom/DOMTest.java
+++ b/src/test/java/freemarker/ext/dom/DOMTest.java
@@ -66,11 +66,17 @@ public class DOMTest extends TemplateTest {
                 "<root xmlns=\"http://example.com/ns1\" xmlns:a=\"http://example.com/ns2\">"
                 + "<a>A</a><a:b>B</a:b><c a1=\"1\" a:a2=\"2\" /></root>");
         
-        // 
+        // When there's no matching prefix declared via the #ftl header, return null for qname:
         assertOutput("${doc?children[0].@@qname!'null'}", "null");
         assertOutput("${doc?children[0]?children[1].@@qname!'null'}", "null");
+        assertOutput("${doc?children[0]?children[2]['@*'][1].@@qname!'null'}", "null");
+        
+        // When we have prefix declared in the #ftl header:
         assertOutput(ftlHeader + "${doc?children[0].@@qname}", "root");
         assertOutput(ftlHeader + "${doc?children[0]?children[1].@@qname}", "n2:b");
+        assertOutput(ftlHeader + "${doc?children[0]?children[2].@@qname}", "c");
+        assertOutput(ftlHeader + "${doc?children[0]?children[2]['@*'][0].@@qname}", "a1");
+        assertOutput(ftlHeader + "${doc?children[0]?children[2]['@*'][1].@@qname}", "n2:a2");
         // Unfortunately these include the xmlns attributes, but that would be non-BC to fix now:
         assertThat(getOutput(ftlHeader + "${doc?children[0].@@start_tag}"), startsWith("<root"));
         assertThat(getOutput(ftlHeader + "${doc?children[0]?children[1].@@start_tag}"), startsWith("<n2:b"));


[13/35] incubator-freemarker git commit: RTFOutputFormat uses application/rtf instead of text/rtf

Posted by dd...@apache.org.
RTFOutputFormat uses application/rtf instead of text/rtf


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/d9f6b444
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/d9f6b444
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/d9f6b444

Branch: refs/heads/2.3
Commit: d9f6b4444c1bf8d910b5ff54f7b8b5cb07606abf
Parents: 62f03d8
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 22 11:32:16 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 22 11:32:16 2015 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/RTFOutputFormat.java     | 2 +-
 src/manual/en_US/book.xml                              | 7 ++++++-
 src/test/java/freemarker/core/RTFOutputFormatTest.java | 2 +-
 3 files changed, 8 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d9f6b444/src/main/java/freemarker/core/RTFOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/RTFOutputFormat.java b/src/main/java/freemarker/core/RTFOutputFormat.java
index 2d613e0..86eb103 100644
--- a/src/main/java/freemarker/core/RTFOutputFormat.java
+++ b/src/main/java/freemarker/core/RTFOutputFormat.java
@@ -47,7 +47,7 @@ public final class RTFOutputFormat extends CommonMarkupOutputFormat<TemplateRTFO
 
     @Override
     public String getMimeType() {
-        return "text/rtf";
+        return "application/rtf";
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d9f6b444/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 18d3f9e..4f6340a 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -5360,7 +5360,7 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
                 <literal>\</literal> as <literal>\{</literal>,
                 <literal>\}</literal>, <literal>\\</literal></td>
 
-                <td><literal>text/rtf</literal></td>
+                <td><literal>application/rtf</literal></td>
 
                 <td><literal>RTFOutputFormat.INSTANCE</literal></td>
               </tr>
@@ -26477,6 +26477,11 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para><literal>RTFOutputFormat</literal> now uses
+              application/rtf MIME type instead of text/rtf</para>
+            </listitem>
+
+            <listitem>
               <para>Added new built-in: <literal>is_markup_output</literal>,
               returns <literal>true</literal> if the value is of type
               <quote>markup output</quote>.</para>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d9f6b444/src/test/java/freemarker/core/RTFOutputFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/RTFOutputFormatTest.java b/src/test/java/freemarker/core/RTFOutputFormatTest.java
index 21e1be5..96d01d0 100644
--- a/src/test/java/freemarker/core/RTFOutputFormatTest.java
+++ b/src/test/java/freemarker/core/RTFOutputFormatTest.java
@@ -123,7 +123,7 @@ public class RTFOutputFormatTest {
     
     @Test
     public void testGetMimeType() {
-        assertEquals("text/rtf", INSTANCE.getMimeType());
+        assertEquals("application/rtf", INSTANCE.getMimeType());
     }
     
 }


[20/35] incubator-freemarker git commit: The parser used by ?interpet and ?eval inherits not only the output_format of its surrounding lexical context, but also the auto-escaping policy of it (basically, if auto-escapig is on or off). Also documented how

Posted by dd...@apache.org.
The parser used by ?interpet and ?eval inherits not only the output_format of its surrounding lexical context, but also the auto-escaping policy of it (basically, if auto-escapig is on or off). Also documented how these built-ins inherit the configuration settings.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/90fcfb9d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/90fcfb9d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/90fcfb9d

Branch: refs/heads/2.3
Commit: 90fcfb9d7a6b859894ca27886ef7bd43c29cb8a8
Parents: d3654bc
Author: ddekany <dd...@apache.org>
Authored: Sun Dec 27 15:54:31 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 27 15:54:31 2015 +0100

----------------------------------------------------------------------
 .../freemarker/core/BuiltInsForStringsMisc.java |  3 +-
 src/main/java/freemarker/core/Interpret.java    |  3 +-
 .../core/OutputFormatBoundBuiltIn.java          |  4 +-
 ..._ParserConfigurationWithInheritedFormat.java | 10 ++--
 src/main/javacc/FTL.jj                          |  2 +-
 src/manual/en_US/book.xml                       | 49 ++++++++++++++------
 .../java/freemarker/core/OutputFormatTest.java  | 22 +++++++++
 7 files changed, 69 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltInsForStringsMisc.java b/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
index 8b83c2c..3d21c0a 100644
--- a/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
+++ b/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
@@ -72,7 +72,8 @@ class BuiltInsForStringsMisc {
                     ParserConfiguration pCfg = parentTemplate.getParserConfiguration();
                     // pCfg.outputFormat is exceptional: it's inherited from the lexical context
                     if (pCfg.getOutputFormat() != outputFormat) {
-                        pCfg = new _ParserConfigurationWithInheritedFormat(pCfg, outputFormat, null);
+                        pCfg = new _ParserConfigurationWithInheritedFormat(
+                                pCfg, outputFormat, Integer.valueOf(autoEscapingPolicy));
                     }
                     
                     FMParser parser = new FMParser(

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/main/java/freemarker/core/Interpret.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Interpret.java b/src/main/java/freemarker/core/Interpret.java
index 0b947ef..01d2a80 100644
--- a/src/main/java/freemarker/core/Interpret.java
+++ b/src/main/java/freemarker/core/Interpret.java
@@ -86,7 +86,8 @@ class Interpret extends OutputFormatBoundBuiltIn {
             ParserConfiguration pCfg = parentTemplate.getParserConfiguration();
             // pCfg.outputFormat is exceptional: it's inherited from the lexical context
             if (pCfg.getOutputFormat() != outputFormat) {
-                pCfg = new _ParserConfigurationWithInheritedFormat(pCfg, outputFormat, null);
+                pCfg = new _ParserConfigurationWithInheritedFormat(
+                        pCfg, outputFormat, Integer.valueOf(autoEscapingPolicy));
             }
             interpretedTemplate = new Template(
                     (parentTemplate.getName() != null ? parentTemplate.getName() : "nameless_template") + "->" + id,

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/main/java/freemarker/core/OutputFormatBoundBuiltIn.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/OutputFormatBoundBuiltIn.java b/src/main/java/freemarker/core/OutputFormatBoundBuiltIn.java
index b32617b..2bcc106 100644
--- a/src/main/java/freemarker/core/OutputFormatBoundBuiltIn.java
+++ b/src/main/java/freemarker/core/OutputFormatBoundBuiltIn.java
@@ -25,10 +25,12 @@ import freemarker.template.utility.NullArgumentException;
 abstract class OutputFormatBoundBuiltIn extends SpecialBuiltIn {
     
     protected OutputFormat outputFormat;
+    protected int autoEscapingPolicy;
     
-    void bindToOutputFormat(OutputFormat outputFormat) {
+    void bindToOutputFormat(OutputFormat outputFormat, int autoEscapingPolicy) {
         NullArgumentException.check(outputFormat);
         this.outputFormat = outputFormat;
+        this.autoEscapingPolicy = autoEscapingPolicy;
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/main/java/freemarker/core/_ParserConfigurationWithInheritedFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/_ParserConfigurationWithInheritedFormat.java b/src/main/java/freemarker/core/_ParserConfigurationWithInheritedFormat.java
index ba21345..c479f45 100644
--- a/src/main/java/freemarker/core/_ParserConfigurationWithInheritedFormat.java
+++ b/src/main/java/freemarker/core/_ParserConfigurationWithInheritedFormat.java
@@ -22,19 +22,17 @@ import freemarker.template.Version;
 
 /**
  * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
- * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
- * access things inside this package that users shouldn't. 
  */ 
 public final class _ParserConfigurationWithInheritedFormat implements ParserConfiguration {
 
     private final OutputFormat outputFormat;
-    private final Integer autoEscaping;
+    private final Integer autoEscapingPolicy;
     private final ParserConfiguration wrappedPCfg;
 
     public _ParserConfigurationWithInheritedFormat(ParserConfiguration wrappedPCfg, OutputFormat outputFormat,
-            Integer autoEscaping) {
+            Integer autoEscapingPolicy) {
         this.outputFormat = outputFormat;
-        this.autoEscaping = autoEscaping;
+        this.autoEscapingPolicy = autoEscapingPolicy;
         this.wrappedPCfg = wrappedPCfg;
     }
 
@@ -67,7 +65,7 @@ public final class _ParserConfigurationWithInheritedFormat implements ParserConf
     }
 
     public int getAutoEscapingPolicy() {
-        return autoEscaping != null ? autoEscaping.intValue() : wrappedPCfg.getAutoEscapingPolicy();
+        return autoEscapingPolicy != null ? autoEscapingPolicy.intValue() : wrappedPCfg.getAutoEscapingPolicy();
     }
 
     public ArithmeticEngine getArithmeticEngine() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index ad81e08..9c858e8 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -2128,7 +2128,7 @@ Expression BuiltIn(Expression lhoExp) :
         }
 
         if (result instanceof OutputFormatBoundBuiltIn) {
-            ((OutputFormatBoundBuiltIn) result).bindToOutputFormat(outputFormat);
+            ((OutputFormatBoundBuiltIn) result).bindToOutputFormat(outputFormat, autoEscapingPolicy);
             
             return result;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 555c8e4..2745adb 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -17570,10 +17570,10 @@ Sorted by name.last:
           built-ins</link> that refer to a loop variable that was created
           outside <literal><replaceable>s</replaceable></literal>.</para>
 
-          <para>The configuration settings that affect the expression parsing
-          (like syntax) are coming from the <literal>Configuration</literal>
-          object, not from template that invokes
-          <literal>eval</literal>.</para>
+          <para>Regarding the configuration settings that affect the parsing
+          (like syntax) and evaluation the rules are the same as with the
+          <link linkend="ref_builtin_interpret"><literal>interpret</literal>
+          built-in</link>.</para>
         </section>
 
         <section xml:id="ref_builtin_has_content">
@@ -17637,16 +17637,6 @@ Sorted by name.last:
           user-defined directive that, when executed, runs the template whose
           content is the value of <literal>templateSource</literal>.</para>
 
-          <para>The configuration settings that affect the parsing (like tag
-          syntax and naming convention) are coming from the
-          <literal>Configuration</literal> object, not from template that
-          calls <literal>interpret</literal>. This also means that the
-          previously auto-detected tag syntax or auto-detected naming
-          convention doesn't effect the parsing of the interpreted template.
-          This is consistent with how the <link
-          linkend="ref_directive_include"><literal>include</literal>
-          directive</link> works.</para>
-
           <para>The name of the template created by
           <literal>interpret</literal> is the name of the template that calls
           <literal>interpret</literal>, plus
@@ -17673,6 +17663,29 @@ Sorted by name.last:
           a sequence of two items, in which case the first item is the FTL
           string to interpret, and the second items is the template name used
           after the <literal>"-&gt;"</literal>.</para>
+
+          <para>The configuration settings that affect the interpreted
+          template are the same as of the surrounding template, except that
+          parser settings specified in the <link
+          linkend="ref.directive.ftl"><literal>ftl</literal> directive</link>
+          or was established via tag syntax or naming convention
+          auto-detection are instead coming from the
+          <literal>Configuration</literal> object (or naturally, from the
+          <link
+          linkend="pgui_config_templateconfigurations"><literal>TemplateConfiguration</literal></link>,
+          if there's any). Thus the tag syntax, naming convention, whitespace
+          handling, etc. of the interpreted template is independent of that
+          established <emphasis>inside</emphasis> the surrounding template. An
+          important exception from this rule is that the <link
+          linkend="dgui_misc_autoescaping_outputformat">output format</link>
+          and auto-escaping policy is inherited from the lexical context where
+          <literal>interpret</literal> is called from. For example in a
+          template that has <literal>&lt;#ftl
+          output_format="XML"&gt;</literal> header (or if you are inside a
+          <literal>&lt;#output_format
+          "XML"&gt;<replaceable>...</replaceable>&lt;/#output_format&gt;</literal>
+          block), <literal>interpret</literal> calls in it will produce
+          directives with XML output format.</para>
         </section>
 
         <section xml:id="ref_builtin_isType">
@@ -27219,6 +27232,14 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 </listitem>
               </itemizedlist>
             </listitem>
+
+            <listitem>
+              <para>The parser used by <literal>?interpet</literal> and
+              <literal>?eval</literal> inherits not only the
+              <literal>output_format</literal> of its surrounding lexical
+              context, but also the auto-escaping policy of it (basically, if
+              auto-escapig is on or off).</para>
+            </listitem>
           </itemizedlist>
         </section>
       </section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/90fcfb9d/src/test/java/freemarker/core/OutputFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/OutputFormatTest.java b/src/test/java/freemarker/core/OutputFormatTest.java
index cc31920..dc5e7d4 100644
--- a/src/test/java/freemarker/core/OutputFormatTest.java
+++ b/src/test/java/freemarker/core/OutputFormatTest.java
@@ -868,10 +868,32 @@ public class OutputFormatTest extends TemplateTest {
                 + "<#outputFormat 'XML'>" + commonFTL + "</#outputFormat>",
                 "Eval: RTF; Interpret: RTF \\{&\\}\n"
                 + "Eval: XML; Interpret: XML {&amp;}");
+        
+        // parser.autoEscapingPolicy is inherited too:
+        assertOutput(
+                "<#ftl autoEsc=false outputFormat='XML'>"
+                + commonFTL + " ${'.autoEsc'?eval?c}",
+                "Eval: XML; Interpret: XML {&} false");
+        assertOutput(
+                "<#ftl outputFormat='XML'>"
+                + "<#noAutoEsc>" + commonFTL + " ${'.autoEsc'?eval?c}</#noAutoEsc>",
+                "Eval: XML; Interpret: XML {&} false");
         assertOutput(
                 "<#ftl autoEsc=false outputFormat='XML'>"
                 + "<#noAutoEsc>" + commonFTL + " ${'.autoEsc'?eval?c}</#noAutoEsc>",
+                "Eval: XML; Interpret: XML {&} false");
+        assertOutput(
+                "<#ftl autoEsc=false outputFormat='XML'>"
+                + "<#autoEsc>" + commonFTL + " ${'.autoEsc'?eval?c}</#autoEsc>",
                 "Eval: XML; Interpret: XML {&amp;} true");
+        assertOutput(
+                "${.outputFormat}<#assign ftl='<#ftl outputFormat=\\'RTF\\'>$\\{.outputFormat}'> <@ftl?interpret/>",
+                "undefined RTF");
+        assertOutput(
+                "${.outputFormat}<#outputFormat 'RTF'>"
+                + "<#assign ftl='$\\{.outputFormat}'> <@ftl?interpret/> ${'.outputFormat'?eval}"
+                + "</#outputFormat>",
+                "undefined RTF RTF");
     }
 
     @Test


[04/35] incubator-freemarker git commit: Made place for the Chinese manual.

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/731be2c2/src/manual/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/book.xml b/src/manual/book.xml
deleted file mode 100644
index c561322..0000000
--- a/src/manual/book.xml
+++ /dev/null
@@ -1,37479 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<book conformance="docgen" version="5.0" xml:lang="en"
-      xmlns="http://docbook.org/ns/docbook"
-      xmlns:xlink="http://www.w3.org/1999/xlink"
-      xmlns:ns5="http://www.w3.org/1999/xhtml"
-      xmlns:ns4="http://www.w3.org/2000/svg"
-      xmlns:ns3="http://www.w3.org/1998/Math/MathML"
-      xmlns:ns="http://docbook.org/ns/docbook">
-  <info>
-    <title>FreeMarker Manual</title>
-
-    <titleabbrev>Manual</titleabbrev>
-
-    <productname>Freemarker 2.3.24 Preview 1</productname>
-  </info>
-
-  <preface role="index.html" xml:id="preface">
-    <title>What is FreeMarker?</title>
-
-    <para>FreeMarker is a <emphasis>template engine</emphasis>: a generic tool
-    to generate text output (HTML web pages, e-mails, configuration files,
-    source code, etc.) based on templates and changing data. It's not an
-    application for end-users in itself, but a Java library, a component that
-    programmers can embed into their products.</para>
-
-    <para>Templates are written in the FreeMarker Template Language (FTL).
-    It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
-    programming language like PHP. You meant to prepare the data to display in
-    a real programming language, like issue database queries and do business
-    calculations, and then the template displays that already prepared data.
-    In the template you are focusing on how to present the data, and outside
-    the template you are focusing on what data to present.</para>
-
-    <mediaobject>
-      <imageobject>
-        <imagedata fileref="figures/overview.png"/>
-      </imageobject>
-    </mediaobject>
-
-    <para>This approach is often referred to as the <link
-    linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
-    particularly popular for dynamic Web pages. It helps in separating the Web
-    page designers (HTML authors) from the developers (Java programmers
-    usually). Designers won't face complicated logic in templates, and can
-    change the appearance of a page without programmers having to change or
-    recompile code.</para>
-
-    <para>While FreeMarker was originally created for generating HTML pages in
-    MVC web application frameworks, it isn't bound to servlets or HTML or
-    anything Web-related. It's used in non-web application environments as
-    well.</para>
-
-    <para>FreeMarker is <link
-    xlink:href="http://www.fsf.org/philosophy/free-sw.html">Free</link>,
-    released under the Apache License, Version 2.0.</para>
-  </preface>
-
-  <part xml:id="dgui">
-    <title>Template Author's Guide</title>
-
-    <chapter xml:id="dgui_quickstart">
-      <title>Getting Started</title>
-
-      <para>This chapter is a very rough introduction to FreeMarker. The
-      chapters after this will go over things in much greater detail.
-      Nonetheless, once you have read this chapter, you will be able to write
-      simple but useful FreeMarker templates.</para>
-
-      <section xml:id="dgui_quickstart_basics">
-        <title>Template + data-model = output</title>
-
-        <para>Let's assume that you need a HTML page in a Web shop, similar to
-        this:</para>
-
-        <programlisting role="output">&lt;html&gt;
-&lt;head&gt;
-  &lt;title&gt;Welcome!&lt;/title&gt;
-&lt;/head&gt;
-&lt;body&gt;
-  &lt;h1&gt;Welcome <emphasis>John Doe</emphasis>!&lt;/h1&gt;
-  &lt;p&gt;Our latest product:
-  &lt;a href="<emphasis>products/greenmouse.html</emphasis>"&gt;<emphasis>green mouse</emphasis>&lt;/a&gt;!
-&lt;/body&gt;
-&lt;/html&gt;</programlisting>
-
-        <para>But the user name ("John Doe" above) should depend on who the
-        logged in Web page visitor is, and the latest product should come from
-        a database and thus it potentially changes too. Thus you can't enter
-        these into the HTML directly, you can't use static HTML. Instead, you
-        can use a <emphasis role="term">template</emphasis> of the desired
-        output. The template is the same as the static HTML would be, except
-        that it contains some instructions to FreeMarker that makes it
-        dynamic:</para>
-
-        <programlisting role="template" xml:id="example.first">&lt;html&gt;
-&lt;head&gt;
-  &lt;title&gt;Welcome!&lt;/title&gt;
-&lt;/head&gt;
-&lt;body&gt;
-  &lt;h1&gt;Welcome <emphasis>${user}</emphasis>!&lt;/h1&gt;
-  &lt;p&gt;Our latest product:
-  &lt;a href="<emphasis>${latestProduct.url}</emphasis>"&gt;<emphasis>${latestProduct.name}</emphasis>&lt;/a&gt;!
-&lt;/body&gt;
-&lt;/html&gt;</programlisting>
-
-        <para>The template is stored on the Web server, usually just like the
-        static HTML page would be. But whenever someone visits this page,
-        FreeMarker will step in and transform the template on-the-fly to plain
-        HTML by replacing the
-        <literal>${<replaceable>...</replaceable>}</literal>-s with up-to-date
-        content, and send the result to the visitor's Web browser. So the
-        visitor's Web browser will receive something like the first example
-        HTML (i.e., plain HTML without FreeMarker instructions), and it will
-        not perceive that FreeMarker is used on the server. (Of course, the
-        template file stored on the Web server is not changed by this; the
-        substitutions only appear in the Web server's response.)</para>
-
-        <para>Note that the template doesn't contain the programming logic to
-        find out who the current visitor is, or to query the database to get
-        the latest product. The data to be displayed is prepared outside
-        FreeMarker, usually by parts written in some <quote>real</quote>
-        programming language like Java. The template author needn't know how
-        these values were calculated. In fact, the way these values are
-        calculated can be completely changed while the templates can remain
-        exactly the same, and also, the look of the page can be completely
-        changed without touching anything but the template. This separation of
-        presentation logic and business logic can be especially useful when
-        the template authors (designers) and the programmers are different
-        individuals, but also helps managing application complexity if they
-        are the same person. Keeping templates focused on presentation issues
-        (visual design, layout and formatting) is a key for using template
-        engines like FreeMarker efficiently.</para>
-
-        <para><indexterm>
-            <primary>data-model</primary>
-          </indexterm>The totality of data that was prepared for the template
-        is called the <emphasis role="term">data-model</emphasis>. As far as
-        the template author is concerned, the data-model is a tree-like
-        structure (like folders and files on your hard disk), which, in this
-        case, could be visualized as:</para>
-
-        <programlisting role="dataModel">(root)
-  |
-  +- <emphasis>user</emphasis> = "Big Joe"
-  |
-  +- <emphasis>latestProduct</emphasis>
-      |
-      +- <emphasis>url</emphasis> = "products/greenmouse.html"
-      |
-      +- <emphasis>name</emphasis> = "green mouse"</programlisting>
-
-        <note>
-          <para>The above is just a visualization; the data-model is not in a
-          textual format, it's from Java objects. For the Java programmers,
-          the root is perhaps a Java object with <literal>getUser()</literal>
-          and <literal>getLatestProduct()</literal> methods, or maybe a Java
-          <literal>Map</literal> with <literal>"user"</literal> and
-          <literal>"latestProducts"</literal> keys. Similarly,
-          <literal>latestProduct</literal> is perhaps a Java Object with
-          <literal>getUrl()</literal> and <literal>getName()</literal>
-          methods.</para>
-        </note>
-
-        <para>Earlier, you have picked values from this data-model, with the
-        <literal>user</literal> and <literal>latestProduct.name</literal>
-        expressions. If we go on with the analogy that the data model is like
-        a file system, then <quote>(root)</quote> and
-        <literal>latestProduct</literal> correspond to directories (folders),
-        and <literal>user</literal>, <literal>url</literal> and
-        <literal>name</literal> are files in those directories.</para>
-
-        <para>To recapitulate, a template and a data-model is needed for
-        FreeMarker to generate the output (like the HTML shown first):</para>
-
-        <para><phrase role="markedTemplate">Template</phrase> + <phrase
-        role="markedDataModel">data-model</phrase> = <phrase
-        role="markedOutput">output</phrase></para>
-      </section>
-
-      <section xml:id="dgui_quickstart_datamodel">
-        <title>The data-model at a glance</title>
-
-        <para>As you have seen, the data-model is basically a tree. This tree
-        can be arbitrarily complicated and deep, for example:</para>
-
-        <programlisting role="dataModel"
-                        xml:id="example.qStart.dataModelWithHashes">(root)
-  |
-  +- animals
-  |   |
-  |   +- mouse
-  |   |   |   
-  |   |   +- size = "small"
-  |   |   |   
-  |   |   +- price = 50
-  |   |
-  |   +- elephant
-  |   |   |   
-  |   |   +- size = "large"
-  |   |   |   
-  |   |   +- price = 5000
-  |   |
-  |   +- python
-  |       |   
-  |       +- size = "medium"
-  |       |   
-  |       +- price = 4999
-  |
-  +- message = "It is a test"
-  |
-  +- misc
-      |
-      +- foo = "Something"</programlisting>
-
-        <para>The variables that act like directories (the root,
-        <literal>animals</literal>, <literal>mouse</literal>,
-        <literal>elephant</literal>, <literal>python</literal>,
-        <literal>misc</literal>) are called <emphasis
-        role="term">hashes</emphasis>. Hashes store other variables (the so
-        called <anchor xml:id="topic.dataModel.subVar"/><emphasis>sub
-        variables</emphasis>) by a lookup name (e.g., <quote>animals</quote>,
-        <quote>mouse</quote> or <quote>price</quote>).</para>
-
-        <para>The variables that store a single value
-        (<literal>size</literal>, <literal>price</literal>,
-        <literal>message</literal> and <literal>foo</literal>) are called
-        <emphasis role="term">scalars</emphasis>.</para>
-
-        <para><anchor xml:id="topic.qStart.accessVariables"/>When you want to
-        use a subvariable in a template, you specify its path from the root,
-        and separate the steps with dots. To access the
-        <literal>price</literal> of a <literal>mouse</literal>, you start from
-        the root and go into <literal>animals</literal>, and then go into
-        <literal>mouse</literal> then go into <literal>price</literal>. So you
-        write <literal>animals.mouse.price</literal>.</para>
-
-        <para>Another important kind of variables are <emphasis
-        role="term">sequences</emphasis>. They store subvariables like hashes,
-        but here subvariables doesn't have a name, they are just items in a
-        list. For example, in this data-model, <literal>animals</literal> and
-        <literal>misc.fruits</literal> are sequences:</para>
-
-        <programlisting role="dataModel"
-                        xml:id="example.qStart.dataModelWithSequences">(root)
-  |
-  +- animals
-  |   |
-  |   +- (1st)
-  |   |   |
-  |   |   +- name = "mouse"
-  |   |   |
-  |   |   +- size = "small"
-  |   |   |
-  |   |   +- price = 50
-  |   |
-  |   +- (2nd)
-  |   |   |
-  |   |   +- name = "elephant"
-  |   |   |
-  |   |   +- size = "large"
-  |   |   |
-  |   |   +- price = 5000
-  |   |
-  |   +- (3rd)
-  |       |
-  |       +- name = "python"
-  |       |
-  |       +- size = "medium"
-  |       |
-  |       +- price = 4999
-  |
-  +- misc
-      |
-      +- fruits
-          |
-          +- (1st) = "orange"
-          |
-          +- (2nd) = "banana"</programlisting>
-
-        <para>To access a subvariable of a sequence you use a numerical index
-        in square brackets. Indexes start from 0 (it's a programmer tradition
-        to start with 0), thus the index of the 1st item is 0, the index of
-        the 2nd item is 1, and so on. So to get the name of the first animal
-        you write <literal>animals[0].name</literal>. To get the second item
-        in <literal>misc.fruits</literal> (the string
-        <literal>"banana"</literal>) you write
-        <literal>misc.fruits[1]</literal>. (In practice, you usually just walk
-        through sequences in order, not caring about the index, but that will
-        be <link linkend="topic.tutorial.list">shown later</link>.)</para>
-
-        <para>Scalars can be further divided into these categories:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para>String: Text, that is, an arbitrary sequence of characters
-            such as ''m'', ''o'', ''u'', ''s'', ''e'' above. For example the
-            <literal>name</literal>-s and <literal>size</literal>-s are
-            strings above.</para>
-          </listitem>
-
-          <listitem>
-            <para>Number: It's a numerical value, like the
-            <literal>price</literal>-s above. The string
-            <literal>"50"</literal> and the number <literal>50</literal> are
-            two totally different things in FreeMarker. The former is just a
-            sequence of two characters (which happens to be readable as a
-            number for humans), while the latter is a numerical value that you
-            can use in arithmetical calculations.</para>
-          </listitem>
-
-          <listitem>
-            <para>Date-like: Either a date-time (stores a date with time of
-            the day), or a date (no time of day), or a time (time of day, no
-            date).</para>
-          </listitem>
-
-          <listitem>
-            <para>Boolean: A true/false (yes/no, on/off, etc.) thing. Like
-            animals could have a <literal>protected</literal> subvariable,
-            which store if the animal is protected or not.</para>
-          </listitem>
-        </itemizedlist>
-
-        <para>Summary:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para>The data-model can be visualized as a tree.</para>
-          </listitem>
-
-          <listitem>
-            <para>Scalars store a single value. The value can be a string or a
-            number or a date-time/date/time or a boolean.</para>
-          </listitem>
-
-          <listitem>
-            <para>Hashes are containers that store other variables and
-            associate them with a unique lookup name.</para>
-          </listitem>
-
-          <listitem>
-            <para>Sequences are containers that store other variables in an
-            ordered sequence. The stored variables can be retrieved via their
-            numerical index, starting from 0.</para>
-          </listitem>
-        </itemizedlist>
-
-        <note>
-          <para>There are other, more advanced value types that we don't cover
-          here, such as methods and directives.</para>
-        </note>
-      </section>
-
-      <section xml:id="dgui_quickstart_template">
-        <title>The template at a glance</title>
-
-        <para>The simplest template is a plain HTML file (or whatever text
-        file; FreeMarker is not confined to HTML). When the client visits that
-        page, FreeMarker will send that HTML to the client as is. However if
-        you want that page to be more dynamic then you begin to put special
-        parts into the HTML which will be understood by FreeMarker:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para><literal>${<replaceable>...</replaceable>}</literal>:
-            FreeMarker will replace it in the output with the actual value of
-            the expression inside the curly brackets. They are called
-            <emphasis role="term">interpolation</emphasis>s.</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="term">FTL tags</emphasis> (for FreeMarker
-            Template Language tags): FTL tags are a bit similar to HTML tags,
-            but they are instructions to FreeMarker and will not be printed to
-            the output. The name of these tags start with
-            <literal>#</literal>. (User-defined FTL tags use
-            <literal>@</literal> instead of <literal>#</literal>, but they are
-            an advanced topic.)</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="term">Comments:</emphasis> Comments are
-            similar to HTML comments, but they are delimited by
-            <literal>&lt;#--</literal> and <literal>--&gt;</literal>. Unlike
-            HTML comments, FTL comments won't get into the output (won't be
-            visible in the page source for the visitor), because FreeMarker
-            skips them.</para>
-          </listitem>
-        </itemizedlist>
-
-        <para>Anything not an FTL tag or an interpolation or comment is
-        considered as static text, and will not be interpreted by FreeMarker;
-        it is just printed to the output as is.</para>
-
-        <para>With FTL tags you refer to so-called <emphasis
-        role="term">directives</emphasis>. This is the same kind of
-        relationship as between HTML tags (e.g.:
-        <literal>&lt;table&gt;</literal> and
-        <literal>&lt;/table&gt;</literal>) and HTML elements (e.g., the
-        <literal>table</literal> element) to which you refer to with the HTML
-        tags. (If you don't feel this difference then just take "FTL tag" and
-        "directive" as synonyms.)</para>
-
-        <note>
-          <para>You can easily try writing templates on <link
-          xlink:href="http://freemarker-online.kenshoo.com/">http://freemarker-online.kenshoo.com/</link></para>
-        </note>
-
-        <section>
-          <title>Some basic directives</title>
-
-          <para>Here we will look at some of the most commonly used directives
-          (<link linkend="ref_directives">but there are much
-          more</link>).</para>
-
-          <section>
-            <title>The if directive</title>
-
-            <para>With the <literal>if</literal> directive you can
-            conditionally skip a section of the template. For example, assume
-            that in the <link linkend="example.first">very first
-            example</link> you want to greet your boss, Big Joe, differently
-            than other users:</para>
-
-            <programlisting role="template">&lt;html&gt;
-&lt;head&gt;
-  &lt;title&gt;Welcome!&lt;/title&gt;
-&lt;/head&gt;
-&lt;body&gt;
-  &lt;h1&gt;
-    Welcome ${user}<emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>, our beloved leader<emphasis>&lt;/#if&gt;</emphasis>!
-  &lt;/h1&gt;
-  &lt;p&gt;Our latest product:
-  &lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
-&lt;/body&gt;
-&lt;/html&gt;</programlisting>
-
-            <para>Here you have told FreeMarker that the <quote>, our beloved
-            leader</quote> should be there only if the value of the variable
-            <literal>user</literal> is equal to the string <literal>"Big
-            Joe"</literal>. In general, things between <literal>&lt;#if
-            <replaceable>condition</replaceable>&gt;</literal> and
-            <literal>&lt;/#if&gt;</literal> tags are skipped if
-            <literal><replaceable>condition</replaceable></literal> is false
-            (the boolean value).</para>
-
-            <para>Let's look at
-            <literal><replaceable>condition</replaceable></literal> more
-            closely: <literal>==</literal> is an operator that tests if the
-            values at its left and right side are equivalent, and the results
-            is a boolean value, true or false accordingly. On the left side of
-            <literal>==</literal> I have <link
-            linkend="topic.qStart.accessVariables">referenced a
-            variable</link> with the syntax that should be already familiar;
-            this will be replaced with the value of the variable. In general,
-            unquoted words inside directives or interpolations are treated as
-            references to variables. On the right side I have specified a
-            literal string. Literal strings in templates must
-            <emphasis>always</emphasis> be put inside quotation marks.</para>
-
-            <para>This will print <quote>Pythons are free today!</quote> if
-            their price is 0:</para>
-
-            <programlisting role="template">&lt;#if animals.python.price == <emphasis>0</emphasis>&gt;
-  Pythons are free today!
-&lt;/#if&gt;</programlisting>
-
-            <para>Similarly as earlier when a string was specified directly,
-            here a number is specified directly (<literal>0</literal>). Note
-            that the number is <emphasis>not</emphasis> quoted. If you quoted
-            it (<literal>"0"</literal>), FreeMarker were misinterpret it as a
-            string literal, and because the price to compare it to is number,
-            you get an error.</para>
-
-            <para>This will print "Pythons are not free today!" if their price
-            is not 0:</para>
-
-            <programlisting role="template">&lt;#if animals.python.price <emphasis>!=</emphasis> 0&gt;
-  Pythons are not free today!
-&lt;/#if&gt;</programlisting>
-
-            <para>As you probably guessed, <literal>!=</literal> means
-            <quote>not equals</quote>.</para>
-
-            <para>You can write things like this too (using <link
-            linkend="example.qStart.dataModelWithHashes">the data-model used
-            to demonstrate hashes</link>):</para>
-
-            <programlisting role="template">&lt;#if <emphasis>animals.python.price &lt; animals.elephant.price</emphasis>&gt;
-  Pythons are cheaper than elephants today.
-&lt;/#if&gt;</programlisting>
-
-            <para>With the <literal>&lt;#else&gt;</literal> tag you can
-            specify what to do if the condition is false. For example:</para>
-
-            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
-  Pythons are cheaper than elephants today.
-<emphasis>&lt;#else&gt;</emphasis>
-  Pythons are not cheaper than elephants today.
-&lt;/#if&gt;</programlisting>
-
-            <para>This prints <quote>Pythons are cheaper than elephants
-            today.</quote> if the price of python is less than the price of
-            elephant, or else it prints <quote>Pythons are not cheaper than
-            elephants today.</quote> You can refine this further by using
-            <literal>elseif</literal>:</para>
-
-            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
-  Pythons are cheaper than elephants today.
-<emphasis>&lt;#elseif animals.elephant.price &lt; animals.python.price&gt;</emphasis>
-  Elephants are cheaper than pythons today.
-&lt;#else&gt;
-  Elephants and pythons cost the same today.
-&lt;/#if&gt;</programlisting>
-
-            <para>If you have a variable with boolean value (a true/false
-            thing) then you can use it directly as the
-            <literal><replaceable>condition</replaceable></literal> of
-            <literal>if</literal>:</para>
-
-            <programlisting role="template">&lt;#if animals.python.protected&gt;
-  Pythons are protected animals!
-&lt;/#if&gt;</programlisting>
-          </section>
-
-          <section>
-            <title>The list directive</title>
-
-            <anchor xml:id="topic.tutorial.list"/>
-
-            <para>This is needed when you want to list something. For example
-            if you merge this template with the <link
-            linkend="example.qStart.dataModelWithSequences">data-model used
-            earlier to demonstrate sequences</link>:</para>
-
-            <programlisting role="template">&lt;p&gt;We have these animals:
-&lt;table border=1&gt;
-  <emphasis>&lt;#list animals as animal&gt;</emphasis>
-    &lt;tr&gt;&lt;td&gt;${<emphasis>animal</emphasis>.name}&lt;td&gt;${<emphasis>animal</emphasis>.price} Euros
-  <emphasis>&lt;/#list&gt;</emphasis>
-&lt;/table&gt;</programlisting>
-
-            <para>then the output will be:</para>
-
-            <programlisting role="output">&lt;p&gt;We have these animals:
-&lt;table border=1&gt;
-    <emphasis>&lt;tr&gt;&lt;td&gt;mouse&lt;td&gt;50 Euros
-    &lt;tr&gt;&lt;td&gt;elephant&lt;td&gt;5000 Euros
-    &lt;tr&gt;&lt;td&gt;python&lt;td&gt;4999 Euros</emphasis>
-&lt;/table&gt;</programlisting>
-
-            <para>The generic form of the <literal>list</literal> directive
-            is:<literal> &lt;#list <replaceable>sequence</replaceable> as
-            <replaceable>loopVariable</replaceable>&gt;<replaceable>repeatThis</replaceable>&lt;/#list&gt;</literal>.
-            The <literal><replaceable>repeatThis</replaceable></literal> part
-            will be repeated for each item in the sequence that you have
-            specified with
-            <literal><replaceable>sequence</replaceable></literal>, one after
-            the other, starting from the first item. In all repetitions
-            <literal><replaceable>loopVariable</replaceable></literal> will
-            hold the value of the current item. This variable exists only
-            between the <literal>&lt;#list
-            <replaceable>...</replaceable>&gt;</literal> and
-            <literal>&lt;/#list&gt;</literal> tags.</para>
-
-            <para>The <literal><replaceable>sequence</replaceable></literal>
-            can be any kind of expression, like we could list the fruits of
-            the example data model like this:</para>
-
-            <programlisting role="template">&lt;ul&gt;
-<emphasis>&lt;#list misc.fruits as fruit&gt;</emphasis>
-  &lt;li&gt;${fruit}
-<emphasis>&lt;/#list&gt;</emphasis>
-&lt;/ul&gt;</programlisting>
-
-            <para>The <literal>misc.fruits</literal> expression should be
-            familiar to you; it <link
-            linkend="topic.qStart.accessVariables">references a variable in
-            the data-model</link>.</para>
-
-            <para>A problem with the above example is that if we happen to
-            have 0 fruits, it will still print an empty
-            <literal>&lt;ul&gt;&lt;/ul&gt;</literal> instead of just nothing.
-            To avoid that, you can use this form of
-            <literal>list</literal>:</para>
-
-            <programlisting role="template">&lt;#list misc.fruits&gt;
-  &lt;ul&gt;
-   <emphasis> &lt;#items as fruit&gt;</emphasis>
-      &lt;li&gt;${fruit}
- <emphasis>   &lt;/#items&gt;</emphasis>
-  &lt;/ul&gt;
-&lt;/#list&gt;</programlisting>
-
-            <para>Here, the <literal>list</literal> directive represents the
-            listing as a whole, and only the part inside the
-            <literal>items</literal> directive is repeated for each fruit. If
-            we have 0 fruits, everything inside <literal>list</literal> is
-            skipped, hence we will not have <literal>ul</literal> tags in
-            case.</para>
-
-            <para>Another frequent listing-related task: let's list the fruits
-            separating them with something, like comma:</para>
-
-            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}<emphasis>&lt;#sep&gt;, </emphasis>&lt;/#list&gt;</programlisting>
-
-            <programlisting role="output">&lt;p&gt;Fruits: orange, banana</programlisting>
-
-            <para>The section covered by <literal>sep</literal> (which we
-            could be written like this too:
-            <literal><replaceable>...</replaceable>&lt;#sep&gt;,
-            &lt;/#sep&gt;&lt;/#list&gt;</literal>) will be only executed when
-            there will be a next item. Hence there's no comma after the last
-            fruit.</para>
-
-            <para>Here again, what's if we have 0 fruits? Just printing
-            <quote>Fruits:</quote> and then nothing is awkward. A
-            <literal>list</literal>, just like an <literal>if</literal>, can
-            have an <literal>else</literal>, which is executed if there were 0
-            list items:</para>
-
-            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}&lt;#sep&gt;, <emphasis>&lt;#else&gt;None</emphasis>&lt;/#list&gt;</programlisting>
-
-            <note>
-              <para>As a matter of fact, this simplistic example could be
-              written like this, but it uses language devices that are off
-              topic here:</para>
-
-              <programlisting role="template">&lt;p&gt;Fruits: ${fruits?join(", ", "None")}</programlisting>
-            </note>
-
-            <para>All these directives (<literal>list</literal>,
-            <literal>items</literal>, <literal>sep</literal>,
-            <literal>else</literal>) can be used together:</para>
-
-            <programlisting role="template">&lt;#list misc.fruits&gt;
-  &lt;p&gt;Fruits:
-  &lt;ul&gt;
-    &lt;#items as fruit&gt;
-      &lt;li&gt;${fruit}&lt;#sep&gt; and&lt;/#sep&gt;
-    &lt;/#items&gt;
-  &lt;/ul&gt;
-&lt;#else&gt;
-  &lt;p&gt;We have no fruits.
-&lt;/#list&gt;</programlisting>
-
-            <note>
-              <para>You can read more about these directives <link
-              linkend="ref_directive_list">in the Reference</link>.</para>
-            </note>
-          </section>
-
-          <section>
-            <title>The include directive</title>
-
-            <para>With the <literal>include</literal> directive you can insert
-            the content of another file into the template.</para>
-
-            <para>Suppose you have to show the same copyright notice on
-            several pages. You can create a file that contains the copyright
-            notice only, and insert that file everywhere where you need that
-            copyright notice. Say, you store this copyright notice in
-            <literal>copyright_footer.html</literal>:</para>
-
-            <programlisting role="template">&lt;hr&gt;
-&lt;i&gt;
-Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
-&lt;br&gt;
-All Rights Reserved.
-&lt;/i&gt;</programlisting>
-
-            <para>Whenever you need that file you simply insert it with the
-            <literal>include</literal> directive:</para>
-
-            <programlisting role="template">&lt;html&gt;
-&lt;head&gt;
-  &lt;title&gt;Test page&lt;/title&gt;
-&lt;/head&gt;
-&lt;body&gt;
-  &lt;h1&gt;Test page&lt;/h1&gt;
-  &lt;p&gt;Blah blah...
-<emphasis>  &lt;#include "/copyright_footer.html"&gt;</emphasis>
-&lt;/body&gt;
-&lt;/html&gt;</programlisting>
-
-            <para>and the output will be:</para>
-
-            <programlisting role="output">&lt;html&gt;
-&lt;head&gt;
-  &lt;title&gt;Test page&lt;/title&gt;
-&lt;/head&gt;
-&lt;body&gt;
-  &lt;h1&gt;Test page&lt;/h1&gt;
-  &lt;p&gt;Blah blah...
-<emphasis>&lt;hr&gt;
-&lt;i&gt;
-Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
-&lt;br&gt;
-All Rights Reserved.
-&lt;/i&gt;</emphasis>
-&lt;/body&gt;
-&lt;/html&gt;</programlisting>
-
-            <para>If you change the <literal>copyright_footer.html</literal>,
-            then the visitor will see the new copyright notice on all
-            pages.</para>
-
-            <note>
-              <para>A much more powerful way of reusing snippets is using
-              macros, but that's an advanced topic <link
-              linkend="dgui_misc_userdefdir">discussed later</link>.</para>
-            </note>
-          </section>
-        </section>
-
-        <section>
-          <title>Using directives together</title>
-
-          <para>You can use directives as many times on a page as you want,
-          and you can nest directives into each other freely. For example,
-          here you nest <literal>if</literal> directive inside a
-          <literal>list</literal> directive:</para>
-
-          <programlisting role="template"><emphasis>&lt;#list animals as animal&gt;</emphasis>
-      &lt;div<emphasis>&lt;#if animal.protected&gt;</emphasis><emphasis> </emphasis>class="protected"<emphasis>&lt;/#if&gt;</emphasis>&gt;
-        ${animal.name} for ${animal.price} Euros
-      &lt;/div&gt;
-<emphasis>&lt;/#list&gt;</emphasis></programlisting>
-
-          <para>Note that since FreeMarker does not interpret text outside FTL
-          tags, interpolations and FTL comments, above you could use the FTL
-          tags inside a 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 coming from
-          the data-model, but added by FreeMarker to the values. To make it
-          unambiguous where the subvarable comes from, to access them you have
-          to use <literal>?</literal> (question mark) instead of
-          <literal>.</literal> (dot). <anchor
-          xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most
-          commonly used built-ins:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>user?upper_case</literal> gives the upper case
-              version of the value of <literal>user</literal> (like
-              <quote>JOHN DOE</quote> instead of <quote>John
-              Doe</quote>)</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>animal.name?cap_first</literal> give the
-              <literal>animal.name</literal> with its first letter converted
-              to upper case (like <quote>Mouse</quote> instead of
-              <quote>mouse</quote>)</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>user?length</literal> gives the number of
-              <emphasis>characters</emphasis> in the value of
-              <literal>user</literal> (8 for <quote>John Doe</quote>)</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>animals?size</literal> gives the number of
-              <emphasis>items</emphasis> in the <literal>animals</literal>
-              sequence (3 in our example data-model)</para>
-            </listitem>
-
-            <listitem>
-              <para>If you are between <literal>&lt;#list animals as
-              animal&gt;</literal> and the corresponding
-              <literal>&lt;/#list&gt;</literal> tag:</para>
-
-              <itemizedlist>
-                <listitem>
-                  <para><literal>animal?index</literal> gives the 0-based
-                  index of <literal>animal</literal> inside
-                  <literal>animals</literal></para>
-                </listitem>
-
-                <listitem>
-                  <para><literal>animal?counter</literal> is like
-                  <literal>index</literal>, but gives the 1-based index</para>
-                </listitem>
-
-                <listitem>
-                  <para><literal>animal?item_parity</literal> gives the
-                  strings <quote>odd</quote> or <quote>even</quote>, depending
-                  on the current counter parity. This is commonly used for
-                  coloring rows with alternating colors, like in
-                  <literal>&lt;td
-                  class="${animal?item_parity}Row"&gt;</literal>.</para>
-                </listitem>
-              </itemizedlist>
-            </listitem>
-          </itemizedlist>
-
-          <para>Some built-ins require parameters to specify the behavior
-          more, for example:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>animal.protected?string("Y", "N")</literal>
-              return the string <quote>Y</quote> or <quote>N</quote> depending
-              on the boolean value of
-              <literal>animal.protected</literal>.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>animal?item_cycle('lightRow',
-              'darkRow')</literal> is the more generic variant of
-              <literal>item_parity</literal> from earlier.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>fruits?join(", ")</literal>: converts the list to
-              a string by concatenating items, and inserting the parameter
-              separator between each items (like <quote>orange,
-              banana</quote>)</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>user?starts_with("J")</literal> gives boolean
-              true of false depending on if <literal>user</literal> starts
-              with the letter <quote>J</quote> or not.</para>
-            </listitem>
-          </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 the referring 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, so the "missing" term used here
-          covers both cases.</phrase></para>
-
-          <para>Wherever you refer to a variable, you can specify a default
-          value for the case the variable is missing, by following the
-          variable name with a <literal>!</literal> and the default value.
-          Like in the following example, when <literal>user</literal> is
-          missing from data model, the template will behave like if
-          <literal>user</literal>'s value were the string
-          <literal>"visitor"</literal>. (When <literal>user</literal> isn't
-          missing, this template behaves exactly like with
-          <literal>${user}</literal>):</para>
-
-          <programlisting role="template">&lt;h1&gt;Welcome ${user<emphasis>!"visitor"</emphasis>}!&lt;/h1&gt;</programlisting>
-
-          <para>You can ask whether a variable isn't missing by putting
-          <literal>??</literal> after its name. Combining this with the
-          already introduced <literal>if</literal> directive you can skip the
-          whole greeting if the <literal>user</literal> variable is
-          missing:</para>
-
-          <programlisting role="template">&lt;#if <emphasis>user??</emphasis>&gt;&lt;h1&gt;Welcome ${user}!&lt;/h1&gt;&lt;/#if&gt;</programlisting>
-
-          <para>Regarding variable accessing with multiple steps, like
-          <literal>animals.python.price</literal>, writing
-          <literal>animals.python.price!0</literal> is correct only if
-          <literal>animals.python</literal> is never missing and only the last
-          subvariable, <literal>price</literal>, is possibly missing (in which
-          case here we assume it's <literal>0</literal>). If
-          <literal>animals</literal> or <literal>python</literal> is missing,
-          the template processing will stop with an "undefined variable"
-          error. To prevent that, you have to write
-          <literal>(animals.python.price)!0</literal>. In that case the
-          expression will be <literal>0</literal> even if
-          <literal>animals</literal> or <literal>python</literal> is missing.
-          Same logic goes for <literal>??</literal>;
-          <literal>animals.python.price??</literal> versus
-          <literal>(animals.python.price)??</literal>.</para>
-        </section>
-
-        <section xml:id="dgui_quickstart_template_autoescaping">
-          <title>Escaping for HTML, XML and other markup</title>
-
-          <para>Let's say the template generates HTML, and you insert values
-          with <literal>${<replaceable>...</replaceable>}</literal> that are
-          plain text (not HTML), like company names coming from a database.
-          Characters that has special meaning in HTML must be
-          <emphasis>escaped</emphasis> in such values, like if
-          <literal>name</literal> is <quote>Someone &amp; Co.</quote> then
-          <literal>${name}</literal> should print <quote>Someone
-          <emphasis>&amp;amp;</emphasis> Co.</quote>.</para>
-
-          <para>FreeMarker automatically escapes all values printed with
-          <literal>${<replaceable>...</replaceable>}</literal> <emphasis>if
-          it's properly configured</emphasis> (that's the responsibility of
-          the programmers; <link
-          linkend="pgui_config_outputformatsautoesc">see here how</link>). The
-          recommended practice is using <literal>ftlh</literal> file extension
-          to activate HTML auto-escaping, and <literal>ftlx</literal> file
-          extension to activate XML auto-escaping.</para>
-
-          <para>You can try if auto-escaping is on like
-          <literal>${"&lt;"}</literal> (for HTML or XML escaping). If it's
-          not, and the configuration won't be adjusted, add this as the very
-          first line of the template:</para>
-
-          <programlisting role="template">&lt;#ftl output_format="HTML"&gt;</programlisting>
-
-          <para>(Use <literal>"XML"</literal> instead of
-          <literal>"HTML"</literal> above if you generate XML.)</para>
-
-          <para>If the string value to print deliberately contains markup,
-          auto-escaping must be prevented like
-          <literal>${<replaceable>value</replaceable>?no_esc}</literal>.</para>
-
-          <para>You can find out much more about auto-escaping and output
-          formats <link linkend="dgui_misc_autoescaping">here...</link></para>
-
-          <note>
-            <para>The kind of automatic escaping described here requires at
-            least FreeMarker 2.3.24. If you have to use an earlier version,
-            use the deprecated <link
-            linkend="ref_directive_escape"><literal>escape</literal>
-            directive</link> instead.</para>
-          </note>
-        </section>
-      </section>
-    </chapter>
-
-    <chapter xml:id="dgui_datamodel">
-      <title>Values, Types</title>
-
-      <section xml:id="dgui_datamodel_basics">
-        <title>Basics</title>
-
-        <note>
-          <para>It is assumed that you have already read the <xref
-          linkend="dgui_quickstart"/> chapter.</para>
-        </note>
-
-        <para>Understanding the concept of values and types is crucial for the
-        understanding of data-models. However, the concept of values and types
-        is not confined to data-models, as you will see.</para>
-
-        <section xml:id="topic.value">
-          <title>What is a value?</title>
-
-          <indexterm>
-            <primary>value</primary>
-          </indexterm>
-
-          <para><phrase role="forProgrammers">Real programmers can safely skip
-          this section.</phrase></para>
-
-          <para>Examples of <emphasis>values</emphasis> as you know the term
-          from the everyday math are 16, 0.5, and so on, i.e. numbers. In the
-          case of computer languages the value term has a wider meaning, as a
-          value needn't be a number. For example, take this data-model:</para>
-
-          <programlisting role="dataModel" xml:id="example.stdDataModel">(root)
- |
- +- user = "Big Joe"
- |
- +- today = Jul 6, 2007
- |
- +- todayHoliday = false
- |
- +- lotteryNumbers
- |   |
- |   +- (1st) = 20
- |   |
- |   +- (2st) = 14
- |   |
- |   +- (3rd) = 42
- |   |
- |   +- (4th) = 8
- |   |
- |   +- (5th) = 15
- |
- +- cargo
-     |
-     +- name = "coal"
-     |
-     +- weight = 40
-</programlisting>
-
-          <para>We say that the <emphasis>value</emphasis> of the the
-          <literal>user</literal> variable is "Big Joe" (a string), the
-          <emphasis>value</emphasis> of <literal>today</literal> is Jul 6,
-          2007 (a date), the <emphasis>value</emphasis> of
-          <literal>todayHoliday</literal> is false (a boolean, ie. a yes/no
-          thing). The <emphasis>value</emphasis> of
-          <literal>lotteryNumbers</literal> is the sequence that contains 20,
-          14, 42, 8, 15. Surely <literal>lotteryNumbers</literal> is multiple
-          values in the sense that it <emphasis>contains</emphasis> multiple
-          values (for example, the 2nd item in it is a the
-          <emphasis>value</emphasis> 14), but still,
-          <literal>lotteryNumbers</literal> itself is a single value. It's
-          like a box that contains many other items; the whole box can be seen
-          as a single item. Last not least we also have the
-          <emphasis>value</emphasis> of <literal>cargo</literal>, which is a
-          hash (a box-like thing again).So, a value is something that can be
-          stored in a variable (e.g., in <literal>user</literal> or
-          <literal>cargo</literal> or <literal>cargo.name</literal>). But a
-          value need not be stored in a variable to be called a value, for
-          example we have the value 100 here:</para>
-
-          <programlisting role="template">&lt;#if cargo.weight &lt; <emphasis>100</emphasis>&gt;Light cargo&lt;/#if&gt;</programlisting>
-
-          <para>The temporaly result of a calculations are also called values,
-          like 20 and 120 when this template is executed (it will print
-          120):</para>
-
-          <programlisting role="template">${cargo.weight / 2 + 100}</programlisting>
-
-          <para>Explanation for this last: As the result of dividing the two
-          values, 40 (the weight of the cargo) and 2, a new value 20 is
-          created. Then 100 is added to it, so the value 120 is created. Then
-          120 is printed
-          (<literal>${<replaceable>...</replaceable>}</literal>), and the
-          template execution goes on and all these values gone.</para>
-
-          <para>Certainly now you feel what the value term means.</para>
-        </section>
-
-        <section>
-          <title>What is type?</title>
-
-          <para>Values have an important aspect, their type. For example the
-          type of the value of the <literal>user</literal> variable is string,
-          and the type of the value of the <literal>lotteryNumbers</literal>
-          variable is sequence. The type of a value is important because it
-          determines to a large extent how and where you can use the value.
-          Like <literal>${user / 2}</literal> is an error, but
-          <literal>${cargo.weight / 2}</literal> works and prints 20, since
-          division only does make sense for a number, but not for a string.
-          Or, using dot like in <literal>cargo.name</literal> does make sense
-          only if <literal>cargo</literal> is a hash. Or, you can list with
-          <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
-          sequences only. Or, the condition of <literal>&lt;#if
-          ...&gt;</literal> must be a boolean. And so on.</para>
-
-          <note>
-            <para>A little terminology... Saying "a boolean" or "a boolean
-            value" or "a value of type boolean" are all the same.</para>
-          </note>
-
-          <para xml:id="topic.multitype"><indexterm>
-              <primary>Multi-typed value</primary>
-            </indexterm>A value can have multiple types at the same time,
-          although it's rarely utilized. For example in the data-model below
-          <literal>mouse</literal> is both a string and a hash:</para>
-
-          <programlisting role="dataModel">(root)
- |
- +- mouse = "Yerri"
-     |
-     +- age = 12
-     |
-     +- color = "brown"</programlisting>
-
-          <para>If you merge this template with the above data-model:</para>
-
-          <programlisting role="template">${mouse}       &lt;#-- uses mouse as a string --&gt;
-${mouse.age}   &lt;#-- uses mouse as a hash --&gt;
-${mouse.color} &lt;#-- uses mouse as a hash --&gt;</programlisting>
-
-          <para>the output will be:</para>
-
-          <programlisting role="output">Yerri
-12
-brown</programlisting>
-        </section>
-
-        <section>
-          <title>The data-model is a hash</title>
-
-          <para>Looking at the various data-model examples you may already
-          realized: the thing marked as "(root)" is just a value of type hash.
-          When you write something like <literal>user</literal>, that means
-          that you want the "user" variable stored in the root hash. Like if
-          you were writing <literal>root.user</literal>, except that there is
-          no variable called "root" so that wouldn't work.</para>
-
-          <para>Some may get confused by the fact that our example data-model,
-          that is, the root hash, contains further hashes and sequences
-          (<literal>lotteryNumbers</literal> and <literal>cargo</literal>).
-          There is nothing special in that. A hash contains other variables,
-          and those variables have a value, which can be a string, a number,
-          etc., and of course it can be a hash or sequence as well. Because,
-          as it was explained earlier, a sequence or a hash is just a value,
-          like a string or a number is.</para>
-        </section>
-      </section>
-
-      <section xml:id="dgui_datamodel_types">
-        <title>The types</title>
-
-        <para>The suppored types are:</para>
-
-        <itemizedlist spacing="compact">
-          <listitem>
-            <para><link linkend="dgui_datamodel_scalar"
-            os="">Scalars:</link></para>
-
-            <itemizedlist spacing="compact">
-              <listitem>
-                <para>String</para>
-              </listitem>
-
-              <listitem>
-                <para>Number</para>
-              </listitem>
-
-              <listitem>
-                <para>Boolean</para>
-              </listitem>
-
-              <listitem>
-                <para>Date-like (date, time, or date-time)</para>
-              </listitem>
-            </itemizedlist>
-          </listitem>
-
-          <listitem>
-            <para><link
-            linkend="dgui_datamodel_container">Containers:</link></para>
-
-            <itemizedlist spacing="compact">
-              <listitem>
-                <para>Hash</para>
-              </listitem>
-
-              <listitem>
-                <para>Sequence</para>
-              </listitem>
-
-              <listitem>
-                <para>Collection</para>
-              </listitem>
-            </itemizedlist>
-          </listitem>
-
-          <listitem>
-            <para>Subroutines:</para>
-
-            <itemizedlist spacing="compact">
-              <listitem>
-                <para><link linkend="dgui_datamodel_method">Methods and
-                functions</link></para>
-              </listitem>
-
-              <listitem>
-                <para><link linkend="dgui_datamodel_userdefdir">User-defined
-                directives</link></para>
-              </listitem>
-            </itemizedlist>
-          </listitem>
-
-          <listitem>
-            <para>Miscellaneous/seldom used:</para>
-
-            <itemizedlist spacing="compact">
-              <listitem>
-                <para><link linkend="dgui_datamodel_node">Node</link></para>
-              </listitem>
-
-              <listitem>
-                <para><link linkend="dgui_datamodel_markupoutput">Markup
-                output</link></para>
-              </listitem>
-            </itemizedlist>
-          </listitem>
-        </itemizedlist>
-
-        <section xml:id="dgui_datamodel_scalar">
-          <title>Scalars</title>
-
-          <anchor xml:id="topic.designer.scalarVariable"/>
-
-          <para>These are the basic, simple kind of values. They can
-          be:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><indexterm>
-                  <primary>string</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>String: It is simple text, e.g., the name of a
-              product.</para>
-
-              <para>If you want to give a string value directly in the
-              template, rather than use a variable that comes from the data
-              model, you write the text between quotation marks, e.g.,
-              <literal>"green mouse"</literal> or <literal>'green
-              mouse'</literal>. (More details regarding the syntax can be
-              found <link linkend="dgui_template_exp_direct_string"
-              xml:lang="">later</link>.)</para>
-            </listitem>
-
-            <listitem>
-              <para><indexterm>
-                  <primary>number</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>Number: For example the price of a product.
-              <phrase role="forProgrammers">Whole numbers and non-whole
-              numbers are not distinguished; there is only a single number
-              type. So for example 3/2 will be always 1.5, and never 1. Just
-              like if you are using a calculator.</phrase></para>
-
-              <para>If you want to give a numerical value directly in the
-              template, then you write for example: <literal>150</literal> or
-              <literal>-90.05</literal> or <literal>0.001</literal>. (More
-              details regarding the syntax can be found <link
-              linkend="dgui_template_exp_direct_number"
-              xml:lang="">later</link>.)</para>
-            </listitem>
-
-            <listitem>
-              <para><indexterm>
-                  <primary>boolean</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>Boolean: A boolean value represents a logical true
-              or false (yes or no). For example, if a the visitor has been
-              logged in or not. Typically you use booleans as the condition of
-              the <literal>if</literal> directive, like <literal>&lt;#if
-              loggedIn
-              &gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal> or
-              <literal>&lt;#if price ==
-              0&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>; in
-              the last case the result of the <literal>price == 0</literal>
-              part is a boolean value.</para>
-
-              <para>In the templates you can directly specify a boolean with
-              the reserved words <literal>true</literal> and
-              <literal>false</literal>.</para>
-            </listitem>
-
-            <listitem>
-              <para><indexterm>
-                  <primary>date</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm><indexterm>
-                  <primary>time</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm><indexterm>
-                  <primary>date-time</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>Date: A date-like value stores date/time related
-              data. It has three variations:</para>
-
-              <itemizedlist>
-                <listitem>
-                  <para>Date: Like April 4, 2003. Day precision, no time of
-                  day part.</para>
-                </listitem>
-
-                <listitem>
-                  <para>Time: Like 10:19:18 PM. Millisecond precision, no date
-                  part.</para>
-                </listitem>
-
-                <listitem>
-                  <para>Date-time (sometimes called "time stamp") as April 4,
-                  2003 10:19:18 PM. Both date and time, with millisecond
-                  precision.</para>
-                </listitem>
-              </itemizedlist>
-
-              <para>Unfortunately, because of the limitations of the Java
-              platform, FreeMarker sometimes can't decide which parts of the
-              date are in use (i.e., if it is date-time, a date or a time).
-              The solution for this problem is an advanced topic that will be
-              discussed <link
-              linkend="ref_builtin_date_datetype">later</link>.</para>
-
-              <para>It is possible to define date-like values directly in
-              templates, but this is an advanced topic that will be explained
-              <link linkend="ref_builtin_string_date">later</link>.</para>
-            </listitem>
-          </itemizedlist>
-
-          <para>Bear in mind that FreeMarker distinguishes strings from
-          numbers, booleans and date-like values. For example, while the
-          string <literal>"150"</literal> looks like the number
-          <literal>150</literal>, a string is still just arbitrary sequence of
-          characters, and you can't do arithmetic with it, can't compare it
-          with another number, etc.</para>
-        </section>
-
-        <section xml:id="dgui_datamodel_container">
-          <title>Containers</title>
-
-          <remark>Re-explanation of hashes and sequences from a more
-          ''professional'' viewpoint as earlier, and some meditation about
-          them.</remark>
-
-          <para>These are the values whose purpose is to contain other
-          variables; they are just containers. The contained variables are
-          often referred as <emphasis>sub variables</emphasis>. The container
-          types are:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><indexterm>
-                  <primary>hash</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>Hash: Associates a unique lookup name with each of
-              its sub variables. The name is an unrestricted string. A hash
-              <emphasis>doesn't define an ordering</emphasis> for the sub
-              variables in it. That is, there is no such thing as the first
-              subvariable, and the second subvariable, etc.; the variables are
-              just accessed by name.</para>
-            </listitem>
-
-            <listitem>
-              <para><indexterm>
-                  <primary>sequence</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>Sequence: Associates an integer number with each
-              of its sub variables. The first subvariable is associated with
-              0, the second with 1, the third to 2, and so on; the sub
-              variables are ordered. These numbers are often called the
-              <emphasis>indexes</emphasis> of the sub variables. Sequences are
-              usually dense, i.e., all indexes up to the index of the last
-              subvariable have an associated subvariable, but it's not
-              strictly necessary. The type of the subvariable values need not
-              be the same.</para>
-            </listitem>
-
-            <listitem>
-              <para><indexterm>
-                  <primary>collection</primary>
-
-                  <secondary>the FTL value type</secondary>
-                </indexterm>Collection: A collection, from the viewpoint of
-              the template author, is a restricted sequence. You cannot access
-              its size or retrieve its sub variables by index, but they can be
-              still listed with the <link
-              linkend="ref.directive.list"><literal>list</literal>
-              directive</link>.</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>
-        </section>
-
-        <section>
-          <title>Subroutines</title>
-
-          <section xml:id="dgui_datamodel_method">
-            <title>Methods and functions</title>
-
-            <anchor xml:id="topic.designer.methodVariable"/>
-
-            <indexterm>
-              <primary>method</primary>
-
-              <secondary>the FTL value type</secondary>
-            </indexterm>
-
-            <para>A value that is a method or a function is used to calculate
-            another value, influenced by the parameters you give to it.</para>
-
-            <para><phrase role="forProgrammers">For programmer types:
-            Methods/functions are first-class values, just like in functional
-            programming languages. This means that functions/methods can be
-            the parameters or return values of other functions/methods, you
-            can assign them to variables, and so on.</phrase></para>
-
-            <para>Suppose that programmers have put the method variable
-            <literal>avg</literal> in the data-model that can be used to
-            calculate the average of numbers. If you give the 3 and 5 as
-            parameters when you access <literal>avg</literal>, then you get
-            the value 4.</para>
-
-            <para>The usage of methods will be explained <link
-            linkend="dgui_template_exp_methodcall">later</link>, but perhaps
-            this example helps to understand what methods are:</para>
-
-            <programlisting role="template">The average of 3 and 5 is: ${avg(3, 5)}
-The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
-The average of the price of a python and an elephant is:
-${avg(animals.python.price, animals.elephant.price)}</programlisting>
-
-            <para>this will output:</para>
-
-            <programlisting role="output">The average of 3 and 5 is: 4
-The average of 6 and 10 and 20 is: 12
-The average of the price of a python and an elephant is:
-4999.5</programlisting>
-
-            <para>What is the difference between a method and a function? As
-            far as the template author is concerned, nothing. Well not really
-            nothing, as methods typically come from the data-model (<phrase
-            role="forProgrammers">as they reflect the methods of Java
-            objects</phrase>), and functions are defined in templates (with
-            the <link
-            linkend="ref.directive.function"><literal>function</literal>
-            directive</link> -- an advanced topic), but both can be used on
-            the same way.</para>
-          </section>
-
-          <section xml:id="dgui_datamodel_userdefdir">
-            <title>User-defined directives</title>
-
-            <indexterm>
-              <primary>macro</primary>
-
-              <secondary>the FTL value type</secondary>
-            </indexterm>
-
-            <indexterm>
-              <primary>directive</primary>
-
-              <secondary>the FTL value type</secondary>
-            </indexterm>
-
-            <indexterm>
-              <primary>user-defined directive</primary>
-
-              <secondary>the FTL value type</secondary>
-            </indexterm>
-
-            <para>A value of this type can be used as user-defined directive
-            (with other words, as FreeMarker tag). An user-defined directive
-            is a subroutine, something like a little reusable template
-            fragment. But this is an advanced topic that will be explained
-            <link linkend="dgui_misc_userdefdir">later</link> in its own
-            chapter.</para>
-
-            <para><phrase role="forProgrammers">For programmer types:
-            user-defined directives (such as macros), are first-class values
-            too, just like functions/methods are.</phrase></para>
-
-            <para>Just to get an idea about user-defined directives (so just
-            ignore this if you won't understand), assume we have a variable,
-            <literal>box</literal>, whose value is a user-defined directive
-            that prints some kind of fancy HTML message box with a title bar
-            and a message in it. The <literal>box</literal> variable could be
-            used in the template like this (for example):</para>
-
-            <programlisting role="template">&lt;@<emphasis>box</emphasis> title="Attention!"&gt;
-  Too much copy-pasting may leads to
-  maintenance headaches.
-&lt;/@<emphasis>box</emphasis>&gt;</programlisting>
-          </section>
-
-          <section>
-            <title>Function/method versus user-defined directive</title>
-
-            <para>This is for advanced users again (so ignore it if you don't
-            understand). It's a frequent dilemma if you should use a
-            function/method or an user-defined directive to implement
-            something. The rule of thumb is: Implement the facility as
-            user-defined directive instead of as function/method if:</para>
-
-            <itemizedlist>
-              <listitem>
-                <para>... the purpose of it is generating a piece of the
-                output that's not just a single value, and typically involves
-                markup. The template language was designed for printing to the
-                output directly, piece by piece, as it goes though
-                <literal>list</literal> loops, <literal>if</literal>-s, etc.
-                Building up a string value in a variable then returning it is
-                much less convenient.</para>
-              </listitem>
-
-              <listitem>
-                <para>... it's the side-effect that is important and not the
-                return value. For example, a directive whose purpose is to add
-                an entry to the server log is like that. (In fact you can't
-                have a return value for a user-defined directive, but some
-                kind of feedback is still possible by setting non-local
-                variables.)</para>
-              </listitem>
-
-              <listitem>
-                <para>... it will do flow control on the caller side (like for
-                example <literal>list</literal> or <literal>if</literal>
-                directives do). You just can't do that with a
-                function/method.</para>
-              </listitem>
-
-              <listitem>
-                <para>... you are using legacy escaping via the
-                <literal>escape</literal> directive (instead of <link
-                linkend="dgui_misc_autoescaping">auto-escaping</link>), and
-                the result contains markup. When you print the result with
-                <literal>${<replaceable>...</replaceable>}</literal>, the
-                markup will be escaped and thus ruined, but if it's printed by
-                a directive call
-                (<literal>&lt;@<replaceable>...</replaceable>&gt;</literal>),
-                it won't be.</para>
-              </listitem>
-            </itemizedlist>
-
-            <para>The Java methods of FreeMarker-unaware Java objects are
-            normally visible as methods in templates, regardless of the nature
-            of the Java method; you have no choice there.</para>
-          </section>
-        </section>
-
-        <section>
-          <title>Miscellaneous</title>
-
-          <section xml:id="dgui_datamodel_node">
-            <title>Nodes</title>
-
-            <indexterm>
-              <primary>node</primary>
-
-              <secondary>the FTL value type</secondary>
-            </indexterm>
-
-            <para>Node variables represent a node in a tree structure, and are
-            used mostly with <link linkend="xgui">XML processing</link>, which
-            is an advanced, and specialized topic.</para>
-
-            <para>Still, a quick overview <emphasis>for advanced
-            users</emphasis>: A node is similar to a sequence that stores
-            other nodes, which are often referred as the children nodes. A
-            node stores a reference to its container node, which is often
-            referred as the parent node. The main point of being a node is the
-            topological information; other data must be stored by utilizing
-            that a value can have multiple types. Like, a value may be both a
-            node and a number, in which case it can store a number as the
-            "pay-load". Apart from the topological information, a node can
-            store some metainformation as well: a node name, a node type
-            (string), and a node namespace (string). For example, if the node
-            symbolizes a <literal>h1</literal> element in an XHTML document,
-            then its name could be <literal>"h1"</literal>, it's node type
-            could be <literal>"element"</literal>, and it's namespace could be
-            <literal>"http://www.w3.org/1999/xhtml"</literal>. But it's up to
-            the designer of the data-model if what meaning these
-            metainformations have, and if they are used at all. The way of
-            retrieving the topological and metainformations is described <link
-            linkend="ref_builtins_node">in a later chapter</link> (that you
-            don't have to understand at this point).</para>
-          </section>
-
-          <section xml:id="dgui_datamodel_markupoutput">
-            <title>Markup output</title>
-
-            <indexterm>
-              <primary>markup output</primary>
-
-              <secondary>the FTL value type</secondary>
-            </indexterm>
-
-            <para>This type is related to <link
-            linkend="dgui_misc_autoescaping">auto-escaping mechanism</link>
-            introduced FreeMarker 2.3.24; you can <link
-            linkend="dgui_misc_autoescaping_movalues">read about this type
-            there</link>. But in short, this is a value that stores text
-            that's already in the output markup format (like HTML, XML, RTF,
-            etc.), and hence must not be auto-escaped.</para>
-
-            <para>Values of this type are usually produced inside the
-            templates (like with <link
-            linkend="ref_builtin_no_esc"><literal>no_esc</literal>
-            built-in</link> or <link linkend="ref_directive_assign">output
-            capturing assignments</link>), but can also be part of the
-            data-model. Such values in the data-model are useful for example
-            if you have message resources that sometimes contain the message
-            in HTML format, rather than in plain text. If the data-model uses
-            HTML markup output values for those messages instead of strings,
-            then the template author need not know which messages contain HTML
-            and which plain text, as double escaping will be avoided
-            automatically when the message is inserted with
-            <literal>${<replaceable>...</replaceable>}</literal>.</para>
-          </section>
-        </section>
-      </section>
-    </chapter>
-
-    <chapter xml:id="dgui_template">
-      <title>The Template</title>
-
-      <indexterm>
-        <primary>template</primary>
-      </indexterm>
-
-      <note>
-        <para>It is assumed that you have already read the <xref
-        linkend="dgui_quickstart"/> and the <xref linkend="dgui_datamodel"/>
-        chapter.</para>
-      </note>
-
-      <section xml:id="dgui_template_overallstructure">
-        <title>Overall structure</title>
-
-        <para>Templates are in fact programs you write in a language called
-        <indexterm>
-            <primary>FTL</primary>
-          </indexterm><emphasis role="term">FTL</emphasis> (for FreeMarker
-        Template Language). This is a quite simple programming language
-        designed for writing templates and nothing else.</para>
-
-        <para>A template (= FTL program) is a mix of the following
-        sections:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para><emphasis role="term">Text</emphasis><indexterm>
-                <primary>text</primary>
-              </indexterm>: Text that will be printed to the output as
-            is.</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="term">Interpolation</emphasis><indexterm>
-                <primary>interpolation</primary>
-              </indexterm>: These sections will be replaced with a calculated
-            value in the output. Interpolations are delimited by
-            <literal>${</literal> and <literal>}</literal> (or with
-            <literal>#{</literal> and <literal>}</literal>, but that shouldn't
-            be used anymore; <link
-            linkend="ref_depr_numerical_interpolation">see more
-            here</link>).</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="term">FTL tags</emphasis><indexterm>
-                <primary>FTL tag</primary>
-              </indexterm>: FTL tags are a bit similar to HTML tags, but they
-            are instructions to FreeMarker and will not be printed to the
-            output.</para>
-          </listitem>
-
-          <listitem>
-            <para><emphasis role="term">Comments</emphasis><indexterm>
-                <primary>comment</primary>
-              </indexterm><indexterm>
-                <primary>&lt;#--...--&gt;</primary>
-              </indexterm><indexterm>
-                <primary>#</primary>
-              </indexterm>: Comments are similar to HTML comments, but they
-            are delimited by <literal>&lt;#--</literal> and
-            <literal>--&gt;</literal>. Comments will be ignored by FreeMarker,
-            and will not be written to the output.</para>
-          </listitem>
-        </itemizedlist>
-
-        <para>Let's see a concrete template. I have marked the template's
-        components with colors: <phrase role="markedText">text</phrase>,
-        <phrase role="markedInterpolation">interpolation</phrase>, <phrase
-        role="markedFTLTag">FTL tag</phrase>, <phrase
-        role="markedComment">comment</phrase>. With the <phrase
-        role="markedInvisibleText">[BR]</phrase>-s I intend to visualize the
-        <link linkend="gloss.lineBreak">line breaks</link>.</para>
-
-        <programlisting role="template"><phrase role="markedText">&lt;html&gt;<phrase
-              role="markedInvisibleText">[BR]</phrase>
-&lt;head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-  &lt;title&gt;Welcome!&lt;/title&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-&lt;/head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-&lt;body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-  <phrase role="markedComment">&lt;#-- Greet the user with his/her name --&gt;</phrase><phrase
-              role="markedInvisibleText">[BR]</phrase>
-  &lt;h1&gt;Welcome <phrase role="markedInterpolation">${user}</phrase>!&lt;/h1&gt;<phrase
-              role="markedInvisibleText">[BR]</phrase>
-  &lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
-  &lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-  <phrase role="markedFTLTag">&lt;#list animals as animal&gt;</phrase><phrase
-              role="markedInvisibleText">[BR]</phrase>
-    &lt;li&gt;<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
-              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
-              role="markedInvisibleText">[BR]</phrase>
-  <phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
-              role="markedInvisibleText">[BR]</phrase>
-  &lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-&lt;/body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-&lt;/html&gt;</phrase></programlisting>
-
-        <para>FTL distinguishes upper case and lower case letters. So
-        <literal>list</literal> is good directive name, while
-        <literal>List</literal> is not. Similarly <literal>${name}</literal>
-        is not the same as <literal>${Name}</literal> or
-        <literal>${NAME}</literal></para>
-
-        <para>It is important to realize that <phrase
-        role="markedInterpolation">interpolations</phrase> can be used in
-        <phrase role="markedText">text</phrase> (and in string literal
-        expressions; see <link
-        linkend="dgui_template_exp_stringop_interpolation">later</link>)
-        only.</para>
-
-        <para>An <phrase role="markedFTLTag">FTL tag</phrase> can't be inside
-        another <phrase role="markedFTLTag">FTL tag</phrase> nor inside an
-        <phrase role="markedInterpolation">interpolation</phrase>. For example
-        this is <emphasis>WRONG</emphasis>: <literal>&lt;#if &lt;#include
-        'foo'&gt;='bar'&gt;...&lt;/#if&gt;</literal></para>
-
-        <para><phrase role="markedComment">Comments</phrase> can be placed
-        inside <phrase role="markedFTLTag">FTL tags</phrase> and <phrase
-        role="markedInterpolation">interpolations</phrase>. For
-        example:</para>
-
-        <programlisting role="template"><phrase role="markedText">&lt;h1&gt;Welcome <phrase
-              role="markedInterpolation">${user <phrase role="markedComment">&lt;#-- The name of user --&gt;</phrase>}</phrase>!&lt;/h1&gt;<phrase
-              role="markedInvisibleText">[BR]</phrase>
-&lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
-&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
-<phrase role="markedFTLTag">&lt;#list <phrase role="markedComment">&lt;#-- some comment... --&gt;</phrase> animals as <phrase
-                role="markedComment">&lt;#-- again... --&gt;</phrase> animal&gt;</phrase><phrase
-              role="markedInvisibleText">[BR]</phrase></phrase>
-<replaceable>...</replaceable></programlisting>
-
-        <note>
-          <para>For those of you who have tried the above examples: You may
-          notice that some of spaces, tabs and line breaks are missing from
-          the template output, even though we said that <phrase
-          role="markedText">text</phrase> is printed as is. Don't bother with
-          it now. This is because the feature called ''white-space stripping''
-          is turned on, and that automatically removes some superfluous
-          spaces, tabs and line breaks. This will be explained <link
-          linkend="dgui_misc_whitespace">later</link>.</para>
-        </note>
-      </section>
-
-      <section xml:id="dgui_template_directives">
-        <title>Directives</title>
-
-        <indexterm>
-          <primary>&lt;#...&gt;</primary>
-        </indexterm>
-
-        <indexterm>
-          <primary>#</primary>
-        </indexterm>
-
-        <anchor xml:id="term.designer.directive"/>
-
-        <remark>Note that the Expressions chapter depends on this chapter, and
-        Interpolations chapter depends on Expressions chapter. Thus Directives
-        must be the first chapter after Basics.</remark>
-
-        <para><indexterm>
-            <primary>directive</primary>
-          </indexterm>You use FTL tags to call <emphasis
-        role="term">directives</emphasis>. In the example you have called the
-        <literal>list</literal> directive. Syntactically you have done it with
-        two tags: <literal>&lt;#list animals as animal&gt;</literal> and
-        <literal>&lt;/#list&gt;</literal>.</para>
-
-        <para><indexterm>
-            <primary>FTL tag</primary>
-          </indexterm>There are two kind of FTL tags:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para>Start-tag:
-            <literal>&lt;#<replaceable>directivename</replaceable>
-            <replaceable>parameters</replaceable>&gt;</literal></para>
-          </listitem>
-
-          <listitem>
-            <para>End-tag:
-            <literal>&lt;/#<replaceable>directivename</replaceable>&gt;</literal></para>
-          </listitem>
-        </itemizedlist>
-
-        <para>This is similar to HTML or XML syntax, except that the tag name
-        starts with <literal>#</literal>. If the directive doesn't have nested
-        content (content between the start-tag and the end-tag), you must use
-        the start-tag with no end-tag. For example you write <literal>&lt;#if
-        <replaceable>something</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>,
-        but just <literal>&lt;#include
-        <replaceable>something</replaceable>&gt;</literal> as FreeMarker knows
-        that the <literal>include</literal> directive can't have nested
-        content.</para>
-
-        <para>The format of the
-        <literal><replaceable>parameters</replaceable></literal> depends on
-        the
-        <literal><replaceable>directivename</replaceable></literal>.</para>
-
-        <para>In fact there are two types of directives: <link
-        linkend="gloss.predefinedDirective">predefined directives</link> and
-        <link linkend="gloss.userDefinedDirective">user-defined
-        directives</link>. For user-defined directives you use
-        <literal>@</literal> instead of <literal>#</literal>, for example
-        <literal>&lt;@mydirective
-        <replaceable>parameters</replaceable>&gt;<replaceable>...</replaceable>&lt;/@mydirective&gt;</literal>.
-        Further difference is that if the directive has no nested content, you
-        must use a tag like <literal>&lt;@mydirective
-        <replaceable>parameters</replaceable> /&gt;</literal>, similarly as in
-        XML (e.g. <literal>&lt;img <replaceable>...</replaceable>
-        /&gt;</literal>). But user-defined directives is an advanced topic
-        that will be discussed <link
-        linkend="dgui_misc_userdefdir">later</link>.</para>
-
-        <para>FTL tags, like HTML tags, must be properly nested. So the code
-        below is wrong, as the <literal>if</literal> directive is both inside
-        and outside of the nested content of the <literal>list</literal>
-        directive:</para>
-
-        <programlisting role="template">&lt;ul&gt;
-<emphasis>&lt;#list animals as animal&gt;</emphasis>
-  &lt;li&gt;${animal.name} for ${animal.price} Euros
-  <emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>
-     (except for you)
-<emphasis>&lt;/#list&gt;</emphasis> &lt;#-- WRONG! The "if" has to be closed first. --&gt;
-<emphasis>&lt;/#if&gt;</emphasis>
-&lt;/ul&gt;</programlisting>
-
-        <para>Note that FreeMarker doesn't care about the nesting of HTML
-        tags, only about the nesting of FTL tags. It just sees HTML as flat
-        text, it doesn't interpret it in any way.</para>
-
-        <para>If you try to use a non-existing directive (e.g., you mistype
-        the directive name), FreeMarker will decline to use the template and
-        produce an error message.</para>
-
-        <para>FreeMarker ignores superfluous <link
-        linkend="gloss.whiteSpace">white-space</link> inside FTL tags. So you
-        can write this:</para>
-
-        <programlisting role="template"><phrase role="markedText"><phrase
-              role="markedFTLTag">&lt;#list<phrase role="markedInvisibleText">[BR]</phrase>
-  animals       as<phrase role="markedInvisibleText">[BR]</phrase>
-     animal<phrase role="markedInvisibleText">[BR]</phrase>
-&gt;</phrase><phrase role="markedInvisibleText">[BR]</phrase>
-<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
-              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
-              role="markedInvisibleText">[BR]</phrase>
-<phrase role="markedFTLTag">&lt;/#list    &gt;</phrase></phrase></programlisting>
-
-        <para>You may not, however, insert white-space between the
-        <literal>&lt;</literal> or <literal>&lt;/</literal> and the directive
-        name.</para>
-
-        <para>The complete list and description of all directives can be found
-        in the <xref linkend="ref_directives"/> (but I recommend that you look
-        at the chapter about expressions first).</para>
-
-        <note>
-          <para>FreeMarker can be configured to use <literal>[</literal> and
-          <literal>]</literal> instead of <literal>&lt;</literal> and
-          <literal>&gt;</literal> in the FTL tags and FTL comments, like
-          <literal>[#if user == "Big
-          Joe"]<replaceable>...</replaceable>[/#if]</literal>. For more
-          information read: <xref
-          linkend="dgui_misc_alternativesyntax"/>.</para>
-        </note>
-
-        <note>
-          <para>FreeMarker can be configured so that it understands predefined
-          directives without <literal>#</literal> (like <literal>&lt;if user
-          == "Big
-          Joe"&gt;<replaceable>...</replaceable>&lt;/if&gt;</literal>).
-          However we don't recommend the usage of this mode. For more
-          information read: <xref linkend="ref_depr_oldsyntax"/></para>
-        </note>
-      </section>
-
-      <section xml:id="dgui_template_exp">
-        <title>Expressions</title>
-
-        <para><indexterm>
-            <primary>expression</primary>
-          </indexterm>When you supply values for interpolations or directive
-        parameters you can use variables or more complex expressions. For
-        example, if x is the number 8 and y is 5, the value of <literal>(x +
-        y)/2</literal> resolves to the numerical value 6.5.</para>
-
-        <para>Before we go into details, let's see some concrete
-        examples:</para>
-
-        <itemizedlist>
-          <listitem>
-            <para>When you supply value for interpolations: The usage of
-            interpolations is
-            <literal>${<replaceable>expression</replaceable>}</literal> where
-            expression gives the value you want to insert into the output as
-            text. So <literal>${(5 + 8)/2}</literal> prints ``6.5'' to the
-            output (or possibly ``6,5'' if the language of your output is not
-            US English).</para>
-          </listitem>
-
-          <listitem>
-            <para>When you supply a value for the directive parameter: You
-            have already seen the <literal>if</literal> directive in the
-            Getting Started section. The syntax of this directive is:
-            <literal>&lt;#if
-            <replaceable>expression</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>.
-            The expression here must evaluate to a boolean value. For example
-            in <literal>&lt;#if 2 &lt; 3&gt;</literal> the <literal>2 &lt;
-            3</literal> (2 is less than 3) is an expression which evaluates to
-            <literal>true</literal>.</para>
-          </listitem>
-        </itemizedlist>
-
-        <section xml:id="exp_cheatsheet">
-          <title>Quick overview (cheat sheet)</title>
-
-          <para>This is a reminder for those of you who already know
-          FreeMarker or are just experienced programmers:</para>
-
-          <itemizedlist spacing="compact">
-            <listitem>
-              <para><link linkend="dgui_template_exp_direct">Specify values
-              directly</link></para>
-
-              <itemizedlist spacing="compact">
-                <listitem>
-                  <para><link
-                  linkend="dgui_template_exp_direct_string">Strings</link>:
-                  <literal>"Foo"</literal> or <literal>'Foo'</literal> or
-                  <literal>"It's \"quoted\""</literal> or <literal>'It\'s
-                  "quoted"'</literal> or
-                  <literal>r"C:\raw\string"</literal></para>
-                </listitem>
-
-                <listitem>
-                  <para><link
-                  linkend="dgui_template_exp_dir

<TRUNCATED>


[11/35] incubator-freemarker git commit: (Missing version history entry)

Posted by dd...@apache.org.
(Missing version history entry)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/2944148e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/2944148e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/2944148e

Branch: refs/heads/2.3
Commit: 2944148e0d0b16e2056cd4833e2cf64ad2deb739
Parents: 7b0a1c4
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 18:20:39 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 18:20:39 2015 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2944148e/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index b997455..295f043 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26579,6 +26579,12 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <literal>BigDecimal</literal> and <literal>bi</literal> for
                   <literal>BigInteger</literal>.</para>
                 </listitem>
+
+                <listitem>
+                  <para>Public static fields can be referred, like
+                  <literal>com.example.MyClass.MY_CONSTANT</literal> or
+                  <literal>Configuration.AUTO_DETECT_TAG_SYNTAX</literal>.</para>
+                </listitem>
               </itemizedlist>
             </listitem>
           </itemizedlist>


[09/35] incubator-freemarker git commit: Output format and escaping related typos and minor adjustments in JavaDoc and Manual

Posted by dd...@apache.org.
Output format and escaping related typos and minor adjustments in JavaDoc and Manual


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/aa53f15d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/aa53f15d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/aa53f15d

Branch: refs/heads/2.3
Commit: aa53f15d3df1440a4f1349796e1082b33950913d
Parents: d5c2d14
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 21 17:50:41 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 21 17:50:41 2015 +0100

----------------------------------------------------------------------
 .../freemarker/core/MarkupOutputFormat.java     | 26 ++++---
 src/main/java/freemarker/core/OutputFormat.java | 35 +++++----
 .../freemarker/core/TemplateConfiguration.java  |  4 +-
 .../core/TemplateMarkupOutputModel.java         | 15 ++--
 .../java/freemarker/template/Configuration.java | 37 +++++-----
 src/manual/en_US/book.xml                       | 75 ++++++++++----------
 6 files changed, 104 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa53f15d/src/main/java/freemarker/core/MarkupOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/MarkupOutputFormat.java b/src/main/java/freemarker/core/MarkupOutputFormat.java
index 784c8e5..0f1302c 100644
--- a/src/main/java/freemarker/core/MarkupOutputFormat.java
+++ b/src/main/java/freemarker/core/MarkupOutputFormat.java
@@ -25,8 +25,12 @@ import freemarker.template.TemplateModelException;
 
 /**
  * An {@link OutputFormat}-s that represent a "markup", which is any format where certain character sequences have
- * special meaning and thus may need escaping. Escaping is important for FreeMarker, as typically it has to insert
- * non-markup data from the data-model.
+ * special meaning and thus may need escaping. (Escaping is important for FreeMarker, as typically it has to insert
+ * non-markup text from the data-model into the output markup.) This class, among others, defines the operations related
+ * to {@link TemplateMarkupOutputModel}-s that belong to the output format.
+ * 
+ * @param <MO>
+ *            The {@link TemplateMarkupOutputModel} class this output format can deal with.
  * 
  * @since 2.3.24
  */
@@ -47,7 +51,7 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
     public abstract MO fromPlainTextByEscaping(String textToEsc) throws TemplateModelException;
 
     /**
-     * Wraps {@link String} that's already markup to {@link TemplateMarkupOutputModel} interface, to indicate its
+     * Wraps a {@link String} that's already markup to {@link TemplateMarkupOutputModel} interface, to indicate its
      * format. This corresponds to {@code ?noEsc}. (This methods is allowed to throw {@link TemplateModelException} if
      * the parameter markup text is malformed, but it's unlikely that an implementation chooses to parse the parameter
      * until, and if ever, that becomes necessary.)
@@ -63,14 +67,15 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
 
     /**
      * Equivalent to calling {@link #fromPlainTextByEscaping(String)} and then
-     * {@link #output(TemplateMarkupOutputModel, Writer)}, but implementators should chose a more efficient way.
+     * {@link #output(TemplateMarkupOutputModel, Writer)}, but the implementation may uses a more efficient solution.
      */
     public abstract void output(String textToEsc, Writer out) throws IOException, TemplateModelException;
     
     /**
      * If this {@link TemplateMarkupOutputModel} was created with {@link #fromPlainTextByEscaping(String)}, it returns
-     * the original plain text, otherwise it might returns {@code null}. Used when converting between different type of
-     * markups and the source was made from plain text.
+     * the original plain text, otherwise it returns {@code null}. Useful for converting between different types
+     * of markups, as if the source format can be converted to plain text without loss, then that just has to be
+     * re-escaped with the target format to do the conversion.
      */
     public abstract String getSourcePlainText(MO mo) throws TemplateModelException;
 
@@ -78,7 +83,7 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
      * Returns the content as markup text; never {@code null}. If this {@link TemplateMarkupOutputModel} was created
      * with {@link #fromMarkup(String)}, it might returns the original markup text literally, but this is not required
      * as far as the returned markup means the same. If this {@link TemplateMarkupOutputModel} wasn't created
-     * with {@link #fromMarkup(String)} and it doesn't yet have to markup, it has to generate the markup now.
+     * with {@link #fromMarkup(String)} and it doesn't yet have the markup, it has to generate the markup now.
      */
     public abstract String getMarkupString(MO mo) throws TemplateModelException;
     
@@ -90,12 +95,12 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
     
     /**
      * Should give the same result as {@link #fromPlainTextByEscaping(String)} and then
-     * {@link #getMarkupString(TemplateMarkupOutputModel)}, but the implementation may uses a more efficient approach.
+     * {@link #getMarkupString(TemplateMarkupOutputModel)}, but the implementation may uses a more efficient solution.
      */
     public abstract String escapePlainText(String plainTextContent) throws TemplateModelException;
 
     /**
-     * Returns if the markup is empty (0 length). This is used be at least {@code ?hasContent}.
+     * Returns if the markup is empty (0 length). This is used by at least {@code ?hasContent}.
      */
     public abstract boolean isEmpty(MO mo) throws TemplateModelException;
     
@@ -107,7 +112,8 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
     public abstract boolean isLegacyBuiltInBypassed(String builtInName) throws TemplateModelException;
     
     /**
-     * Usually {@code true}; tells if by default auto-escaping should be on for this format. 
+     * Tells if by default auto-escaping should be on for this format. It should be {@code true} if you need to escape
+     * on most of the places where you insert values. 
      */
     public abstract boolean isAutoEscapedByDefault();
     

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa53f15d/src/main/java/freemarker/core/OutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/OutputFormat.java b/src/main/java/freemarker/core/OutputFormat.java
index 05495ca..72ea821 100644
--- a/src/main/java/freemarker/core/OutputFormat.java
+++ b/src/main/java/freemarker/core/OutputFormat.java
@@ -18,39 +18,44 @@
  */
 package freemarker.core;
 
+import freemarker.template.Configuration;
 import freemarker.template.utility.ClassUtil;
 import freemarker.template.utility.StringUtil;
 
 /**
- * Encapsulates the {@link TemplateMarkupOutputModel} factories and {@code TemplateOutputModel} operations, and other
- * meta information (like MIME type) about a certain output format.
+ * Represents an output format.
+ * 
+ * @see Configuration#setOutputFormat(OutputFormat)
+ * @see Configuration#setRegisteredCustomOutputFormats(java.util.Collection)
+ * @see MarkupOutputFormat
  * 
  * @since 2.3.24
  */
 public abstract class OutputFormat {
 
     /**
-     * The short name we used to refer to this format (like in the {@code #ftl} header).
+     * The short name used to refer to this format (like in the {@code #ftl} header).
      */
     public abstract String getName();
     
     /**
-     * Returns the MIME type of the output format. This might comes handy when generating generating a HTTP response.
-     * {@code null} if the output format doesn't clearly corresponds to a specific MIME type.
+     * Returns the MIME type of the output format. This might comes handy when generating a HTTP response. {@code null}
+     * if this output format doesn't clearly corresponds to a specific MIME type.
      */
     public abstract String getMimeType();
 
     /**
-     * Tells if this output format allows inserting {@link TemplateMarkupOutputModel}-s of another output formats into it. If
-     * {@code true}, the foreign {@link TemplateMarkupOutputModel} will be inserted into the output as is (like if the
-     * surrounding output format was the same). This is usually a bad idea, as such an even could indicate application
-     * bugs. If this method returns {@code false} (recommended), then FreeMarker will try to assimilate the inserted
-     * value by converting its format to this format, which will currently (2.3.24) cause exception, unless the inserted
-     * value is made by escaping plain text and the target format is not escaping, in which case format conversion is
-     * trivially possible. (It's not impossible to extending conversions beyond this, if there will be real world demand
-     * for it.)
+     * Tells if this output format allows inserting {@link TemplateMarkupOutputModel}-s of another output formats into
+     * it. If {@code true}, the foreign {@link TemplateMarkupOutputModel} will be inserted into the output as is (like
+     * if the surrounding output format was the same). This is usually a bad idea allow, as such an event could indicate
+     * application bugs. If this method returns {@code false} (recommended), then FreeMarker will try to assimilate the
+     * inserted value by converting its format to this format, which will currently (2.3.24) cause exception, unless the
+     * inserted value is made by escaping plain text and the target format is non-escaping, in which case format
+     * conversion is trivially possible. (It's not impossible that conversions will be extended beyond this, if there
+     * will be demand for that.)
      * 
-     * <p>{@code true} value is used by {@link UndefinedOutputFormat}.
+     * <p>
+     * {@code true} value is used by {@link UndefinedOutputFormat}.
      */
     public abstract boolean isOutputFormatMixingAllowed();
 
@@ -70,7 +75,7 @@ public abstract class OutputFormat {
     
     /**
      * Should be like {@code "foo=\"something\", bar=123"}; this will be inserted inside the parentheses in
-     * {@link #toString()}. 
+     * {@link #toString()}. Shouldn't return {@code null}; should return {@code ""} if there are no extra properties.  
      */
     protected String toStringExtraProperties() {
         return "";

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa53f15d/src/main/java/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateConfiguration.java b/src/main/java/freemarker/core/TemplateConfiguration.java
index 310028f..2c89d01 100644
--- a/src/main/java/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/freemarker/core/TemplateConfiguration.java
@@ -114,8 +114,8 @@ public final class TemplateConfiguration extends Configurable implements ParserC
         if (((Configuration) cfg).getIncompatibleImprovements().intValue() < _TemplateAPI.VERSION_INT_2_3_22
                 && hasAnyConfigurableSet()) {
             throw new IllegalStateException(
-                    "This TemplateConfiguration can't be associated to a Configuration that has incompatibleImprovements "
-                    + "less than 2.3.22, because it changes non-parser settings.");
+                    "This TemplateConfiguration can't be associated to a Configuration that has "
+                    + "incompatibleImprovements less than 2.3.22, because it changes non-parser settings.");
         }
         
         super.setParent(cfg);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa53f15d/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateMarkupOutputModel.java b/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
index 4713f5b..3606379 100644
--- a/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
+++ b/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
@@ -26,14 +26,15 @@ import freemarker.template.TemplateScalarModel;
  * "markup output" template language data-type; stores markup (some kind of "rich text" / structured format, as opposed
  * to plain text) that meant to be printed as template output. Each implementation of this type has a
  * {@link OutputFormat} subclass pair (like {@link TemplateHTMLOutputModel} has {@link HTMLOutputFormat}). This type is
- * related to the {@link Configuration#setOutputFormat(OutputFormat)} and {@link Configuration#setAutoEscapingPolicy(int)}
- * mechanism; see more there. Values of this type are exempt from automatic escaping with that mechanism.
+ * related to the {@link Configuration#setOutputFormat(OutputFormat)} and
+ * {@link Configuration#setAutoEscapingPolicy(int)} mechanism; see more there. Values of this type are exempt from
+ * automatic escaping with that mechanism.
  * 
- * <p>Note that {@link TemplateMarkupOutputModel}-s are by design not handled like {@link TemplateScalarModel}-s,
- * and so the implementations of this interface usually shouldn't implement {@link TemplateScalarModel}. (Because,
- * operations applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.)
- * The template author should make conscious decision of passing in the markup as String by using
- * {@code ?markup_string}.
+ * <p>
+ * Note that {@link TemplateMarkupOutputModel}-s are by design not handled like {@link TemplateScalarModel}-s, and so
+ * the implementations of this interface usually shouldn't implement {@link TemplateScalarModel}. (Because, operations
+ * applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.) The template
+ * author should make conscious decision of passing in the markup as String by using {@code ?markup_string}.
  * 
  * @param <MO>
  *            Refers to the interface's own type, which is useful in interfaces that extend

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa53f15d/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 0e67121..4199458 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -1794,13 +1794,13 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     /**
      * Sets the (default) output format. Usually, you leave this on its default, which is
      * {@link UndefinedOutputFormat#INSTANCE}, and then override it for individual templates based on their name (like
-     * based on their "file" extension) with {@link #setTemplateConfigurations(TemplateConfigurationFactory)}. This setting is
-     * also overridden by the standard file extensions; see them at
+     * based on their "file" extension) with {@link #setTemplateConfigurations(TemplateConfigurationFactory)}. This
+     * setting is also overridden by the standard file extensions; see them at
      * {@link #setRecognizeStandardFileExtensions(boolean)}.
      * 
      * <p>
-     * The output format is mostly important because of auto-escaping (see {@link #setAutoEscapingPolicy(int)}), but maybe
-     * also used by the embedding application to set the HTTP response MIME type, etc.
+     * The output format is mostly important because of auto-escaping (see {@link #setAutoEscapingPolicy(int)}), but
+     * maybe also used by the embedding application to set the HTTP response MIME type, etc.
      * 
      * @see #setRegisteredCustomOutputFormats(Collection)
      * @see #setTemplateConfigurations(TemplateConfigurationFactory)
@@ -1854,19 +1854,23 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
     
     /**
-     * Returns the output format for a name (not {@code null}).
+     * Returns the output format for a name.
      * 
-     * <p>
-     * The name can also refer to a combined format that's created ad-hoc from the registered formats. For example, if
-     * you need RTF embedded into HTML, the name will be <code>HTML{RTF}</code>, where "HTML" and "RTF" refer to the
-     * existing formats. This logic can be used recursively, so for example <code>XML{HTML{RTF}}</code> is also valid.
+     * @param name
+     *            Either the name of the output format as it was registered with
+     *            {@link Configuration#setRegisteredCustomOutputFormats(Collection)}, or a combined output format name.
+     *            A output combined format is created ad-hoc from the registered formats. For example, if you need RTF
+     *            embedded into HTML, the name will be <code>HTML{RTF}</code>, where "HTML" and "RTF" refer to the
+     *            existing formats. This logic can be used recursively, so for example <code>XML{HTML{RTF}}</code> is
+     *            also valid.
+     * 
+     * @return Not {@code null}.
      * 
      * @throws UnregisteredOutputFormatException
      *             If there's no output format registered with the given name.
      * @throws IllegalArgumentException
-     *             If the usage of <code>{</code> and <code>}</code> in the name is syntactically wrong, or if not
-     *             all {@link OutputFormat}-s are {@link MarkupOutputFormat}-s in the <code>...{...}</code>
-     *             expression.
+     *             If the usage of <code>{</code> and <code>}</code> in the name is syntactically wrong, or if not all
+     *             {@link OutputFormat}-s are {@link MarkupOutputFormat}-s in the <code>...{...}</code> expression.
      * 
      * @since 2.3.24
      */
@@ -1882,7 +1886,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
             }
             
             MarkupOutputFormat outerOF = getMarkupOutputFormatForCombined(name.substring(0, openBrcIdx));
-            MarkupOutputFormat innerOF = getMarkupOutputFormatForCombined(name.substring(openBrcIdx + 1, name.length() - 1));
+            MarkupOutputFormat innerOF = getMarkupOutputFormatForCombined(
+                    name.substring(openBrcIdx + 1, name.length() - 1));
             
             return new CombinedMarkupOutputFormat(name, outerOF, innerOF);
         } else {
@@ -1943,8 +1948,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * The default value is an empty collection.
      * 
      * @param registeredCustomOutputFormats
-     *            The collection of the {@link OutputFormat}-s, each must be different and has a unique name within this
-     *            collection.
+     *            The collection of the {@link OutputFormat}-s, each must be different and has a unique name (
+     *            {@link OutputFormat#getName()}) within this collection.
      * 
      * @throws IllegalArgumentException
      *             When multiple different {@link OutputFormat}-s have the same name in the parameter collection. When
@@ -2002,7 +2007,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         }
         this.registeredCustomOutputFormats = Collections.unmodifiableMap(m);
         
-        cache.clear();
+        clearTemplateCache();
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa53f15d/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index ce8137e..acfead4 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -913,9 +913,9 @@ All Rights Reserved.
           extension to activate XML auto-escaping.</para>
 
           <para>You can try if auto-escaping is on like
-          <literal>${"&lt;"}</literal> (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>
+          <literal>${"&lt;"}</literal> and then checking the raw output (for
+          HTML or XML escaping). If it's not, and the configuration won't be
+          adjusted, add this as the very first line of the template:</para>
 
           <programlisting role="template">&lt;#ftl output_format="HTML"&gt;</programlisting>
 
@@ -5282,7 +5282,7 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
           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 leverage for its own purposes.</para>
+          can use for its own purposes.</para>
 
           <para>It's the programmer's responsibility to <link
           linkend="pgui_config_outputformatsautoesc">associate output format
@@ -5318,7 +5318,7 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
                 <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
                 <literal>&amp;#39;</literal></td>
 
-                <td><literal>text/HTML</literal></td>
+                <td><literal>text/html</literal></td>
 
                 <td><literal>HTMLOutputFormat.INSTANCE</literal></td>
               </tr>
@@ -5370,8 +5370,7 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
                 <td><literal>plainText</literal></td>
 
                 <td>Doesn't escape. Doesn't accept markup output values from
-                other output formats. The output format inside string
-                literals.</td>
+                other output formats.</td>
 
                 <td><literal>text/plain</literal></td>
 
@@ -5380,9 +5379,8 @@ jsmith@other.com, jsmith@other.com, jsmith@other.com</programlisting>
             </tbody>
           </informaltable>
 
-          <para>The programmers can extend this with their your own output
-          formats, so this is maybe not all the output formats in your
-          application!</para>
+          <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">
@@ -5412,7 +5410,7 @@ ${"'"}  &lt;#-- Prints: &amp;apos; --&gt;</programlisting>
             output_format="XML" auto_esc=true&gt;</literal> might helps (and
             that means that FreeMarker was configured to use
             <quote>disable</quote> auto-escaping <emphasis>policy</emphasis>,
-            which is usually not recommended).</para>
+            which is generally not recommended).</para>
           </note>
 
           <para>The output format can also be applied to only a section of a
@@ -5431,16 +5429,16 @@ ${"'"}  &lt;#-- Prints: &amp;#39; --&gt;
           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
-          that's 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>
+          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">
@@ -5494,7 +5492,7 @@ ${'&amp;'}  &lt;#-- prints: &amp; --&gt;</programlisting>
 ${'&amp;'}  &lt;#-- prints: &amp; --&gt;
 ${'&amp;'<emphasis>?esc</emphasis>}  &lt;#-- prints: &amp;amp; --&gt;</programlisting>
 
-          <para>Of course, both <literal>autoesc</literal> and
+          <para>Naturally, both <literal>autoesc</literal> and
           <literal>?esc</literal> works inside <literal>noautoesc</literal>
           blocks too.</para>
         </section>
@@ -5502,7 +5500,7 @@ ${'&amp;'<emphasis>?esc</emphasis>}  &lt;#-- prints: &amp;amp; --&gt;</programli
         <section xml:id="dgui_misc_autoescaping_movalues">
           <title><quote>Markup output</quote> values</title>
 
-          <para>In FTL, <link linkend="dgui_datamodel_basics">values has
+          <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
@@ -5524,11 +5522,11 @@ ${'&amp;'<emphasis>?esc</emphasis>}  &lt;#-- prints: &amp;amp; --&gt;</programli
             </listitem>
           </itemizedlist>
 
-          <para>Hence these can be used outside
+          <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 (that so needs escaping) or HTML
-          (that so mustn't be escaped):</para>
+          decide if the message is plain text (hence needs escaping) or HTML
+          (hence it mustn't be escaped):</para>
 
           <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
 
@@ -5559,7 +5557,7 @@ Captured output: ${captured}</programlisting>
           <programlisting role="output">Just a string: &amp;lt;b&amp;gt;Test&amp;lt;/b&amp;gt;
 Captured output: &lt;b&gt;Test&lt;/b&gt;</programlisting>
 
-          <para>Because the captured output is markup output it wasn't
+          <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
@@ -5568,7 +5566,7 @@ Captured output: &lt;b&gt;Test&lt;/b&gt;</programlisting>
           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,
-          and you can get that as
+          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
@@ -5584,7 +5582,7 @@ As expected:
 ${markupOutput1}
 ${markupOutput2}
 
-Double escaping:
+Possibly unintended double escaping:
 ${markupOutput1?markup_string}
 ${markupOutput2?markup_string}</programlisting>
 
@@ -5592,7 +5590,7 @@ ${markupOutput2?markup_string}</programlisting>
 &lt;b&gt;Test&lt;/b&gt;
 Foo &amp;amp; bar
 
-Double escaping:
+Possibly unintended double escaping:
 &amp;lt;b&amp;gt;Test&amp;lt;/b&amp;gt;
 Foo &amp;amp;amp; bar</programlisting>
         </section>
@@ -5667,10 +5665,11 @@ RTF:  Failed</programlisting>
             that, which is the output format used for templates for which no
             output format was specified in the configuration:</para>
 
-            <programlisting role="template">&lt;#outputformat "HTML"&gt;&lt;#assign htmlMO&gt;&lt;p&gt;Test&lt;/#assign&gt;&lt;/#outputformat&gt;
+            <programlisting role="template">&lt;#-- We assume that we have "undefined" output format here. --&gt;
+
+&lt;#outputformat "HTML"&gt;&lt;#assign htmlMO&gt;&lt;p&gt;Test&lt;/#assign&gt;&lt;/#outputformat&gt;
 &lt;#outputformat "XML"&gt;&lt;#assign xmlMO&gt;&lt;p&gt;Test&lt;/p&gt;&lt;/#assign&gt;&lt;/#outputformat&gt;
 &lt;#outputformat "RTF"&gt;&lt;#assign rtfMO&gt;\par Test&lt;/#assign&gt;&lt;/#outputformat&gt;
-&lt;#-- We assume that we have "undefined" output format here. --&gt;
 HTML: ${htmlMO}
 XML:  ${xmlMO}
 RTF:  ${rtfMO}</programlisting>
@@ -5692,7 +5691,7 @@ RTF:  \par Test</programlisting>
             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 value. Example:</para>
+            concatenated to form a new markup output value. Example:</para>
 
             <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
 ${"&lt;h1&gt;"?no_esc + "Foo &amp; bar" + "&lt;/h1&gt;"?no_esc}</programlisting>
@@ -5703,8 +5702,8 @@ ${"&lt;h1&gt;"?no_esc + "Foo &amp; bar" + "&lt;/h1&gt;"?no_esc}</programlisting>
             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 wasn't possible either, that's
-            an error. (See the <link
+            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>
@@ -5717,8 +5716,8 @@ ${"&lt;h1&gt;"?no_esc + "Foo &amp; bar" + "&lt;/h1&gt;"?no_esc}</programlisting>
             <literal>&lt;#assign s = "Hello ${name}!"&gt;</literal>), it's
             just a shorthand of using the <literal>+</literal> operator
             (<literal>&lt;#assign s = "Hello" + name + "!"&gt;</literal>).
-            Thus, <literal>${<replaceable>...</replaceable>}</literal> inside
-            string expressions isn't auto-escaped.</para>
+            Thus, <literal>${<replaceable>...</replaceable>}</literal>-s
+            inside string expressions aren't auto-escaped.</para>
 
             <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
 &lt;#assign name = "Foo &amp; Bar"&gt;
@@ -5733,7 +5732,7 @@ ${s?replace('&amp;'), 'and'}</programlisting>
             <programlisting role="output">&amp;lt;p&amp;gt;Hello Foo &amp;amp; Bar!
 &lt;p&gt;Hello Foo &amp;amp; Bar!
 
-To prove that s didn't contain the value in escaped form:
+To prove that "s" didn't contain the value in escaped form:
 &amp;lt;p&amp;gt;Hello Foo and Bar!</programlisting>
           </section>