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

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


The following commit(s) were added to refs/heads/FREEMARKER-188 by this push:
     new ef26ea0  FREEMARKER-188 First cut of implementation is working
ef26ea0 is described below

commit ef26ea094cbade271004b30a891cc07685f95133
Author: Siegfried Goeschl <[email protected]>
AuthorDate: Tue Sep 7 22:06:33 2021 +0200

    FREEMARKER-188 First cut of implementation is working
---
 .../base/datasource/DataSourceLoaderFactory.java   | 19 +++---
 .../freemarker/generator/base/util/ListUtils.java  | 19 +++++-
 .../cli/config/output/AbstractOutputGenerator.java | 64 +++++++++++++++++++
 .../config/output/GeneratingOutputGenerator.java   | 72 +++++++++++++++++++++-
 .../generator/cli/task/FreeMarkerTask.java         | 12 ++--
 .../generator/cli/util/TemplateSourceFactory.java  | 34 ++++++++++
 .../freemarker/generator/cli/ManualTest.java       |  6 +-
 7 files changed, 204 insertions(+), 22 deletions(-)

diff --git 
a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceLoaderFactory.java
 
b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceLoaderFactory.java
index 1bdf8d5..2e061bb 100644
--- 
a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceLoaderFactory.java
+++ 
b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceLoaderFactory.java
@@ -28,17 +28,12 @@ import java.util.Arrays;
  */
 public abstract class DataSourceLoaderFactory {
 
-    private static DataSourceLoader dataSourceLoader;
-
-    public static synchronized DataSourceLoader create() {
-        if (dataSourceLoader == null) {
-            dataSourceLoader = new DefaultDataSourceLoader(
-                    Arrays.asList(
-                            new FileDataSourceLoader(),
-                            new HttpDataSourceLoader(),
-                            new EnvironmentDataSourceLoader()
-                    ));
-        }
-        return dataSourceLoader;
+    public static DataSourceLoader create() {
+        return new DefaultDataSourceLoader(
+                Arrays.asList(
+                        new FileDataSourceLoader(),
+                        new HttpDataSourceLoader(),
+                        new EnvironmentDataSourceLoader()
+                ));
     }
 }
diff --git 
a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/util/ListUtils.java
 
b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/util/ListUtils.java
index 4ec6fbc..08ccd5b 100644
--- 
a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/util/ListUtils.java
+++ 
b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/util/ListUtils.java
@@ -17,8 +17,11 @@
 package org.apache.freemarker.generator.base.util;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 public class ListUtils {
 
@@ -57,10 +60,24 @@ public class ListUtils {
      * @param <T>  the type of the array
      * @return copied array
      */
-    public static <T> T coalesce(List<T> list) {
+    public static <T> T coalesce(Collection<T> list) {
         return list.stream()
                 .filter(Objects::nonNull)
                 .findFirst()
                 .orElse(null);
     }
+
+    /**
+     * Concatenate an array of lists.
+     *
+     * @param lists array of lists
+     * @param <T>   the type of the array
+     * @return concatenated list
+     */
+    @SafeVarargs
+    public static <T> List<T> concatenate(Collection<T>... lists) {
+        return Stream.of(lists)
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+    }
 }
diff --git 
a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/AbstractOutputGenerator.java
 
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/AbstractOutputGenerator.java
new file mode 100644
index 0000000..e654ecb
--- /dev/null
+++ 
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/AbstractOutputGenerator.java
@@ -0,0 +1,64 @@
+package org.apache.freemarker.generator.cli.config.output;
+
+import org.apache.freemarker.generator.base.FreeMarkerConstants.Location;
+import org.apache.freemarker.generator.base.datasource.DataSource;
+import org.apache.freemarker.generator.base.datasource.DataSourceFactory;
+import org.apache.freemarker.generator.base.datasource.DataSourcesSupplier;
+import org.apache.freemarker.generator.base.util.NonClosableWriterWrapper;
+import org.apache.freemarker.generator.base.util.UriUtils;
+import org.apache.freemarker.generator.cli.config.DataModelSupplier;
+import org.apache.freemarker.generator.cli.config.Settings;
+import org.apache.freemarker.generator.cli.picocli.OutputGeneratorDefinition;
+
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static 
org.apache.freemarker.generator.base.FreeMarkerConstants.DEFAULT_GROUP;
+import static 
org.apache.freemarker.generator.base.FreeMarkerConstants.Location.STDIN;
+import static 
org.apache.freemarker.generator.base.mime.Mimetypes.MIME_TEXT_PLAIN;
+
+public abstract class AbstractOutputGenerator {
+
+    protected List<DataSource> dataSources(Settings settings, 
OutputGeneratorDefinition outputGeneratorDefinition) {
+        final ArrayList<DataSource> result = new ArrayList<>();
+
+        // Add optional data source from STDIN at the start of the list since
+        // this allows easy sequence slicing in FreeMarker.
+        if (settings.isReadFromStdin()) {
+            result.add(0, stdinDataSource());
+        }
+
+        final DataSourcesSupplier outputGeneratorDataSourcesSupplier = new 
DataSourcesSupplier(
+                outputGeneratorDefinition.getDataSources(),
+                settings.getSourceIncludePattern(),
+                settings.getSourceExcludePattern(),
+                settings.getInputEncoding()
+        );
+
+        result.addAll(outputGeneratorDataSourcesSupplier.get());
+
+        return result;
+    }
+
+    protected Map<String, Object> dataModels(OutputGeneratorDefinition 
outputGeneratorDefinition) {
+        return new 
DataModelSupplier(outputGeneratorDefinition.getDataModels()).get();
+    }
+
+    protected Writer stdoutWriter(Charset outputEncoding) {
+        // avoid closing System.out after rendering the template
+        return new BufferedWriter(new NonClosableWriterWrapper(new 
OutputStreamWriter(System.out, outputEncoding)));
+    }
+
+    private static DataSource stdinDataSource() {
+        final URI uri = UriUtils.toUri(Location.SYSTEM, STDIN);
+        return DataSourceFactory.fromInputStream(STDIN, DEFAULT_GROUP, uri, 
System.in, MIME_TEXT_PLAIN, UTF_8, new HashMap<>());
+    }
+}
diff --git 
a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/GeneratingOutputGenerator.java
 
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/GeneratingOutputGenerator.java
index c6d3ddd..c90fd64 100644
--- 
a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/GeneratingOutputGenerator.java
+++ 
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/config/output/GeneratingOutputGenerator.java
@@ -16,15 +16,31 @@
  */
 package org.apache.freemarker.generator.cli.config.output;
 
+import org.apache.freemarker.generator.base.datasource.DataSource;
 import org.apache.freemarker.generator.base.output.OutputGenerator;
+import org.apache.freemarker.generator.base.template.TemplateOutput;
+import org.apache.freemarker.generator.base.template.TemplateSource;
+import org.apache.freemarker.generator.base.util.ListUtils;
+import org.apache.freemarker.generator.base.util.StringUtils;
+import org.apache.freemarker.generator.base.util.Validate;
 import org.apache.freemarker.generator.cli.config.Settings;
+import org.apache.freemarker.generator.cli.config.Suppliers;
 import org.apache.freemarker.generator.cli.picocli.OutputGeneratorDefinition;
+import org.apache.freemarker.generator.cli.picocli.TemplateOutputDefinition;
+import org.apache.freemarker.generator.cli.picocli.TemplateSourceDefinition;
+import org.apache.freemarker.generator.cli.util.TemplateSourceFactory;
 
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Function;
 
-public class GeneratingOutputGenerator implements 
Function<OutputGeneratorDefinition, List<OutputGenerator>> {
+public class GeneratingOutputGenerator
+        extends AbstractOutputGenerator
+        implements Function<OutputGeneratorDefinition, List<OutputGenerator>> {
 
     private final Settings settings;
 
@@ -33,7 +49,57 @@ public class GeneratingOutputGenerator implements 
Function<OutputGeneratorDefini
     }
 
     @Override
-    public List<OutputGenerator> apply(OutputGeneratorDefinition 
outputGeneratorDefinition) {
-        return Collections.emptyList();
+    public List<OutputGenerator> apply(OutputGeneratorDefinition definition) {
+        Validate.notNull(definition, "definition must not be null");
+
+        final List<OutputGenerator> result = new ArrayList<>();
+        final TemplateSourceDefinition templateSourceDefinition = 
definition.getTemplateSourceDefinition();
+        final TemplateOutputDefinition templateOutputDefinition = 
definition.getTemplateOutputDefinition();
+        final Map<String, Object> dataModels = super.dataModels(definition);
+        final List<DataSource> dataSources = super.dataSources(settings, 
definition);
+        final List<DataSource> sharedDataSources = 
Suppliers.sharedDataSourcesSupplier(settings).get();
+        final List<DataSource> combinedDataSources = 
ListUtils.concatenate(dataSources, sharedDataSources);
+        final TemplateSource templateSource = 
TemplateSourceFactory.create(templateSourceDefinition, 
settings.getTemplateEncoding());
+
+        for (DataSource dataSource : combinedDataSources) {
+            final TemplateOutput templateOutput = 
templateOutput(templateOutputDefinition, settings, dataSource);
+            final OutputGenerator outputGenerator = new OutputGenerator(
+                    templateSource,
+                    templateOutput,
+                    Collections.singletonList(dataSource),
+                    dataModels
+            );
+            result.add(outputGenerator);
+        }
+
+        return result;
+    }
+
+    private TemplateOutput templateOutput(TemplateOutputDefinition 
templateOutputDefinition, Settings settings, DataSource dataSource) {
+        final Charset outputEncoding = settings.getOutputEncoding();
+        final File templateOutputFile = 
templateOutputFile(templateOutputDefinition, dataSource);
+        if (settings.getCallerSuppliedWriter() != null) {
+            return 
TemplateOutput.fromWriter(settings.getCallerSuppliedWriter());
+        } else if (templateOutputFile != null) {
+            return TemplateOutput.fromFile(templateOutputFile, outputEncoding);
+        } else {
+            return TemplateOutput.fromWriter(stdoutWriter(outputEncoding));
+        }
+    }
+
+    private File templateOutputFile(TemplateOutputDefinition 
templateOutputDefinition, DataSource dataSource) {
+        if (templateOutputDefinition == null || 
!templateOutputDefinition.hasOutput()) {
+            return null;
+        }
+
+        final File outputDirectory = new 
File(templateOutputDefinition.outputs.get(0));
+        final String relativeFilePath = dataSource.getRelativeFilePath();
+        final String fileName = dataSource.getBaseName() + ".html";
+
+        if (StringUtils.isEmpty(relativeFilePath)) {
+            return new File(outputDirectory, fileName);
+        } else {
+            return new File(outputDirectory, relativeFilePath + "/" + 
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 4ae0377..ab04339 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
@@ -25,6 +25,7 @@ import 
org.apache.freemarker.generator.base.datasource.DataSources;
 import org.apache.freemarker.generator.base.output.OutputGenerator;
 import org.apache.freemarker.generator.base.template.TemplateOutput;
 import org.apache.freemarker.generator.base.template.TemplateSource;
+import org.apache.freemarker.generator.base.util.ListUtils;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -33,14 +34,11 @@ import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import static java.util.Objects.requireNonNull;
 import static org.apache.freemarker.generator.base.FreeMarkerConstants.Model;
@@ -108,8 +106,12 @@ public class FreeMarkerTask implements Callable<Integer> {
     }
 
     private static DataSources toDataSources(OutputGenerator outputGenerator, 
List<DataSource> sharedDataSources) {
-        return new DataSources(Stream.of(outputGenerator.getDataSources(), 
sharedDataSources)
-                .flatMap(Collection::stream).collect(Collectors.toList()));
+        // TODO FREEMARKER-188 06.09.2021 sgoeschl - make this more explicit
+        if (outputGenerator.getDataSources().isEmpty()) {
+            return new 
DataSources(ListUtils.concatenate(outputGenerator.getDataSources(), 
sharedDataSources));
+        } else {
+            return new DataSources(outputGenerator.getDataSources());
+        }
     }
 
     @SafeVarargs
diff --git 
a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/util/TemplateSourceFactory.java
 
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/util/TemplateSourceFactory.java
new file mode 100644
index 0000000..ae39a92
--- /dev/null
+++ 
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/util/TemplateSourceFactory.java
@@ -0,0 +1,34 @@
+package org.apache.freemarker.generator.cli.util;
+
+import org.apache.freemarker.generator.base.FreeMarkerConstants.Location;
+import org.apache.freemarker.generator.base.datasource.DataSource;
+import org.apache.freemarker.generator.base.datasource.DataSourceLoader;
+import org.apache.freemarker.generator.base.datasource.DataSourceLoaderFactory;
+import org.apache.freemarker.generator.base.template.TemplateSource;
+import org.apache.freemarker.generator.base.util.Validate;
+import org.apache.freemarker.generator.cli.picocli.TemplateSourceDefinition;
+
+import java.io.File;
+import java.nio.charset.Charset;
+
+public class TemplateSourceFactory {
+
+    public static TemplateSource create(TemplateSourceDefinition 
templateSourceDefinition, Charset charset) {
+        Validate.notNull(templateSourceDefinition, "templateSourceDefinition 
must not be null");
+        Validate.notNull(charset, "charset must not be null");
+
+        final String template = templateSourceDefinition.template;
+        final DataSourceLoader dataSourceLoader = 
DataSourceLoaderFactory.create();
+
+        if (templateSourceDefinition.isInteractiveTemplate()) {
+            return TemplateSource.fromCode(Location.INTERACTIVE, 
templateSourceDefinition.interactiveTemplate);
+        } else if (new File(template).exists()) {
+            final String templateSource = templateSourceDefinition.template;
+            try (DataSource dataSource = 
dataSourceLoader.load(templateSource)) {
+                return TemplateSource.fromCode(dataSource.getName(), 
dataSource.getText(charset.name()));
+            }
+        } else {
+            return TemplateSource.fromPath(template, charset);
+        }
+    }
+}
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 b9cce26..64705a0 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
@@ -24,7 +24,11 @@ import java.io.IOException;
 public class ManualTest extends AbstractMainTest {
 
     // private static final String CMD = "-V";
-    private static final String CMD = "-t 
src/app/examples/templates/datasources.ftl 
transactions:csv=src/app/examples/data/csv/transactions.csv#delimiter=TAB 
https://xkcd.com/info.0.json envvars=env:///";
+    private static final String CMD =
+            "-M generate " +
+                    "-o target/out " +
+                    "-t freemarker-generator/csv/html/transform.ftl " +
+                    "src/app/examples/data/csv";
 
     @Override
     public String execute(String commandLine) throws IOException {

Reply via email to