From cb2be8d178f6540878f46bb8e816c5eeee0d9bcb Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Tue, 31 Mar 2015 10:19:26 +0000
Subject: [PATCH] CR-6494 OPENDJ-1897 Generate locales ref doc with a template

---
 opendj-doc-plugin/src/main/resources/templates/sec-locales-subtypes.ftl                   |   71 ++++++++++++++
 opendj-doc-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java |  211 ++++++++++++++++++++++++------------------
 opendj-doc-plugin/pom.xml                                                                 |    5 +
 3 files changed, 197 insertions(+), 90 deletions(-)

diff --git a/opendj-doc-plugin/pom.xml b/opendj-doc-plugin/pom.xml
index d67b3dd..899ac3a 100644
--- a/opendj-doc-plugin/pom.xml
+++ b/opendj-doc-plugin/pom.xml
@@ -55,6 +55,11 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
+      <groupId>org.freemarker</groupId>
+      <artifactId>freemarker</artifactId>
+      <version>2.3.21</version>
+    </dependency>
+    <dependency>
       <groupId>org.twdata.maven</groupId>
       <artifactId>mojo-executor</artifactId>
       <version>2.2.0</version>
diff --git a/opendj-doc-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java b/opendj-doc-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java
index e1c0e8d..ea02283 100644
--- a/opendj-doc-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java
+++ b/opendj-doc-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java
@@ -26,6 +26,9 @@
 
 import static com.forgerock.opendj.ldap.CoreMessages.*;
 
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -33,16 +36,22 @@
 import org.apache.maven.plugins.annotations.Parameter;
 import org.forgerock.opendj.ldap.schema.CoreSchemaSupportedLocales;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
-import java.util.TreeSet;
 
 /**
  * Generate schema-related reference documentation sources.
@@ -65,7 +74,6 @@
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         final Locale currentLocale = getLocaleFromTag(locale);
-
         final String localeReference = getLocalesAndSubTypesDocumentation(currentLocale);
         final File localeReferenceFile = new File(outputDirectory, "sec-locales-subtypes.xml");
         try {
@@ -79,6 +87,22 @@
     }
 
     /**
+     * Returns a DocBook XML Section element documenting supported locales and language subtypes.
+     * @param currentLocale The locale for which to generate the documentation.
+     * @return A DocBook XML Section element documenting supported locales and language subtypes.
+     */
+    private String getLocalesAndSubTypesDocumentation(final Locale currentLocale) {
+        final Map<String, Object> map = new HashMap<String, Object>();
+        map.put("year", new SimpleDateFormat("yyyy").format(new Date()));
+        map.put("lang", getTagFromLocale(currentLocale));
+        map.put("title", DOC_LOCALE_SECTION_TITLE.get());
+        map.put("info", DOC_LOCALE_SECTION_INFO.get());
+        map.put("locales", getLocalesDocMap(currentLocale));
+        map.put("subtypes", getSubTypesDocMap(currentLocale));
+        return applyTemplate("sec-locales-subtypes.ftl", map);
+    }
+
+    /**
      * Create the output directory if it does not exist.
      * @throws IOException  Failed to create the directory.
      */
@@ -105,23 +129,61 @@
     private final Map<String, String> localeTagsToOids =
             CoreSchemaSupportedLocales.getJvmSupportedLocaleNamesToOids();
 
+    /** FreeMarker template configuration. */
+    private Configuration configuration;
+
     /**
-     * Returns a DocBook XML VariableList element documenting supported locales.
-     * @param currentLocale The locale for which to generate the documentation.
-     * @return A DocBook XML VariableList element documenting supported locales.
+     * Returns a FreeMarker configuration for applying templates.
+     * @return A FreeMarker configuration for applying templates.
      */
