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 2021/10/25 07:36:42 UTC
[freemarker-generator] 01/01: Merge remote-tracking branch
'origin/master' into FREEMARKER-154. Also updated website module and
DocBook content to be compatible with it.
This is an automated email from the ASF dual-hosted git repository.
ddekany pushed a commit to branch FREEMARKER-154
in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git
commit 56bc016d7cd375cabfd1e9b7cea0be7fb8e245ef
Merge: 7a6e620 20d7f13
Author: ddekany <dd...@apache.org>
AuthorDate: Mon Oct 25 00:42:45 2021 +0200
Merge remote-tracking branch 'origin/master' into FREEMARKER-154. Also updated website module and DocBook content to be compatible with it.
freemarker-generator-base/pom.xml | 2 +-
.../generator/base/FreeMarkerConstants.java | 9 ++
.../base/activation/CachingUrlDataSource.java | 1 +
.../generator/base/datasource/DataSource.java | 138 ++++++++++++++++++---
.../base/datasource/DataSourceFactory.java | 18 ++-
.../base/datasource/DataSourceLoader.java | 2 +-
.../base/datasource/DataSourceLoaderFactory.java | 21 ++--
.../generator/base/datasource/DataSources.java | 118 ++++++++++++++----
.../base/datasource/DataSourcesSupplier.java | 48 +++++--
.../generator/base/file/RecursiveFileSupplier.java | 24 ++--
.../freemarker/generator/base/mime/Mimetypes.java | 3 +
.../base/mime/MimetypesFileTypeMapFactory.java | 6 +-
.../generator/base/output/OutputGenerator.java | 20 ++-
.../freemarker/generator/base/table/Table.java | 2 +-
.../freemarker/generator/base/util/FileUtils.java | 48 +++++++
.../freemarker/generator/base/util/ListUtils.java | 19 ++-
.../base/util/NonClosableWriterWrapper.java | 2 +-
.../generator/base/util/OperatingSystem.java | 2 +-
.../generator/base/util/PropertiesTransformer.java | 3 +-
.../generator/base/util/StringUtils.java | 8 ++
.../generator/datasource/DataSourceTest.java | 18 ++-
.../generator/datasource/DataSourcesTest.java | 81 ++++++++----
.../freemarker/generator/util/FileUtilsTest.java | 74 +++++++++++
freemarker-generator-cli/CHANGELOG.md | 16 ++-
freemarker-generator-cli/pom.xml | 10 +-
.../src/app/config/freemarker-generator.properties | 1 +
.../src/app/examples/data/ftl/nginx/nginx.conf.ftl | 2 +-
.../src/app/examples/data/nginx/test1-api.nginx | 30 +++++
.../examples/data/nginx/test1-application.nginx | 27 ++++
.../utahparser/juniper_bgp_summary_example.txt | 12 ++
.../utahparser/juniper_bgp_summary_template.xml | 83 +++++++++++++
.../templates/accesslog/combined-access.ftl | 2 +-
.../templates/csv/csv/gatling-user-credentials.ftl | 2 +-
.../app/examples/templates/csv/fo/transactions.ftl | 2 +-
.../app/examples/templates/csv/fo/transform.ftl | 2 +-
.../examples/templates/csv/html/transactions.ftl | 2 +-
.../src/app/examples/templates/csv/md/filter.ftl | 2 +-
.../src/app/examples/templates/csv/shell/curl.ftl | 2 +-
.../app/examples/templates/dataframe/example.ftl | 2 +-
.../examples/templates/dataframe/html/print.ftl | 2 +-
.../src/app/examples/templates/datasources.ftl | 135 ++++++++++++--------
.../src/app/examples/templates/demo.ftl | 10 +-
.../app/examples/templates/excel/csv/custom.ftl | 2 +-
.../templates/excel/dataframe/transform.ftl | 2 +-
.../examples/templates/html/csv/dependencies.ftl | 2 +-
.../app/examples/templates/html/txt/licence.ftl | 2 +-
.../examples/templates/javafaker/csv/testdata.ftl | 2 +-
.../templates/json/csv/swagger-endpoints.ftl | 2 +-
.../templates/json/dataframe/github-users.ftl | 2 +-
.../examples/templates/json/md/github-users.ftl | 2 +-
.../templates/logs/csv/serverlog-to-csv.ftl | 2 +-
.../nginx/confluence/nginx-config-parser.ftl | 34 +++++
.../templates/properties/csv/locker-test-users.ftl | 2 +-
.../app/examples/templates/tsv/fo/transactions.ftl | 2 +-
.../csv/transform.ftl} | 26 ++--
.../templates/utahparser}/json/transform.ftl | 6 +-
.../app/examples/templates/xml/txt/recipients.ftl | 2 +-
.../app/examples/templates/yaml/txt/transform.ftl | 2 +-
.../src/app/scripts/run-examples.bat | 42 ++++++-
.../src/app/scripts/run-examples.sh | 42 ++++++-
.../src/app/templates/freemarker-generator/cat.ftl | 2 +-
.../csv/{md => confluence}/transform.ftl | 7 +-
.../freemarker-generator/csv/csv/transform.ftl | 2 +-
.../freemarker-generator/csv/html/transform.ftl | 2 +-
.../freemarker-generator/csv/md/transform.ftl | 2 +-
.../freemarker-generator/excel/csv/transform.ftl | 2 +-
.../freemarker-generator/excel/html/transform.ftl | 2 +-
.../freemarker-generator/excel/md/transform.ftl | 2 +-
.../app/templates/freemarker-generator/info.ftl | 50 ++++++--
.../freemarker-generator/json/yaml/transform.ftl | 2 +-
.../freemarker-generator/yaml/json/transform.ftl | 2 +-
.../org/apache/freemarker/generator/cli/Main.java | 19 +--
.../cli/config/ConfigurationSupplier.java | 5 +
.../generator/cli/config/DataModelSupplier.java | 12 +-
.../cli/config/OutputGeneratorsSupplier.java | 111 +++--------------
.../freemarker/generator/cli/config/Settings.java | 43 ++++---
.../freemarker/generator/cli/config/Suppliers.java | 4 +-
.../cli/config/output/AbstractOutputGenerator.java | 80 ++++++++++++
.../output/DataSourceSeedingOutputGenerator.java | 112 +++++++++++++++++
.../output/DataSourceSeedingOutputMapper.java | 58 +++++++++
.../TemplateSeedingOutputGenerator.java} | 75 +++--------
.../cli/config/output}/TemplateTransformation.java | 5 +-
.../output}/TemplateTransformationsBuilder.java | 4 +-
.../generator/cli/picocli/DataModelDefinition.java | 7 ++
.../cli/picocli/DataSourceDefinition.java | 7 ++
.../generator/cli/picocli/GitVersionProvider.java | 9 ++
.../cli/picocli/OutputGeneratorDefinition.java | 35 ++++++
...Definition.java => OutputMapperDefinition.java} | 15 +--
...ceDefinition.java => OutputSeedDefinition.java} | 17 ++-
.../cli/picocli/TemplateOutputDefinition.java | 7 ++
.../cli/picocli/TemplateSourceDefinition.java | 8 ++
.../picocli/TemplateSourceFilterDefinition.java | 12 +-
.../generator/cli/task/FreeMarkerTask.java | 41 ++++--
.../generator/cli/util/TemplateSourceFactory.java | 50 ++++++++
.../generator/cli/wrapper/DataSourcesAdapter.java | 115 +++++++++++++++++
.../wrapper/FreeMarkerGeneratorObjectWrapper.java | 31 +++--
.../src/site/markdown/cli/concepts/data-models.md | 2 +-
.../src/site/markdown/cli/concepts/data-sources.md | 54 ++++----
.../src/site/markdown/cli/concepts/named-uris.md | 12 +-
.../site/markdown/cli/concepts/transformation.md | 44 +++++--
.../site/markdown/cli/usage/parsing-with-grok.md | 4 +-
.../site/markdown/cli/usage/running-examples.md | 98 ++++++---------
.../site/markdown/cli/usage/using-dataframes.md | 6 +-
.../src/test/data}/template/application.properties | 0
.../src/test/data}/template/nginx/nginx.conf.ftl | 0
.../freemarker/generator/cli/ExamplesTest.java | 47 ++++++-
.../freemarker/generator/cli/ManualTest.java | 4 +-
.../freemarker/generator/cli/PicocliTest.java | 2 +-
.../cli/config/AbstractOutputGeneratorTest.java | 79 ++++++++++++
.../cli/config/ConfigurationSupplierTest.java | 5 +-
.../generator/cli/config/SuppliersTest.java | 4 +-
.../config/TemplateSeedingOutputGeneratorTest.java | 121 ++++++++++++++++++
.../DataSourceSeedingOutputGeneratorTest.java | 135 ++++++++++++++++++++
.../output/DataSourceSeedingOutputMapperTest.java | 95 ++++++++++++++
.../TemplateTransformationsBuilderTest.java | 9 +-
.../src/test/templates/echo.ftl | 2 +-
.../src/test/templates/manual.ftl | 8 +-
.../src/test/templates/tools/csv.ftl | 2 +-
freemarker-generator-maven-plugin-sample/pom.xml | 2 +-
freemarker-generator-maven-plugin/pom.xml | 2 +-
freemarker-generator-tools/pom.xml | 8 +-
.../generator/tools/commonscsv/CommonsCSVTool.java | 6 +-
.../commonscsv/impl/CommonsCSVPrinterFacade.java | 12 ++
.../tools/dataframe/impl/CSVConverter.java | 2 +-
.../generator/tools/excel/ExcelTool.java | 2 +-
.../freemarker/generator/tools/grok/GrokTool.java | 4 +-
.../generator/tools/system/SystemTool.java | 29 ++++-
.../generator/tools/utahparser/UtahParserTool.java | 100 +++++++++++++++
.../tools/utahparser/impl/ParserWrapper.java | 86 +++++++++++++
.../utahparser/juniper_bgp_summary_example.txt | 12 ++
.../utahparser/juniper_bgp_summary_template.xml | 69 +++++++++++
.../tools/commonsexec/CommonsExecToolTest.java | 26 ++++
.../generator/tools/system/SystemToolTest.java | 8 +-
.../tools/utahparser/UtahParserToolTest.java | 103 +++++++++++++++
freemarker-generator-website/pom.xml | 2 +-
.../src/main/docgen/book.xml | 54 ++++----
.../licence.ftl => licences/LICENCE_utahparser.txt | 90 +-------------
pom.xml | 10 +-
138 files changed, 2753 insertions(+), 751 deletions(-)
diff --cc freemarker-generator-website/pom.xml
index a5cc6ff,0000000..f8424c5
mode 100644,000000..100644
--- a/freemarker-generator-website/pom.xml
+++ b/freemarker-generator-website/pom.xml
@@@ -1,101 -1,0 +1,101 @@@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.freemarker.generator</groupId>
+ <artifactId>freemarker-generator</artifactId>
- <version>0.1.0-SNAPSHOT</version>
++ <version>0.2.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>freemarker-generator-website</artifactId>
+ <name>Website</name>
+ <description>Apache FreeMarker Generator Website</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+
+ <websiteOutputDirectory>${project.build.directory}/website</websiteOutputDirectory>
+ <freemarkerGeneratorAppHome>${project.basedir}/../freemarker-generator-cli/target/appassembler</freemarkerGeneratorAppHome>
+ <docgenInsertedExampleTemplatesDirectory>${freemarkerGeneratorAppHome}/examples/templates</docgenInsertedExampleTemplatesDirectory>
+ <docgenInsertedExampleOutputDirectory>${freemarkerGeneratorAppHome}/target/out</docgenInsertedExampleOutputDirectory>
+ <docgenInsertedTemplatesDirectory>${freemarkerGeneratorAppHome}/templates</docgenInsertedTemplatesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.freemarker.generator</groupId>
+ <artifactId>freemarker-generator-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.freemarker.docgen</groupId>
+ <artifactId>freemarker-docgen-maven</artifactId>
+ <version>0.0.2-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <id>docgen-transform</id>
+ <phase>package</phase>
+ <goals>
+ <goal>transform</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <sourceDirectory>src/main/docgen</sourceDirectory>
+ <outputDirectory>${websiteOutputDirectory}</outputDirectory>
+ <insertableFiles>
+ <templates>${docgenInsertedTemplatesDirectory}/**</templates>
+ <exampleTemplates>${docgenInsertedExampleTemplatesDirectory}/**</exampleTemplates>
+ </insertableFiles>
+ <customVariables>
+ <version>${project.version}</version>
+ <freemarkerGeneratorAppHome>${freemarkerGeneratorAppHome}</freemarkerGeneratorAppHome>
+ </customVariables>
+ <!-- TODO set it back to false before release -->
+ <offline>true</offline>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.freemarker.generator</groupId>
+ <artifactId>freemarker-generator-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <!-- This is need this only when we have freemarker-docgen-maven SNAPSHOT dependency -->
+ <repository>
+ <id>apache-snapshot-repository</id>
+ <url>https://repository.apache.org/content/repositories/snapshots/</url>
+ <releases><enabled>false</enabled></releases>
+ <snapshots><enabled>true</enabled></snapshots>
+ </repository>
+ </repositories>
+</project>
diff --cc freemarker-generator-website/src/main/docgen/book.xml
index 791051c,0000000..0da2433
mode 100644,000000..100644
--- a/freemarker-generator-website/src/main/docgen/book.xml
+++ b/freemarker-generator-website/src/main/docgen/book.xml
@@@ -1,1537 -1,0 +1,1537 @@@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<book conformance="docgen" version="5.0" xml:lang="en"
+ xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns5="http://www.w3.org/1998/Math/MathML"
+ xmlns:ns4="http://www.w3.org/1999/xhtml"
+ xmlns:ns3="http://www.w3.org/2000/svg"
+ xmlns:ns="http://docbook.org/ns/docbook">
+ <info>
+ <title>Apache FreeMarker Generator Manual</title>
+
+ <titleabbrev>FreeMarker Generator Manual</titleabbrev>
+
+ <productname>Apache FreeMarker Generator
+ [docgen.customVariables.version]</productname>
+ </info>
+
+ <chapter role="index.html" xml:id="about">
+ <title>What's FreeMarker Generator?</title>
+
+ <remark>Up until "Quick fasts", this is mostly new content compared to the
+ Markdown version.</remark>
+
+ <warning>
+ <para><emphasis>No backward compatibility is promised!</emphasis>
+ FreeMarker Generator is in early stage of development, and so new
+ versions can break backward compatibility. However, the template engine
+ itself (FreeMarker) keeps backward compatibility, so hopefully the bulk
+ of your work can be still used in a future versions of FreeMarker
+ Generator, should you decide to upgrade it.</para>
+ </warning>
+
+ <para>FreeMarker Generator is a command line tool that generates files
+ based on FreeMarker template files, and data that's typically provided in
+ files (such as JSON files, CSV files, etc.) as well. It can be used to
+ generated source code, configuration files, etc.</para>
+
+ <para>Quick facts:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Requires Java 8+ on Linux, Mac OS X, or Windows</para>
+ </listitem>
+
+ <listitem>
+ <para>Uses stdin, files, and URL-s to load data and templates</para>
+ </listitem>
+
+ <listitem>
+ <para>Reads a variety of structured data formats such as access logs,
+ CSV, Excel, JSON, HTML, YAML, XML</para>
+ </listitem>
+
+ <listitem>
+ <para>Provides JSONPath, XPath and DataFrame-s for advanced data
+ manipulation</para>
+ </listitem>
+
+ <listitem>
+ <para>Can transform a whole directory with a single command-line
+ invocation</para>
+ </listitem>
+
+ <listitem>
+ <para>Made for the heavy lifting of data by using lazy-loading and
+ streaming</para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <para>Currently, FreeMarker Generator can only be invoked via command
+ line interface (CLI). In the future, we might add other interfaces, like
+ a Maven plugin. Actually, there's already a FreeMarker Generator Maven
+ plugin, but that doesn't share code, or concepts with the CLI. In the
+ future, we hope to unite these into a common engine. But for now the
+ Maven plugin is considered to be a legacy artifact. However, it works,
+ and you can use it. But anything you see in this documentation is not
+ applicable there, except this: [TODO copy and link plugin Maven
+ site]</para>
+ </note>
+ </chapter>
+
+ <chapter xml:id="first-steps">
+ <title>First Steps</title>
+
+ <section xml:id="getting-started">
+ <title>Getting Started</title>
+
+ <simplesect>
+ <title>Installation</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>Requires Java 1.8+ on Linux, Mac OS X and Windows</para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="download">Download</link> the binary release
+ of the FreeMarker Generator command line tool. Unpack the archive
+ in a directory of your choice.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the <literal>bin/freemarker-cli</literal> or
+ <literal>bin/freemarker-cli.bat</literal> to your
+ <literal>PATH</literal> variable</para>
+ </listitem>
+ </itemizedlist>
+ </simplesect>
+
+ <simplesect>
+ <title>Verify Installation</title>
+
+ <para>On my local box (Mac OS 10.15.5) I use the following
+ setup:</para>
+
+ <remark>This above have used export FREEMARKER_CLI_HOME=..., but I
+ found that to be confusing, as one my thinks FREEMARKER_CLI_HOME is
+ recognized by the launcher script something (like JAVA_HOME, ANT_HOME,
+ etc).</remark>
+
+ <programlisting>export PATH=$PATH:/Applications/Java/freemarker-generator/bin</programlisting>
+
+ <para>Afterwards Apache FreeMarker Generator can be executed from the
+ command line:</para>
+
+ <programlisting>> which freemarker-generator
+/Applications/Java/freemarker-generator/bin/freemarker-generator</programlisting>
+
+ <para>and check the version of Apache FreeMarker CLI:</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -V
+[/docgen.insertWithOutput]</programlisting>
+ </simplesect>
+
+ <simplesect>
+ <title>Command Line Options</title>
+
+ <para>Apache FreeMarker Generator provides command line help as shown
+ below:</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -h
+[/docgen.insertWithOutput]</programlisting>
+ </simplesect>
+
+ <simplesect>
+ <title>The Info Template</title>
+
+ <para>The distribution ships with a couple of FreeMarker templates and
+ the <literal>templates/freemarker-generator/info.ftl</literal> is
+ particularly helpful to better understand Apache FreeMarker
+ CLI.</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t freemarker-generator/info.ftl
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>Above:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The <quote>FreeMarker Generator Information</quote> section
+ provides insights into configuration and currently processed
+ template.</para>
+ </listitem>
+
+ <listitem>
+ <para>The <quote>FreeMarker Generator Template Loader
+ Directories</quote> shows the template directories being searched
+ to resolve a template path</para>
+ </listitem>
+
+ <listitem>
+ <para>The <quote>FreeMarker Generator Tools</quote> section list
+ the available tools</para>
+ </listitem>
+
+ <listitem>
+ <para>The <quote>FreeMarker Generator Data Model</quote> section
+ shows all available entries in the current FreeMarker
+ context</para>
+ </listitem>
+ </itemizedlist>
+ </simplesect>
+ </section>
+
+ <section xml:id="running-examples">
+ <title>Running the Examples</title>
+
+ <para>There are many examples (see below) available you can execute -
+ The examples were tested with Java 1.8 on Mac OS X.</para>
+
+ <para>Run <literal>run-examples.sh</literal> or
+ <literal>run-examples.bat</literal> in the Apache FreeMarker Generator
+ installation directory, and have a look at the generated output.</para>
+
+ <remark>Removed console output showing list of examples and ls like
+ output from here. I think it doesn't help users, and had to be generated
+ in Maven somehow.</remark>
+
+ <para>Please note that generated PDF files are very likely not found
+ since they require wkhtmltopdf and Apache FOP installation.</para>
+
+ <section>
+ <title>Transforming GitHub JSON To Markdown</title>
+
+ <para>A simple example with real JSON data to be transformed into
+ Markdown.</para>
+
+ <para>You can either use the existing JSON sample</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/json/md/github-users.ftl [docgen.wd]/examples/data/json/github-users.json
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>or pipe a <literal>curl</literal> response</para>
+
+ <programlisting>> curl -s https://api.github.com/users | freemarker-generator -t examples/templates/json/md/github-users.ftl --stdin</programlisting>
+
+ <para>Below you see the Apache FreeMarker Template:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/json/md/github-users.ftl"]</programlisting>
+
+ <para>This creates the following output:</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/examples/github.png" width="100%"/>
+ </imageobject>
+ </mediaobject>
+
+ <remark>Above are real people, so we shouldn't include this.</remark>
+ </section>
+
+ <section>
+ <title>CSV to HTML/Markdown Transformation</title>
+
+ <para>Sometimes you have a CSV file which needs to be translated in
+ Markdown or HTML - there are on-line solutions
+ available<remark>[removed external product link from here]</remark>,
+ but having a local solution gives you more flexibility.</para>
+
+ <programlisting>[docgen.checkCommand]
+freemarker-generator -t freemarker-generator/csv/md/transform.ftl [docgen.wd]/examples/data/csv/contract.csv
+[/docgen.checkCommand]
+[docgen.checkCommand]
+freemarker-generator -t freemarker-generator/csv/html/transform.ftl [docgen.wd]/examples/data/csv/contract.csv
+[/docgen.checkCommand]</programlisting>
+
+ <para>The FreeMarker template is shown below.</para>
+
+ <programlisting role="template">[docgen.insertFile "@templates/freemarker-generator/csv/md/transform.ftl"]</programlisting>
+
+ <para>The resulting file actually looks pleasant when compared to raw
+ CSV</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/examples/contract.png" width="100%"/>
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Transform XML To Plain Text</title>
+
+ <para>Of course you can also transform an XML document:</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/xml/txt/recipients.ftl [docgen.wd]/examples/data/xml/recipients.xml
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>This is using the following template:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/xml/txt/recipients.ftl"]</programlisting>
+ </section>
+
+ <section>
+ <title>Transform JSON To CSV</title>
+
+ <para>One day I was asked a to prepare a CSV files containing REST
+ endpoints described by Swagger - technically this is a JSON to CSV
+ transformation. Of course I could create that CSV manually but writing
+ a FTL template doing that was simply more fun and saves time in the
+ future.</para>
+
+ <remark>Certainly many will find the story telling tone strange.
+ Especially if we assume that others will contribute to this (who's "I"
+ then). We should just state what this is an example of, tersely. This
+ also applies to other parts.</remark>
+
+ <para><remark>Below has no example source code to include. As we don't
+ provide backward compatibility yet, we better stick to runnable
+ examples, or else they will become outdated here.</remark></para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/json/csv/swagger-endpoints.ftl"]</programlisting>
+
+ <para>Invoking the FTL template, and its output:</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/json/csv/swagger-endpoints.ftl [docgen.wd]/examples/data/json/swagger-spec.json
+[/docgen.insertWithOutput]</programlisting>
+ </section>
+
+ <section>
+ <title>Transforming Excel Documents</title>
+
+ <para>Another day my project management asked me to create a CSV
+ configuration file based on an Excel documents - as usual manual
+ copying was not an option due to required data cleanup and data
+ transformation. So I thought about Apache POI which support XLS and
+ XLSX documents - integration of Apache POI was a breeze but the
+ resulting code was not particularly useful example. So a more generic
+ transformation was provided to show the transformation of Excel
+ documents.</para>
+
+ <programlisting>[docgen.checkCommand]
+freemarker-generator -t freemarker-generator/excel/html/transform.ftl [docgen.wd]/examples/data/excel/test.xls
+[/docgen.checkCommand]
+[docgen.checkCommand]
+freemarker-generator -t freemarker-generator/excel/html/transform.ftl [docgen.wd]/examples/data/excel/test.xlsx
+[/docgen.checkCommand]
+[docgen.checkCommand]
+freemarker-generator -t freemarker-generator/excel/html/transform.ftl [docgen.wd]/examples/data/excel/test-multiple-sheets.xlsx
+[/docgen.checkCommand]
+[docgen.checkCommand]
+freemarker-generator -t freemarker-generator/excel/md/transform.ftl [docgen.wd]/examples/data/excel/test-multiple-sheets.xlsx
+[/docgen.checkCommand]</programlisting>
+
+ <para>The provided FTL transforms an Excel into a HTML document
+ supporting multiple Excel sheets:</para>
+
+ <programlisting role="template">[docgen.insertFile "@templates/freemarker-generator/excel/html/transform.ftl"]</programlisting>
+
+ <para>but the result looks reasonable</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/examples/excel-to-html.png"
+ width="100%"/>
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Transform Property Files To CSV</title>
+
+ <para>In this sample we transform all property files found in a
+ directory (recursive search using include pattern) to a CSV
+ file.</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator --data-source-include *.properties -t [docgen.wd]/examples/templates/properties/csv/locker-test-users.ftl [docgen.wd]/examples/data/properties
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>The template it uses is this:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/properties/csv/locker-test-users.ftl"]</programlisting>
+
+ <para>The template uses a couple of interesting features:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>We process a list of property files</para>
+ </listitem>
+
+ <listitem>
+ <para>The <literal>strip_text</literal> and
+ <literal>compress</literal> strips any white-spaces and
+ line-breaks from the output so we can create a proper CSV
+ file</para>
+ </listitem>
+
+ <listitem>
+ <para>We use FTL functions to extract the
+ <literal>tenant</literal> and <literal>site</literal>, e.g.
+ <literal>extractTenant</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>We add a manual line break using
+ <literal>${'\n'}</literal></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Transform CSV To XML-FO</title>
+
+ <para>For a POC (proof of concept) I created a sample transformation
+ from CSV to XML-FO in order to create a PDF document using <link
+ xlink:href="https://xmlgraphics.apache.org/fop">Apache FOP</link>
+ using the following template file:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/csv/fo/transform.ftl"]</programlisting>
+
+ <para>In order to create the PDF you need to execute the following
+ commands (assuming that you have Apache FOP installed):</para>
+
+ <programlisting>[docgen.insertWithOutput]freemarker-generator -t [docgen.wd]/examples/templates/csv/fo/transform.ftl [docgen.wd]/examples/data/csv/locker-test-users.csv[/docgen.insertWithOutput] > sample.fo
+
+> fop -fo sample.fo sample.pdf
+Dec 29, 2018 10:24:30 PM org.apache.fop.events.LoggingEventListener processEvent
+WARNING: Font "Symbol,normal,700" not found. Substituting with "Symbol,normal,400".
+Dec 29, 2018 10:24:30 PM org.apache.fop.events.LoggingEventListener processEvent
+WARNING: Font "ZapfDingbats,normal,700" not found. Substituting with "ZapfDingbats,normal,400".
+Dec 29, 2018 10:24:30 PM org.apache.fop.events.LoggingEventListener processEvent
+INFO: Rendered page #1.</programlisting>
+
+ <para>The result does not look very impressive but it is a PDF
+ :-)</para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/examples/locker-test-users-pdf.png"
+ width="100%"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>Further along the line of the POC we converted a transaction
+ export from CSV to PDF using Apache FOP:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/csv/fo/transactions.ftl"]</programlisting>
+
+ <programlisting>[docgen.insertWithOutput]freemarker-generator -t [docgen.wd]/examples/templates/csv/fo/transactions.ftl [docgen.wd]/examples/data/csv/transactions.csv[/docgen.insertWithOutput] > transactions.fo
+
+> fop -fo transactions.fo transactions.pdf
+Jan 16, 2019 11:15:21 PM org.apache.fop.events.LoggingEventListener processEvent
+WARNING: Font "Symbol,normal,700" not found. Substituting with "Symbol,normal,400".
+Jan 16, 2019 11:15:21 PM org.apache.fop.events.LoggingEventListener processEvent
+WARNING: Font "ZapfDingbats,normal,700" not found. Substituting with "ZapfDingbats,normal,400".
+Jan 16, 2019 11:15:21 PM org.apache.fop.events.LoggingEventListener processEvent
+WARNING: The contents of fo:block line 1 exceed the available area in the inline-progression direction by 11027 millipoints. (See position 1519:51)
+Jan 16, 2019 11:15:22 PM org.apache.fop.events.LoggingEventListener processEvent
+INFO: Rendered page #1.
+Jan 16, 2019 11:15:22 PM org.apache.fop.events.LoggingEventListener processEvent
+INFO: Rendered page #2.</programlisting>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/examples/transactions.png" width="100%"/>
+ </imageobject>
+ </mediaobject>
+ </section>
+
+ <section>
+ <title>Transforming HTML To CSV</title>
+
+ <para>Recently I got the rather unusual question how to determine the
+ list of dependencies of an application - one easy way is the Maven
+ "dependencies.html" but this is unstructured data. Having said that
+ the Jsoup library is perfectly able to parse most real-life HTML and
+ provides a DOM model.</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/html/csv/dependencies.ftl"]</programlisting>
+
+ <para>Your dependencies as CSV can be generated as shown below:</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/html/csv/dependencies.ftl [docgen.wd]/examples/data/html/dependencies.html
+[/docgen.insertWithOutput]</programlisting>
+ </section>
+
+ <section>
+ <title>Transform CSV To Shell Script</title>
+
+ <para>For a customer project we wanted to record REST request /
+ responses using WireMock - really quick and dirty. So we decided to
+ avoid any sophisticated test tool but generate a ready-to-use shell
+ script executing cURL commands. It turned out that handling of dollar
+ signs is a bit tricky.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Using <literal>noparse</literal> directive to disable
+ parsing of dollar signs</para>
+ </listitem>
+
+ <listitem>
+ <para>Using <literal>${r"${MY_BASE_URL}"</literal> to generate
+ output with dollar signs</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>and the final FTL is found below:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/csv/shell/curl.ftl"]</programlisting>
+
+ <para>Rendering the FreeMarker template:</para>
+
+ <programlisting>freemarker-generator -t examples/templates/csv/shell/curl.ftl examples/data/csv/user.csv</programlisting>
+
+ <para>Looks a bit complicated but lets dissect the things</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>date "+%FT%H:%M:%S" | tr -d '\n'</literal> creates
+ a timestamp and removes the line feed</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>curl --write-out</literal> allows to print runtime
+ data (see <link
+ xlink:href="https://ec.haxx.se/usingcurl-writeout.html">https://ec.haxx.se/usingcurl-writeout.html</link>)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><remark>Shell/curl specifics are irrelevant, as far as
+ FreeMarker Generator is concerned. We should remove the above
+ explanation.</remark></para>
+
+ <para><remark>What specialty with generating shell scripts we want to
+ demonstrate in this example? Is it escaping ${...} maybe? That belongs
+ to the FreeMarker documentation. But if we still want to show that
+ here, I would recommend using the [=...] interpolation syntax when
+ generating something that already uses ${...}.</remark></para>
+
+ <para>Executing the result shell script creates the following output
+ (which is a nice CSV for further processing):</para>
+
+ <programlisting>time,user,status,duration,size
+2019-09-27T21:02:52,AAAAAAA,200,0.522473,206
+2019-09-27T21:02:53,BBBBBBB,200,0.498093,206
+2019-09-27T21:02:54,CCCCCCC,200,0.529013,206
+2019-09-27T21:02:54,DDDDDDD,200,0.528268,206</programlisting>
+
+ <remark>We can't generate the above in Docgen, as curl is might not be
+ available, or can't fetch remote resource.</remark>
+ </section>
+
+ <section>
+ <title>Executing Arbitrary Commands</title>
+
+ <para>Using Apache Commons Exec allows to execute arbitrary commands -
+ nice but dangerous. It was recently quite useful to to invoke AWS CLI
+ to generate a Confluence page about the overall setup of our AWS
+ accounts.</para>
+
+ <para>A few snippets to illustrate the points:</para>
+
+ <programlisting role="template"><#ftl output_format="plainText" strip_whitespace="true">
+<#assign profile = tools.system.getProperty("profile", "default")>
+<#assign ec2Instances = ec2Instances()/>
+
+h3. AWS EC2 Instance
+<@printEc2Instances ec2Instances/>
+
+<#function ec2Instances>
+ <#local json = awsCliToJson("aws ec2 describe-instances --profile ${profile}")>
+ <#local instances = json.read("$.Reservations[*].Instances[*]")>
+ <#return instances?sort_by(['InstanceType'])>
+</#function>
+
+<#function awsCliToJson line>
+ <#local output = tools.exec.execute(line)>
+ <#return tools.jsonpath.parse(output)>
+</#function>
+
+<#function getAwsEc2InstanceTag tags name>
+ <#return tags?filter(x -> x["Key"] == name)?first["Value"]!"">
+</#function>
+
+<#macro printEc2Instances ec2Instances>
+ <#compress>
+ || NAME || INSTANCE_TYPE || VCPUS || STATE || PRIVATE_IP_ADDRESS ||
+ <#list ec2Instances as ec2Instance>
+ <#assign instanceType = ec2Instance["InstanceType"]>
+ <#assign arn = ec2Instance["IamInstanceProfile"]["Arn"]>
+ <#assign privateIpAddress = ec2Instance["PrivateIpAddress"]>
+ <#assign state = ec2Instance["State"]["Name"]>
+ <#assign launchTime = ec2Instance["LaunchTime"]>
+
+ <#assign coreCount = ec2Instance["CpuOptions"]["CoreCount"]?number>
+ <#assign threadsPerCore = ec2Instance["CpuOptions"]["ThreadsPerCore"]?number>
+ <#assign nrOfVirtualCpus = coreCount * threadsPerCore>
+
+ <#assign tags = ec2Instance["Tags"]/>
+ <#assign awsCloudFormationStackId = getAwsEc2InstanceTag(tags, "aws:cloudformation:stack-id")>
+ <#assign awsCloudFormationStackName = getAwsEc2InstanceTag(tags, "aws:cloudformation:stack-name")>
+ <#assign name = getAwsEc2InstanceTag(tags, "Name")>
+ <#assign country = getAwsEc2InstanceTag(tags, "Country")>
+ <#assign environment = getAwsEc2InstanceTag(tags, "Environment")>
+
+ | ${name} | ${instanceType} | ${nrOfVirtualCpus} | ${state} | ${privateIpAddress} |
+ </#list>
+ </#compress>
+</#macro></programlisting>
+
+ <para><remark>Not in runnable examples (see same problem earlier, why
+ that matters). Although, it's next to impossible to make a portable
+ example of this. Question is, what do we want to demonstrate here? Lot
+ of lines to dig through for the reader, and the point is maybe just
+ <#local output = tools.exec.execute(line)>.</remark></para>
+ </section>
+
+ <section>
+ <title>Interactive Templates</title>
+
+ <para>Sometime you need to apply a CSS, JSON or XPath query in an
+ ad-hoc way without installing <literal>xmllint</literal>,
+ <literal>jq</literal> or <literal>pup</literal> - in this case you can
+ pass a FreeMarker template in an interactive fashion.</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -i 'Some template here... ${1 + 1}'
+[/docgen.insertWithOutput]
+
+[docgen.insertWithOutput]
- freemarker-generator -i '${tools.jsonpath.parse(dataSources?values[0]).read("$.info.title")}' [docgen.wd]/examples/data/json/swagger-spec.json
++freemarker-generator -i '${tools.jsonpath.parse(dataSources[0]).read("$.info.title")}' [docgen.wd]/examples/data/json/swagger-spec.json
+[/docgen.insertWithOutput]
+
+[docgen.insertWithOutput]
- freemarker-generator -i '${tools.xml.parse(dataSources?values[0])["recipients/person[1]/name"]}' [docgen.wd]/examples/data/xml/recipients.xml
++freemarker-generator -i '${tools.xml.parse(dataSources[0])["recipients/person[1]/name"]}' [docgen.wd]/examples/data/xml/recipients.xml
+[/docgen.insertWithOutput]
+
+[docgen.insertWithOutput]
- freemarker-generator -i '${tools.jsoup.parse(dataSources?values[0]).select("a")[0]}' [docgen.wd]/examples/data/html/dependencies.html
++freemarker-generator -i '${tools.jsoup.parse(dataSources[0]).select("a")[0]}' [docgen.wd]/examples/data/html/dependencies.html
+[/docgen.insertWithOutput]</programlisting>
+
+ <remark>I have deleted some examples above, as they were problematic
+ to generate. I think one or two would be enough anyway, as we just
+ demonstrate -i here.</remark>
+ </section>
+
+ <section>
+ <title>Filtering & Transforming CSV</title>
+
+ <para>During an integration project we imported large transactions CSV
+ files (500.000+ records) and in case of import failures the developers
+ would be happy to get a nice outline of the transactions causing the
+ problem (the CSV records have 60+ columns) - in essence it is
+ filtering (based on some primary key) and and transforming into a
+ human-readable output format (Markdown).</para>
+
- <para>So lets start the filtering & transformaction using the
++ <para>So lets start the filtering & transformation using the
+ following command line</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -e UTF-8 -l de_AT -Pcolumn="Order ID" \
+ -Pvalues=226939189,957081544 \
+ -t [docgen.wd]/examples/templates/csv/md/filter.ftl [docgen.wd]/examples/data/csv/sales-records.csv
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>The FreeMarker template referred was this:</para>
+
+ <programlisting role="template">[docgen.insertFile "@exampleTemplates/csv/md/filter.ftl"]</programlisting>
+ </section>
+
+ <section>
+ <title>Converting Between JSON And YAML</title>
+
+ <para>Sometimes we simply need to transform a JSON into an equivalent
+ YAML or the other way around.</para>
+
+ <programlisting>[docgen.insertWithOutput]freemarker-generator -t freemarker-generator/yaml/json/transform.ftl [docgen.wd]/examples/data/yaml/swagger-spec.yaml[/docgen.insertWithOutput]
- [docgen.insertWithOutput]freemarker-generator -i '${tools.gson.toJson(tools.yaml.parse(dataSources?values[0]))}' [docgen.wd]/examples/data/yaml/swagger-spec.yaml[/docgen.insertWithOutput]
++[docgen.insertWithOutput]freemarker-generator -i '${tools.gson.toJson(tools.yaml.parse(dataSources[0]))}' [docgen.wd]/examples/data/yaml/swagger-spec.yaml[/docgen.insertWithOutput]
+[docgen.insertWithOutput]freemarker-generator -i '${tools.gson.toJson(yaml)}' -m yaml=[docgen.wd]/examples/data/yaml/swagger-spec.yaml[/docgen.insertWithOutput]
+
+[docgen.insertWithOutput]freemarker-generator -t freemarker-generator/json/yaml/transform.ftl [docgen.wd]/examples/data/json/swagger-spec.json[/docgen.insertWithOutput]
- [docgen.insertWithOutput]freemarker-generator -i '${tools.yaml.toYaml(tools.gson.parse(dataSources?values[0]))}' [docgen.wd]/examples/data/json/swagger-spec.json[/docgen.insertWithOutput]
++[docgen.insertWithOutput]freemarker-generator -i '${tools.yaml.toYaml(tools.gson.parse(dataSources[0]))}' [docgen.wd]/examples/data/json/swagger-spec.json[/docgen.insertWithOutput]
+[docgen.insertWithOutput]freemarker-generator -i '${tools.yaml.toYaml(json)}' -m json=[docgen.wd]/examples/data/json/swagger-spec.json[/docgen.insertWithOutput]</programlisting>
+ </section>
+
+ <section>
+ <title>Using Advanced FreeMarker Features</title>
+
+ <para>There is a <literal>demo.ftl</literal> which shows some advanced
+ FreeMarker functionality:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Invoking a Java constructor</para>
+ </listitem>
+
+ <listitem>
+ <para>Invoke a static method of non-instantiable class</para>
+ </listitem>
+
+ <listitem>
+ <para>Work with Java enumerations</para>
+ </listitem>
+
+ <listitem>
+ <para>Access System properties</para>
+ </listitem>
+
+ <listitem>
+ <para>Access Environment variables</para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/demo.ftl
+[/docgen.insertWithOutput]</programlisting>
+ </section>
+ </section>
+ </chapter>
+
+ <chapter xml:id="concepts">
+ <title>Concepts</title>
+
+ <section xml:id="design-goals">
+ <title>Design Goals</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>Create a proper command-line tool which has Unix look &
+ feel</para>
+ </listitem>
+
+ <listitem>
+ <para>Handle arbitrary large input and output data</para>
+ </listitem>
+
+ <listitem>
+ <para>Support multiple source files/directories for a single
+ transformation</para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of Java <literal>properties</literal>
+ (<literal>java.util.Properties</literal>) files<remark> Reworded
+ this a bit. Especially, to remove reference to the
+ JDK.</remark></para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of CSV files using <link
+ xlink:href="https://commons.apache.org/proper/commons-csv/">Apache
+ Commons CSV</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of JSON using <link
+ xlink:href="https://github.com/jayway/JsonPath">Jayway's
+ JSONPath</link> and <link
+ xlink:href="https://github.com/google/gson">GSON</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of Excel using <link
+ xlink:href="https://poi.apache.org">Apache POI</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of YAML using <link
+ xlink:href="https://bitbucket.org/asomov/snakeyaml/wiki/Home">SnakeYAML</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of HTML using <link
+ xlink:href="https://jsoup.org">JSoup</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support transformation of structured log files using <link
+ xlink:href="https://github.com/thekrakken/java-grok">Grok</link></para>
+ </listitem>
+
+ <listitem>
+ <para>XML & XPath is supported by FreeMarker <link
+ xlink:href="http://freemarker.org/docs/xgui.html">out-of-the-box</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support for reading a data source content from STDIN to
+ integrate with command line tools</para>
+ </listitem>
+
+ <listitem>
+ <para>Support execution of arbitrary commands using <link
+ xlink:href="https://commons.apache.org/proper/commons-exec/">Apache
+ Commons Exec</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Support creation of test data using <link
+ xlink:href="https://github.com/DiUS/java-faker/">JavaFaker</link></para>
+ </listitem>
+
+ <listitem>
+ <para>Add some commonly useful information such as Java System
+ Properties, environment variables</para>
+ </listitem>
+
+ <listitem>
+ <para>Support embedding the code in existing applications</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section xml:id="datasources">
+ <title>Data Sources</title>
+
+ <para>A <literal>DataSource</literal> consists of lazy-loaded data
+ available in Apache FreeMarker's model. It provides:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>A <literal>name</literal> uniquely identifying a data
+ source</para>
+ </listitem>
+
+ <listitem>
+ <para>An <literal>uri</literal> which as used to create the data
+ source</para>
+ </listitem>
+
+ <listitem>
+ <para>A <literal>contentType</literal> and
+ <literal>charset</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>Access to textual content directly or using a line
+ iterator</para>
+ </listitem>
+
+ <listitem>
+ <para>Access to the underlying data input stream</para>
+ </listitem>
+ </itemizedlist>
+
+ <section>
+ <title>Loading a Data Source</title>
+
+ <para>A <literal>DataSource</literal> can be loaded from the file
+ system, e.g., as positional command line argument:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl [docgen.wd]/README.md
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>from an URL:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl --data-source xkcd=https://xkcd.com/info.0.json
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>or from an environment variable, e.g.
+ <literal>NGINX_CONF</literal> having a JSON payload:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"
+ systemProperties={'freemarker.generator.datasource.envOverride.NGINX_CONF': '{"NGINX_PORT":"8443","NGINX_HOSTNAME":"localhost"}'}
+]
+freemarker-generator -t freemarker-generator/info.ftl --data-source conf=env:///NGINX_CONF#mimeType=application/json
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>Of course you can load multiple data sources directly:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl [docgen.wd]/README.md xkcd=https://xkcd.com/info.0.json
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>or load them from a directory:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl --data-source [docgen.wd]/examples/data
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>which can be combined with <literal>include</literal> and
+ <literal>exclude</literal> filters:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl -s [docgen.wd]/examples/data --data-source-include='*.json'
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>Access to <literal>stdin</literal> is implemented as
+ <literal>DataSource</literal> - please note that
+ <literal>stdin</literal> is read lazily to cater for arbitrary large
+ input data<remark> (TODO: Docgen can't generate this yet, because of
+ the cat and pipe)</remark>:</para>
+
+ <programlisting>cat examples/data/csv/contract.csv | bin/freemarker-generator -t freemarker-generator/info.ftl --stdin
+
- FreeMarker Generator DataSources
++FreeMarker Generator Data Sources
+------------------------------------------------------------------------------
+[#1]: name=stdin, group=default, fileName=stdin mimeType=text/plain, charset=UTF-8, length=-1 Bytes
+URI : system:///stdin</programlisting>
+ </section>
+
+ <section>
+ <title>Selecting a Data Source</title>
+
+ <para>After loading one or more <literal>DataSource</literal> they are
+ accessible as <literal>dataSource</literal> map in the FreeMarker
+ model:</para>
+
+ <itemizedlist>
+ <listitem>
- <para><literal>dataSources?values[0]</literal> or
- <literal>dataSources?values?first</literal> selects the first data
++ <para><literal>dataSources[0]</literal> or
++ <literal>dataSources?first</literal> selects the first data
+ source</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>dataSources["user.csv"]</literal> selects the data
+ source with the name <literal>"user.csv"</literal></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Iterating Over Data Sources</title>
+
+ <para>The data sources are exposed as map within FreeMarker's data
+ model<remark> (TODO: There's no example template to insert
+ here)</remark>:</para>
+
+ <programlisting><#-- Do something with the data sources -->
+<#if dataSources?has_content>
+Some data sources found
+<#else>
+No data sources found ...
+</#if>
+
+<#-- Get the number of data sources -->
+${dataSources?size}
+
+<#-- Iterate over a map of data sources -->
+<#list dataSources as name, dataSource>
+- ${name} => ${dataSource.length}
+</#list>
+
+<#-- Iterate over a list of data sources -->
- <#list dataSources?values as dataSource>
++<#list dataSources as dataSource>
+- [#${dataSource?counter}]: name=${dataSource.name}
+</#list></programlisting>
+ </section>
+
+ <section>
+ <title>Filtering of Data Sources</title>
+
+ <para>Combining FreeMarker's <literal>filter</literal> built-in with
+ the <literal>DataSource.match</literal> methods allows more advanced
+ selection of data sources (using Apache Commons IO wild-card
+ matching)<remark> (TODO: There's no example template to insert
+ here)</remark>:</para>
+
+ <programlisting><#-- List all data sources containing "test" in the name -->
- <#list dataSources?values?filter(ds -> ds.match("name", "*test*")) as ds>
++<#list dataSources?filter(ds -> ds.match("name", "*test*")) as ds>
+- ${ds.name}
+</#list>
+
+<#-- List all data sources having "json" extension -->
- <#list dataSources?values?filter(ds -> ds.match("extension", "json")) as ds>
++<#list dataSources?filter(ds -> ds.match("extension", "json")) as ds>
+- ${ds.name}
+</#list>
+
+<#-- List all data sources having "src/test/data/properties" in their file path -->
- <#list dataSources?values?filter(ds -> ds.match("filePath", "*/src/test/data/properties")) as ds>
++<#list dataSources?filter(ds -> ds.match("filePath", "*/src/test/data/properties")) as ds>
+- ${ds.name}
+</#list>
+
+<#-- List all data sources of a group -->
- <#list dataSources?values?filter(ds -> ds.match("group", "default")) as ds>
++<#list dataSources?filter(ds -> ds.match("group", "default")) as ds>
+- ${ds.name}
+</#list></programlisting>
+ </section>
+
+ <section>
+ <title>Using and Inspecting Data Sources</title>
+
+ <para><remark>These were two separate chapters, but they both shown
+ parts of datasources.ftl, so I unified them.</remark></para>
+
+ <para>In most cases the data source will be passed to a tool, but
+ there are some useful operations available as shown below:</para>
+
+ <programlisting>[docgen.insertFile "@exampleTemplates/datasources.ftl"]</programlisting>
+
+ <para>will result in:</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/datasources.ftl --data-source [docgen.wd]/examples/data/csv/contract.csv
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>You can also use similar command like above to inspect what data
+ source you have.</para>
+ </section>
+ </section>
+
+ <section xml:id="named-uri">
+ <title>Named URI-s</title>
+
+ <para>Named URIs allow identifying <literal>DataSource</literal>-s (not
+ a JDBC <literal>DataSource</literal>, <link linkend="datasources">but
+ this</link><remark> - added this, or else it can confuse Java
+ developers</remark>) and pass additional information.</para>
+
+ <para>A Named URI consists of:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>An optional name</para>
+ </listitem>
+
+ <listitem>
+ <para>An URI or simple file name</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><remark>There was a figure heer from
+ https://docs.gomplate.ca/datasources/, which is nicer but I wasn't sure
+ about how that affects our LICENSE, etc. So I substituted that with this
+ paragraph. </remark>As a refresher, here's an example URL to show what
+ components an URI can have in general:
+ <literal>someScheme://user@some.domain.org:1234/foo/bar/baaz?param1=value1;param2=value2#someFragment</literal>.
+ Before the <literal>:</literal>, <literal>someScheme</literal> is called
+ the scheme, then, after the <literal>\\</literal>,
+ <literal>user@some.domain.org:1234</literal> is called the authority,
+ then comes <literal>/foo/bar/baaz</literal> with is called the path,
+ then, after the <literal>?</literal>,
+ <literal>param1=value1;param2=value2</literal> is the query, and finally
+ after the <literal>#</literal>, <literal>someFragment</literal> is
+ called the fragment.</para>
+
+ <para>For our purposes, the scheme and the path components are
+ especially important, though the other components are used by certain
+ data sources for particular purposes.</para>
+
+ <orderedlist>
+ <listitem>
+ <para>Scheme: All data sources require a scheme (except for file
+ when using relative paths)</para>
+ </listitem>
+
+ <listitem>
+ <para>Authority: Used only by remote data sources, and can be
+ omitted in some of those cases.</para>
+ </listitem>
+
+ <listitem>
+ <para>Path: Can be omitted, but usually used as the basis of the
+ locator for the datasource.</para>
+ </listitem>
+
+ <listitem>
+ <para>Query: Used mainly for HTTP and HTTPS URLs.</para>
+ </listitem>
+
+ <listitem>
+ <para>Fragment: Used rarely for providing additional attributes,
+ e.g. <literal>mimeType</literal> of
+ <literal>charset</literal></para>
+ </listitem>
+ </orderedlist>
+
+ <section>
+ <title>Using Named URIs For A File</title>
+
+ <para>The following Named URI loads a <literal>user.csv</literal> and
+ the data source is available as <literal>my_users</literal>:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl my_users=[docgen.wd]/examples/data/csv/user.csv
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>A Named URI allows to pass additional information as part of the
+ fragment, e.g. the charset of the text file:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl my_users=[docgen.wd]/examples/data/csv/user.csv#charset=UTF-16
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>In addition to the simplified file syntax full URIs can be
+ used:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl https://www.google.com#charset=ISO-8859-1
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>and also combined with a name:</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl page=http://www.google.com#charset=ISO-8859-1
+[/docgen.insertWithOutput]</programlisting>
+ </section>
+
+ <section>
+ <title>Using Named URIs For Directories</title>
+
+ <para>A Name URI can be also combined with file directories.</para>
+
+ <para>Load all CVS files of a directory using the group "csv":</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
+freemarker-generator -t freemarker-generator/info.ftl :csv=[docgen.wd]/examples/data/csv
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>or use a charset for all files of a directory</para>
+
- <programlisting>[docgen.insertWithOutput from="FreeMarker Generator DataSources" to=r"^\s*$"]
- freemarker-generator -t freemarker-generator/info.ftl '[docgen.wd]/examples/data/csv#charset=UTF-16&mimetype=text/plain'
++ <programlisting>[docgen.insertWithOutput from="FreeMarker Generator Data Sources" to=r"^\s*$"]
++freemarker-generator -t freemarker-generator/info.ftl '[docgen.wd]/examples/data/csv#charset=UTF-16&mimeType=text/plain'
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>It is also possible to provide data source properties to all
+ files being loaded</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/datasources.ftl '[docgen.wd]/examples/data/csv#format=DEFAULT'
+[/docgen.insertWithOutput]</programlisting>
+
+ <para/>
+ </section>
+ </section>
+
+ <section xml:id="data-models">
+ <title>Data Models</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section xml:id="passing-configuration-data">
+ <title>Passing Configuration Data</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section xml:id="template-loading">
+ <title>Template Loading</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section xml:id="transformation">
+ <title>Transformation</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section xml:id="tools">
+ <title>Tools</title>
+
+ <para>TODO</para>
+ </section>
+ </chapter>
+
+ <chapter xml:id="usage-details">
+ <title>Usage details</title>
+
+ <remark role="editorialNote">In the markdown version this chapter was
+ "Usage", but I though that clashes with "Getting Started" in
+ meaning.</remark>
+
+ <section>
+ <title>Transforming Directories</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section>
+ <title>Using DataFrames</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section>
+ <title>Transforming CSV</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section>
+ <title>Generating test data</title>
+
+ <para>TODO</para>
+ </section>
+
+ <section>
+ <title>Parsing with Grok</title>
+
+ <para>Think of <literal>Grok</literal> as modular regular expressions
+ with a pre-defined functionality to parse access logs or any other data
+ where you can't comprehend the regular expression any longer, one very
+ simple example is <literal>QUOTEDSTRING</literal>.</para>
+
+ <programlisting>QUOTEDSTRING (?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))</programlisting>
+
+ <para>And with <literal>Grok</literal> the
+ <literal>QUOTEDSTRING</literal> is just a building block for an even
+ more complex regular expression such as
+ <literal>COMBINEDAPACHELOG</literal>.</para>
+
+ <programlisting>[docgen.insertWithOutput]
+freemarker-generator -t [docgen.wd]/examples/templates/accesslog/combined-access.ftl [docgen.wd]/examples/data/accesslog/combined-access.log
+[/docgen.insertWithOutput]</programlisting>
+
+ <para>using the following FreeMarker template:</para>
+
+ <programlisting>[docgen.insertFile "@exampleTemplates/accesslog/combined-access.ftl"]</programlisting>
+
+ <para>While this looks small and tidy there are some nifty
+ features:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>tools.grok.compile("%{COMBINEDAPACHELOG}")</literal>
+ builds the <literal>Grok</literal> instance to parse access logs in
+ <literal>Combined Format</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>The data source is streamed line by line and not loaded into
+ memory in one piece</para>
+ </listitem>
+
+ <listitem>
+ <para>This also works for using <literal>stdin</literal> so are able
+ to parse GB of access log or other files</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </chapter>
+
+ <chapter xml:id="advanced-topics">
+ <title>Advanced topics</title>
+
+ <section xml:id="freemarker-cli-configuration">
+ <title>FreeMarker CLI Configuration</title>
+
+ <para>TODO</para>
+ </section>
+ </chapter>
+
+ <chapter xml:id="appendixes">
+ <title>Appendixes</title>
+
+ <section xml:id="download">
+ <title>Download</title>
+
+ <simplesect>
+ <title>Latest release: 0.1.0</title>
+
+ <para>Released on 2020-[FIXME]-[FIXME]. Requires Java 1.8 or
+ higher.</para>
+
+ <para><link linkend="version_0_1_0">See what's new...</link></para>
+
+ <para>Downloads:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link
+ xlink:href="https://www.apache.org/dyn/closer.cgi/freemarker/generator/0.1.0/binaries/apache-freemarker-generator-cli-0.1.0-bin.tar.gz">Binary
+ release of the command line tool (tar.gz)</link> [<link
+ xlink:href="https://www.apache.org/dyn/closer.cgi/freemarker/generator/0.1.0/binaries/apache-freemarker-generator-cli-0.1.0-bin.tar.gz.sha512">SHA512</link>]
+ [<link
+ xlink:href="https://www.apache.org/dyn/closer.cgi/freemarker/generator/0.1.0/binaries/apache-freemarker-generator-cli-0.1.0-bin.tar.gz.asc">ASC</link>]</para>
+ </listitem>
+
+ <listitem>
+ <para><link
+ xlink:href="https://www.apache.org/dyn/closer.cgi/freemarker/generator/0.1.0/binaries/apache-freemarker-generatori-0.1.0-src.tar.gz">Source
+ release (tar.gz)</link> [<link
+ xlink:href="https://www.apache.org/dyn/closer.cgi/freemarker/generator/0.1.0/binaries/apache-freemarker-generatori-0.1.0-src.tar.gz.sha512">SHA512</link>]
+ [<link
+ xlink:href="https://www.apache.org/dyn/closer.cgi/freemarker/generator/0.1.0/binaries/apache-freemarker-generatori-0.1.0-src.tar.gz.asc">ASC</link>]</para>
+ </listitem>
+ </itemizedlist>
+ </simplesect>
+ </section>
+
+ <section xml:id="versionsHistory">
+ <title>Version history</title>
+
+ <section xml:id="version_0_1_0">
+ <title>0.1.0</title>
+
+ <para>This is the first release at Apache. The previous version of the
+ project was here: <link
+ xlink:href="https://github.com/sgoeschl/freemarker-cli">https://github.com/sgoeschl/freemarker-cli</link>.
+ Compared to that, the most important changes are these:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>[TODO]</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section xml:id="legal">
+ <title>Legal</title>
+
+ <section xml:id="license">
+ <title>License</title>
+
+ <para>Bellow license applies to the FreeMarker Generator source code.
+ Binary distributions of FreeMarker Generator may bundles 3rd party
+ dependencies, in which case see the license included in the binary
+ distribution for more information about the licenses of bundled
+ dependencies!</para>
+
+ <programlisting role="unspecified">
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+==============================================================================
+END LICENSE</programlisting>
+ </section>
+
+ <section xml:id="export_control">
+ <title>Export Control</title>
+
+ <para>The FreeMarker Generator source code doesn't include
+ cryptography. Furthermore its binary (downloadable) forms don't
+ include any cryptography software. Hence, FreeMarker has no Export
+ Control Classification Number (ECCN). Where an ECCN should be filled,
+ the label "not subject to EAR" could be used.</para>
+
+ <para>FreeMarker Generator itself doesn't add any exporting
+ limitations.</para>
+ </section>
+ </section>
+ </chapter>
+</book>