You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by sg...@apache.org on 2020/04/15 22:26:29 UTC

[freemarker-generator] 08/08: FREEMARKER-141 freemarker-cli: Expose user-supplied parameters in the data model

This is an automated email from the ASF dual-hosted git repository.

sgoeschl pushed a commit to branch FREEMARKER-141
in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git

commit 79c669eaf345e115207a6df5eb6bf9f66b76b93c
Author: Siegfried Goeschl <si...@gmail.com>
AuthorDate: Thu Apr 16 00:25:05 2020 +0200

    FREEMARKER-141 freemarker-cli: Expose user-supplied parameters in the data model
---
 .../base/activation/CachingUrlDataSource.java      | 16 ++++++++++
 .../generator/base/activation/Mimetypes.java       | 16 ++++++++++
 .../generator/base/datasource/DataSource.java      |  5 ++-
 .../base/parameter/ParameterModelSupplier.java     |  7 ++--
 .../org/apache/freemarker/generator/cli/Main.java  |  5 ++-
 .../freemarker/generator/cli/config/Settings.java  | 12 +++----
 .../freemarker/generator/cli/config/Suppliers.java |  6 ++--
 .../generator/cli/task/FreeMarkerTask.java         |  5 +--
 .../src/site/markdown/cli/concepts/named-uris.md   | 14 ++++----
 .../site/markdown/cli/concepts/user-parameters.md  | 37 ++++++++++++++++++++++
 .../src/site/markdown/index.md                     |  1 +
 .../freemarker/generator/cli/ManualTest.java       |  4 +--
 .../generator/cli/config/SettingsTest.java         |  2 +-
 freemarker-generator-cli/templates/info.ftl        | 12 ++++---
 14 files changed, 106 insertions(+), 36 deletions(-)

diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/CachingUrlDataSource.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/CachingUrlDataSource.java
index 24e02ac..6616598 100644
--- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/CachingUrlDataSource.java
+++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/CachingUrlDataSource.java
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package org.apache.freemarker.generator.base.activation;
 
 import javax.activation.URLDataSource;
diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/Mimetypes.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/Mimetypes.java
index 5bb4ebe..3a18a86 100644
--- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/Mimetypes.java
+++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/activation/Mimetypes.java
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package org.apache.freemarker.generator.base.activation;
 
 public class Mimetypes {
diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSource.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSource.java
index 4864dc6..94acf92 100644
--- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSource.java
+++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSource.java
@@ -34,7 +34,6 @@ import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static java.nio.charset.Charset.forName;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Objects.requireNonNull;
 import static org.apache.commons.io.IOUtils.lineIterator;
@@ -172,7 +171,7 @@ public class DataSource implements Closeable {
     public String getText(String charsetName) {
         final StringWriter writer = new StringWriter();
         try (InputStream is = getUnsafeInputStream()) {
-            IOUtils.copy(is, writer, forName(charsetName));
+            IOUtils.copy(is, writer, Charset.forName(charsetName));
             return writer.toString();
         } catch (IOException e) {
             throw new RuntimeException("Failed to get text: " + toString(), e);
@@ -224,7 +223,7 @@ public class DataSource implements Closeable {
      */
     public LineIterator getLineIterator(String charsetName) {
         try {
-            return closables.add(lineIterator(getUnsafeInputStream(), forName(charsetName)));
+            return closables.add(lineIterator(getUnsafeInputStream(), Charset.forName(charsetName)));
         } catch (IOException e) {
             throw new RuntimeException("Failed to create line iterator: " + toString(), e);
         }
diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/parameter/ParameterModelSupplier.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/parameter/ParameterModelSupplier.java
index da5a757..ac74090 100644
--- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/parameter/ParameterModelSupplier.java
+++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/parameter/ParameterModelSupplier.java
@@ -16,22 +16,21 @@
  */
 package org.apache.freemarker.generator.base.parameter;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.function.Supplier;
 
-import static java.util.Objects.requireNonNull;
-
 /**
  * Converts a map of parameters to a map. The resulting map contains
- * either (key -> String) or (key -> Map<String, Object>).
+ * either (key=String) or (key=Map&lt;String, Object&gt;).
  */
 public class ParameterModelSupplier implements Supplier<Map<String, Object>> {
 
     private final Map<String, String> parameters;
 
     public ParameterModelSupplier(Map<String, String> parameters) {
-        this.parameters = requireNonNull(parameters);
+        this.parameters = parameters != null ? parameters : Collections.emptyMap();
     }
 
     @Override
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/Main.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/Main.java
index 99d1876..60b0ccc 100644
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/Main.java
+++ b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/Main.java
@@ -17,6 +17,7 @@
 package org.apache.freemarker.generator.cli;
 
 import org.apache.freemarker.generator.base.FreeMarkerConstants.GeneratorMode;
+import org.apache.freemarker.generator.base.parameter.ParameterModelSupplier;
 import org.apache.freemarker.generator.base.util.ClosableUtils;
 import org.apache.freemarker.generator.base.util.StringUtils;
 import org.apache.freemarker.generator.cli.config.Settings;
@@ -205,6 +206,8 @@ public class Main implements Callable<Integer> {
     }
 
     private Settings settings(Properties configuration, List<File> templateDirectories) {
+        final ParameterModelSupplier parameterModelSupplier = new ParameterModelSupplier(parameters);
+
         return Settings.builder()
                 .isReadFromStdin(readFromStdin)
                 .setArgs(args)
@@ -216,7 +219,7 @@ public class Main implements Callable<Integer> {
                 .setLocale(locale)
                 .setOutputEncoding(outputEncoding)
                 .setOutputFile(outputFile)
-                .setParameters(parameters != null ? parameters : new HashMap<>())
+                .setParameters(parameterModelSupplier.get())
                 .setDataSources(getCombindedDataSources())
                 .setDataModels(dataModels)
                 .setSystemProperties(systemProperties != null ? systemProperties : new Properties())
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Settings.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Settings.java
index e3151bf..5163aed 100644
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Settings.java
+++ b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Settings.java
@@ -86,10 +86,10 @@ public class Settings {
     private final List<String> dataSources;
 
     /** User-supplied list of data sources directly exposed in the data model */
-    private List<String> dataModels;
+    private final List<String> dataModels;
 
     /** User-supplied parameters */
-    private final Map<String, String> parameters;
+    private final Map<String, Object> parameters;
 
     /** User-supplied system properties */
     private final Properties sytemProperties;
@@ -113,7 +113,7 @@ public class Settings {
             boolean isReadFromStdin,
             List<String> dataSources,
             List<String> dataModels,
-            Map<String, String> parameters,
+            Map<String, Object> parameters,
             Properties sytemProperties,
             Writer writer) {
         if (isEmpty(template) && isEmpty(interactiveTemplate)) {
@@ -208,7 +208,7 @@ public class Settings {
         return dataModels;
     }
 
-    public Map<String, String> getParameters() {
+    public Map<String, Object> getParameters() {
         return parameters;
     }
 
@@ -282,7 +282,7 @@ public class Settings {
         private boolean isReadFromStdin;
         private List<String> dataSources;
         private List<String> dataModels;
-        private Map<String, String> parameters;
+        private Map<String, Object> parameters;
         private Properties systemProperties;
         private Properties configuration;
         private Writer writer;
@@ -383,7 +383,7 @@ public class Settings {
             return this;
         }
 
-        public SettingsBuilder setParameters(Map<String, String> parameters) {
+        public SettingsBuilder setParameters(Map<String, Object> parameters) {
             if (parameters != null) {
                 this.parameters = parameters;
             }
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Suppliers.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Suppliers.java
index 9937610..6a57e59 100644
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Suppliers.java
+++ b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/Suppliers.java
@@ -21,8 +21,8 @@ import org.apache.freemarker.generator.base.datasource.DataSourcesSupplier;
 import org.apache.freemarker.generator.base.file.PropertiesClassPathSupplier;
 import org.apache.freemarker.generator.base.file.PropertiesFileSystemSupplier;
 import org.apache.freemarker.generator.base.file.PropertiesSupplier;
-import org.apache.freemarker.generator.base.parameter.ParameterModelSupplier;
 
+import java.util.Map;
 import java.util.function.Supplier;
 
 /**
@@ -61,8 +61,8 @@ public class Suppliers {
         return new DataModelSupplier(settings.getDataModels());
     }
 
-    public static ParameterModelSupplier parameterSupplier(Settings settings) {
-        return new ParameterModelSupplier(settings.getParameters());
+    public static Supplier<Map<String, Object>> parameterSupplier(Settings settings) {
+        return settings::getParameters;
     }
 
     public static PropertiesSupplier propertiesSupplier(String fileName) {
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/task/FreeMarkerTask.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/task/FreeMarkerTask.java
index 549078c..803b9c2 100644
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/task/FreeMarkerTask.java
+++ b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/task/FreeMarkerTask.java
@@ -89,7 +89,7 @@ public class FreeMarkerTask implements Callable<Integer> {
     public Integer call() {
         final Template template = template(settings, configurationSupplier);
         try (Writer writer = settings.getWriter(); DataSources dataSources = dataSources(settings, dataSourcesSupplier)) {
-            final Map<String, Object> dataModel = dataModel(settings, dataSources, parameterModelSupplier, dataModelsSupplier, toolsSupplier);
+            final Map<String, Object> dataModel = dataModel(dataSources, parameterModelSupplier, dataModelsSupplier, toolsSupplier);
             template.process(dataModel, writer);
             return SUCCESS;
         } catch (RuntimeException e) {
@@ -140,18 +140,15 @@ public class FreeMarkerTask implements Callable<Integer> {
     }
 
     private static Map<String, Object> dataModel(
-            Settings settings,
             DataSources dataSources,
             Supplier<Map<String, Object>> parameterModelSupplier,
             Supplier<Map<String, Object>> dataModelsSupplier,
             Supplier<Map<String, Object>> tools) {
         final Map<String, Object> result = new HashMap<>();
-
         result.putAll(dataModelsSupplier.get());
         result.put(DATASOURCES, dataSources);
         result.putAll(parameterModelSupplier.get());
         result.putAll(tools.get());
-
         return result;
     }
 
diff --git a/freemarker-generator-cli/src/site/markdown/cli/concepts/named-uris.md b/freemarker-generator-cli/src/site/markdown/cli/concepts/named-uris.md
index 2a2469e..7ab78e8 100644
--- a/freemarker-generator-cli/src/site/markdown/cli/concepts/named-uris.md
+++ b/freemarker-generator-cli/src/site/markdown/cli/concepts/named-uris.md
@@ -18,13 +18,13 @@ scheme     authority               path        query   fragment
 
 For our purposes, the scheme and the path components are especially important, though the other components are used by certain datasources for particular purposes.
 
-| Component | Purpose |
-|-----------|---------|
-| scheme	| All datasources require a scheme (except for file when using relative paths) |
-| authority	| Used only by remote datasources, and can be omitted in some of those cases. Consists of userinfo (user:pass), host, and port. |
-| path	    | Can be omitted, but usually used as the basis of the locator for the datasource. |
-| query	    | Used mainly for HTTP and HTTPS URLs |
-| fragment	| Used rarely for providing additional attributes, e.g. `mimetype` of `charset` |
+| Component | Purpose                                                                                                   |
+|-----------|-----------------------------------------------------------------------------------------------------------|
+| scheme	| All datasources require a scheme (except for file when using relative paths)                              |
+| authority	| Used only by remote datasources, and can be omitted in some of those cases.                               |
+| path	    | Can be omitted, but usually used as the basis of the locator for the datasource.                          |
+| query	    | Used mainly for HTTP and HTTPS URLs                                                                       |
+| fragment	| Used rarely for providing additional attributes, e.g. `mimetype` of `charset`                             |
 
 The following Named URI loads a "user.csv" and the data source is available as `my_users` 
 
diff --git a/freemarker-generator-cli/src/site/markdown/cli/concepts/user-parameters.md b/freemarker-generator-cli/src/site/markdown/cli/concepts/user-parameters.md
new file mode 100644
index 0000000..46f2d2e
--- /dev/null
+++ b/freemarker-generator-cli/src/site/markdown/cli/concepts/user-parameters.md
@@ -0,0 +1,37 @@
+# User-Supplied Parameters
+
+User-supplied parameters allow to pass additional information to an Apache FreeMarker template 
+
+* `-Pname=value` to define a key/value pair
+* `-Pname:group=value` to define a map containing key/value pairs, i.e nested map 
+
+Pass a simple name/value pair on the command line 
+
+```
+> bin/freemarker-cli -t templates/info.ftl -P key=value
+
+User Supplied Parameters
+------------------------------------------------------------------------------
+- key ==> value
+```
+
+By providing a `group` you can create nested maps
+
+```
+> bin/freemarker-cli -t templates/info.ftl -P foo1:group=bar1 -P foo2:group=bar2
+
+User Supplied Parameters
+------------------------------------------------------------------------------
+- group ==> { foo1=bar1 foo2=bar2 }
+```
+
+It is also possible to mix and match the two approaches
+
+```
+> bin/freemarker-cli -t templates/info.ftl -P foo1:group=bar1 -P foo2:group=bar2 -P key=value
+
+User Supplied Parameters
+------------------------------------------------------------------------------
+- key ==> value
+- group ==> { foo1=bar1 foo2=bar2 }
+```
\ No newline at end of file
diff --git a/freemarker-generator-cli/src/site/markdown/index.md b/freemarker-generator-cli/src/site/markdown/index.md
index c5807bc..791ab12 100644
--- a/freemarker-generator-cli/src/site/markdown/index.md
+++ b/freemarker-generator-cli/src/site/markdown/index.md
@@ -2,5 +2,6 @@
 
 ### Concepts
 
+* [User-Supplied Parameters](cli/concepts/user-parameters.html)
 * [Named URIs](cli/concepts/named-uris.html)
 * [Data Models](cli/concepts/data-models.html)
\ No newline at end of file
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ManualTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ManualTest.java
index c6eb230..210f32f 100644
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ManualTest.java
+++ b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ManualTest.java
@@ -28,7 +28,7 @@ public class ManualTest {
     // private static final String CMD = "-b ./src/test -l de_AT -DFOO=foo -DBAR=bar -t templates/info.ftl site/sample/csv/transactions.csv";
     // private static final String CMD = "-b ./src/test -DFOO=foo -PBAR=bar -l de -t templates/demo.ftl site/sample/csv/transactions.csv";
     // private static final String CMD = "-b ./src/test -DFOO=foo -PBAR=bar -t templates/demo.ftl site/sample/csv/transactions.csv";
-    private static final String CMD = "-b ./src/test -PCSV_OUT_FORMAT=TDF -t templates/csv/transform.ftl site/sample/csv/contract.csv";
+    // private static final String CMD = "-b ./src/test -PCSV_OUT_FORMAT=TDF -t templates/csv/transform.ftl site/sample/csv/contract.csv";
     // private static final String CMD = "-t templates/excel/csv/transform.ftl -l de_AT site/sample/excel/test.xlsx";
     // private static final String CMD = "-i ${JsonPathTool.parse(DataSources.first).read('$.info.title')} site/sample/json/swagger-spec.json";
     // private static final String CMD = "-i ${XmlTool.parse(DataSources.first)['recipients/person[1]/name']} site/sample/xml/recipients.xml";
@@ -48,7 +48,7 @@ public class ManualTest {
     // private static final String CMD = "-b ./src/test -t templates/demo.ftl -m env=./site/sample/properties/user_0001/user.properties";
     // private static final String CMD = "-b ./src/test -t templates/demo.ftl -m ./site/sample/properties/user_0001/user.properties";
     // private static final String CMD = "-b ./src/test --data-model post=https://jsonplaceholder.typicode.com/posts/2 -t templates/info.ftl";
-    // private static final String CMD = "-b ./src/test -t templates/info.ftl -P key:group=value";
+    private static final String CMD = "-b ./src/test -t templates/info.ftl -P name=value";
 
 
     public static void main(String[] args) {
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/config/SettingsTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/config/SettingsTest.java
index 0ccd737..16032e4 100644
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/config/SettingsTest.java
+++ b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/config/SettingsTest.java
@@ -42,7 +42,7 @@ public class SettingsTest {
     private static final String ANY_OUTPUT_FILE = "outputFile";
     private static final List<String> ANY_SOURCES = singletonList("sources");
     private static final String ANY_TEMPLATE_NAME = "templateName";
-    private static final Map<String, String> ANY_USER_PARAMETERS = new HashMap<>();
+    private static final Map<String, Object> ANY_USER_PARAMETERS = new HashMap<>();
     private static final Properties ANY_SYSTEM_PROPERTIES = new Properties();
 
     @Test
diff --git a/freemarker-generator-cli/templates/info.ftl b/freemarker-generator-cli/templates/info.ftl
index 01384c3..3d46398 100644
--- a/freemarker-generator-cli/templates/info.ftl
+++ b/freemarker-generator-cli/templates/info.ftl
@@ -48,8 +48,12 @@ URI : ${dataSource.uri}
 
 User Supplied Parameters
 ------------------------------------------------------------------------------
-<#list SystemTool.parameters as name,value>
-- ${name} ==> ${value}
+<#list SystemTool.parameters as key,value>
+<#if value?is_hash>
+- ${key} ==> { <#list value as name,value>${name}=${value} </#list>}
+<#else>
+- ${key} ==> ${value}
+</#if>
 </#list>
 
 User Supplied System Properties
@@ -62,7 +66,5 @@ SystemTool
 ------------------------------------------------------------------------------
 Command line         : ${SystemTool.getCommandLineArgs()?join(", ")}
 Host Name            : ${SystemTool.getHostName()}
-Java Home            : ${SystemTool.getEnv("JAVA_HOME", "N.A.")}
+Current Dir          : ${SystemTool.getEnv("PWD", "N.A.")}
 User Name            : ${SystemTool.getSystemProperty("user.name", "N.A.")}
-Timestamp            : ${SystemTool.currentTimeMillis}
-Writer               : ${SystemTool.writer.class.name}