-    private String getLocalesDocumentation(final Locale currentLocale) {
-        if (currentLocale == null) {
-            return "";
+    private Configuration getConfiguration() {
+        if (configuration == null) {
+            configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+            configuration.setClassForTemplateLoading(GenerateSchemaDocMojo.class, "/templates");
+            configuration.setDefaultEncoding("UTF-8");
+            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
         }
+        return configuration;
+    }
 
-        class LocaleDoc {
-            String tag;
-            String language;
-            String oid;
+    /**
+     * Returns the String result from applying a FreeMarker template.
+     * @param template The name of a template file found in {@code resources/templates/}.
+     * @param map      The map holding the data to use in the template.
+     * @return The String result from applying a FreeMarker template.
+     */
+    private String applyTemplate(final String template, final Map<String, Object> map) {
+        // FreeMarker requires a configuration to find the template.
+        configuration = getConfiguration();
+
+        // FreeMarker takes the data and a Writer to process the template.
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        Writer writer = new OutputStreamWriter(outputStream);
+        try {
+            Template configurationTemplate = configuration.getTemplate(template);
+            configurationTemplate.process(map, writer);
+            return outputStream.toString();
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            org.forgerock.util.Utils.closeSilently(writer, outputStream);
         }
+    }
 
-        Map<String, LocaleDoc> locales = new HashMap<String, LocaleDoc>();
+    /** Container for documentation regarding a locale. */
+    private class LocaleDoc {
+        String tag;
+        String language;
+        String oid;
+    }
+
+    /**
+     * Returns a map of languages to Locale documentation containers.
+     * @param currentLocale     The Locale of the resulting documentation.
+     * @return A map of languages to Locale documentation containers.
+     */
+    private Map<String, LocaleDoc> getLanguagesToLocalesMap(final Locale currentLocale) {
+        Map<String, LocaleDoc> locales = new TreeMap<String, LocaleDoc>();
         for (String tag : localeTagsToOids.keySet()) {
             final Locale locale = getLocaleFromTag(tag);
             if (locale == null) {
@@ -134,52 +196,50 @@
             if (!localeDoc.language.equals(localeDoc.tag)) {
                 // No display language so must not be supported in current JVM
                 locales.put(localeDoc.language, localeDoc);
-            } else {
-                if (localeDoc.tag.equals("sh")) {
-                    localeDoc.language = DOC_LANGUAGE_SH.get().toString(currentLocale);
-                    locales.put(localeDoc.language, localeDoc);
-                }
+            } else if (localeDoc.tag.equals("sh")) {
+                localeDoc.language = DOC_LANGUAGE_SH.get().toString(currentLocale);
+                locales.put(localeDoc.language, localeDoc);
             }
         }
-        if (locales.isEmpty()) {
-            return "";
-        }
-
-        final String eol = System.getProperty("line.separator");
-        final StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder
-                .append(" <variablelist xml:id=\"supported-locales\">").append(eol)
-                .append("  <title>").append(DOC_SUPPORTED_LOCALES_TITLE.get()).append("</title>").append(eol)
-                .append("  <indexterm><primary>").append(DOC_SUPPORTED_LOCALES_INDEXTERM.get())
-                .append("</primary></indexterm>").append(eol);
-        Set<String> sortedLanguages = new TreeSet<String>(locales.keySet());
-        for (String language : sortedLanguages) {
-            LocaleDoc locale = locales.get(language);
-            stringBuilder
-                    .append("  <varlistentry>").append(eol)
-                    .append("   <term>").append(locale.language).append("</term>").append(eol)
-                    .append("   <listitem>").append(eol)
-                    .append("    <para>").append(DOC_LOCALE_TAG.get(locale.tag)).append("</para>").append(eol)
-                    .append("    <para>").append(DOC_LOCALE_OID.get(locale.oid)).append("</para>").append(eol)
-                    .append("   </listitem>").append(eol)
-                    .append("  </varlistentry>").append(eol);
-        }
-        stringBuilder.append(" </variablelist>").append(eol);
-        return stringBuilder.toString();
+        return locales;
     }
 
     /**
-     * Returns a DocBook XML ItemizedList element documenting supported language subtypes.
-     * @param currentLocale The locale for which to generate the documentation.
-     * @return A DocBook XML ItemizedList element documenting supported language subtypes.
+     * Returns a map of information for documenting supported locales.
+     * @param currentLocale The locale for which to generate the information.
+     * @return A map of information for documenting supported locales.
      */
-    private String getSubTypesDocumentation(final Locale currentLocale) {
-        if (currentLocale == null) {
-            return "";
+    private Map<String, Object> getLocalesDocMap(final Locale currentLocale) {
+        final Map<String, Object> result = new HashMap<String, Object>();
+        result.put("title", DOC_SUPPORTED_LOCALES_TITLE.get());
+        result.put("indexTerm", DOC_SUPPORTED_LOCALES_INDEXTERM.get());
+        final Map<String, LocaleDoc> localesMap = getLanguagesToLocalesMap(currentLocale);
+        final Set<String> sortedLanguages = localesMap.keySet();
+        final List<Map<String, Object>> locales = new LinkedList<Map<String, Object>>();
+        for (final String language : sortedLanguages) {
+            final LocaleDoc locale = localesMap.get(language);
+            final Map<String, Object> map = new HashMap<String, Object>();
+            map.put("language", locale.language);
+            map.put("tag", DOC_LOCALE_TAG.get(locale.tag));
+            map.put("oid", DOC_LOCALE_OID.get(locale.oid));
+            locales.add(map);
         }
+        result.put("locales", locales);
+        return result;
+    }
 
-        Map<String, String> map = new TreeMap<String, String>();
-        for (String tag : localeTagsToOids.keySet()) {
+    /**
+     * Returns a map of information for documenting supported language subtypes.
+     * @param currentLocale The locale for which to generate the information.
+     * @return A map of information for documenting supported language subtypes.
+     */
+    private Map<String, Object> getSubTypesDocMap(final Locale currentLocale) {
+        final Map<String, Object> result = new HashMap<String, Object>();
+        result.put("title", DOC_SUPPORTED_SUBTYPES_TITLE.get());
+        result.put("indexTerm", DOC_SUPPORTED_SUBTYPES_INDEXTERM.get());
+        final List<Map<String, Object>> locales = new LinkedList<Map<String, Object>>();
+        for (final String tag : localeTagsToOids.keySet()) {
+            final Map<String, Object> map = new HashMap<String, Object>();
             int idx = tag.indexOf('-');
             if (idx == -1) {
                 final Locale locale = getLocaleFromTag(tag);
@@ -188,48 +248,19 @@
                 }
                 final String language = locale.getDisplayName(currentLocale);
                 if (!language.equals(tag)) {
-                    map.put(language, tag);
-                } else {
-                    if (tag.equals("sh")) {
-                        map.put(DOC_LANGUAGE_SH.get().toString(currentLocale), tag);
-                    }
+                    map.put("language", language);
+                    map.put("tag", tag);
+                } else if (tag.equals("sh")) {
+                    map.put("language", DOC_LANGUAGE_SH.get().toString(currentLocale));
+                    map.put("tag", tag);
+                }
+                if (!map.isEmpty()) {
+                    locales.add(map);
                 }
             }
         }
-
-        final String eol = System.getProperty("line.separator");
-        final StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append(" <itemizedlist xml:id=\"supported-language-subtypes\">").append(eol)
-                .append("  <title>").append(DOC_SUPPORTED_SUBTYPES_TITLE.get()).append("</title>").append(eol)
-                .append("  <indexterm><primary>").append(DOC_SUPPORTED_SUBTYPES_INDEXTERM.get())
-                .append("</primary></indexterm>").append(eol);
-        for (String language: map.keySet()) {
-            stringBuilder
-                    .append("  <listitem><para>").append(language).append(", ")
-                    .append(map.get(language)).append("</para></listitem>").append(eol);
-        }
-        stringBuilder.append(" </itemizedlist>").append(eol);
-        return stringBuilder.toString();
-    }
-
-    /**
-     * Returns a DocBook XML Section element documenting supported locales and language subtypes.
-     * @param currentLocale The locale for which to generate the documentation.
-     * @return A DocBook XML Section element documenting supported locales and language subtypes.
-     */
-    private String getLocalesAndSubTypesDocumentation(final Locale currentLocale) {
-        final String eol = System.getProperty("line.separator");
-        return "<section xml:id=\"sec-locales-subtypes\" "
-                + "xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" "
-                + "xml:lang=\"" + getTagFromLocale(currentLocale) + "\" "
-                + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
-                + "xsi:schemaLocation=\"http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd\""
-                + ">" + eol
-                + " <title>" + DOC_LOCALE_SECTION_TITLE.get() + "</title>" + eol
-                + " <para>" + DOC_LOCALE_SECTION_INFO.get() + "</para>" + eol
-                + getLocalesDocumentation(currentLocale) + eol
-                + getSubTypesDocumentation(currentLocale) + eol
-                + "</section>";
+        result.put("locales", locales);
+        return result;
     }
 
     /**
diff --git a/opendj-doc-plugin/src/main/resources/templates/sec-locales-subtypes.ftl b/opendj-doc-plugin/src/main/resources/templates/sec-locales-subtypes.ftl
new file mode 100644
index 0000000..14d6215
--- /dev/null
+++ b/opendj-doc-plugin/src/main/resources/templates/sec-locales-subtypes.ftl
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ! CCPL HEADER START
+  !
+  ! This work is licensed under the Creative Commons
+  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
+  ! To view a copy of this license, visit
+  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
+  ! or send a letter to Creative Commons, 444 Castro Street,
+  ! Suite 900, Mountain View, California, 94041, USA.
+  !
+  ! You can also obtain a copy of the license at
+  ! trunk/opendj/legal-notices/CC-BY-NC-ND.txt.
+  ! See the License for the specific language governing permissions
+  ! and limitations under the License.
+  !
+  ! If applicable, add the following below this CCPL HEADER, with the fields
+  ! enclosed by brackets "[]" replaced with your own identifying information:
+  !      Portions Copyright [yyyy] [name of copyright owner]
+  !
+  ! CCPL HEADER END
+  !
+  !      Copyright 2011-${year} ForgeRock AS.
+  !
+-->
+<section xml:id="sec-locales-subtypes"
+         xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="${lang}"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://docbook.org/ns/docbook
+                             http://docbook.org/xml/5.0/xsd/docbook.xsd">
+
+ <title>${title}</title>
+
+ <para>
+  ${info}
+ </para>
+
+ <variablelist xml:id="supported-locales">
+  <title>${locales.title}</title>
+  <indexterm><primary>${locales.indexTerm}</primary></indexterm>
+
+  <#list locales.locales as locale>
+  <varlistentry>
+   <term>${locale.language}</term>
+   <listitem>
+    <para>
+     ${locale.tag}
+    </para>
+
+    <para>
+     ${locale.oid}
+    </para>
+   </listitem>
+  </varlistentry>
+  </#list>
+
+ </variablelist>
+
+ <itemizedlist xml:id="supported-language-subtypes">
+  <title>${subtypes.title}</title>
+  <indexterm><primary>${subtypes.indexTerm}</primary></indexterm>
+
+  <#list subtypes.locales?sort_by("language") as subtype>
+  <listitem>
+   <para>${subtype.language}, ${subtype.tag}</para>
+  </listitem>
+  </#list>
+
+ </itemizedlist>
+
+</section>

--
Gitblit v1.10.0