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 {