This is an automated email from the ASF dual-hosted git repository.
sgoeschl pushed a commit to branch FREEMARKER-195
in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git
The following commit(s) were added to refs/heads/FREEMARKER-195 by this push:
new 9bc14cf FREEMARKER-195 [freemarker-generator] Cleanup code and
examples
9bc14cf is described below
commit 9bc14cf161b9c8e6bde568eb32b3e28ab237b62c
Author: Siegfried Goeschl <[email protected]>
AuthorDate: Mon Oct 4 22:43:33 2021 +0200
FREEMARKER-195 [freemarker-generator] Cleanup code and examples
---
.../generator/base/datasource/DataSources.java | 78 +++++++++++-------
.../generator/datasource/DataSourcesTest.java | 6 +-
.../src/app/examples/templates/datasources.ftl | 93 ++++++++++------------
.../generator/cli/model/DataSourcesAdapter.java | 81 ++++---------------
4 files changed, 112 insertions(+), 146 deletions(-)
diff --git
a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSources.java
b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSources.java
index e6b4c3f..129b996 100644
---
a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSources.java
+++
b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSources.java
@@ -23,6 +23,7 @@ import org.apache.freemarker.generator.base.util.Validate;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -39,24 +40,27 @@ public class DataSources implements Closeable {
/** The underlying list of data sources */
private final List<DataSource> dataSources;
+ /** Map of named data sources */
+ private final Map<String, DataSource> dataSourcesMap;
+
public DataSources(Collection<DataSource> dataSources) {
- Validate.notNull(dataSources, "No data sources provided");
- this.dataSources = new ArrayList<>(dataSources);
+ Validate.notNull(dataSources, "dataSources must not be null");
+
+ this.dataSources = Collections.unmodifiableList(new
ArrayList<>(dataSources));
+ this.dataSourcesMap =
Collections.unmodifiableMap(dataSourcesMap(dataSources));
}
/**
* Get the names of all data sources.
*
- * @return data source names
+ * @return list of data source names
*/
public List<String> getNames() {
- return dataSources.stream()
- .map(DataSource::getName)
- .collect(Collectors.toList());
+ return new ArrayList<>(dataSourcesMap.keySet());
}
/**
- * Get the requested metadata value for all data sources.
+ * Get a list of unique metadata value for all data sources.
*
* @param key key of the metadata part
* @return list of metadata values
@@ -64,13 +68,15 @@ public class DataSources implements Closeable {
public List<String> getMetadata(String key) {
return dataSources.stream()
.map(ds -> ds.getMetadata(key))
+ .filter(StringUtils::isNotEmpty)
+ .distinct()
.collect(Collectors.toList());
}
/**
- * Get a list of unique groups of all data sources.
+ * Get a list of unique group names of all data sources.
*
- * @return list of groups
+ * @return list of group names
*/
public List<String> getGroups() {
return dataSources.stream()
@@ -80,21 +86,22 @@ public class DataSources implements Closeable {
.collect(Collectors.toList());
}
+ /**
+ * Returns the number of elements in this list.
+ *
+ * @return the number of elements in this list
+ */
public int size() {
return dataSources.size();
}
- public boolean isEmpty() {
- return dataSources.isEmpty();
- }
-
/**
- * Get an array representation of the underlying data sources.
+ * Returns <tt>true</tt> if this list contains no elements.
*
- * @return list of data sources
+ * @return <tt>true</tt> if this list contains no elements
*/
- public DataSource[] toArray() {
- return dataSources.toArray(new DataSource[0]);
+ public boolean isEmpty() {
+ return dataSources.isEmpty();
}
/**
@@ -103,7 +110,7 @@ public class DataSources implements Closeable {
* @return list of data sources
*/
public List<DataSource> toList() {
- return new ArrayList<>(dataSources);
+ return dataSources;
}
/**
@@ -118,15 +125,15 @@ public class DataSources implements Closeable {
* @return linked hasp map of data sources
*/
public Map<String, DataSource> toMap() {
- return dataSources.stream().collect(Collectors.toMap(
- DataSource::getName,
- identity(),
- (ds1, ds2) -> {
- throw new IllegalStateException("Duplicate key detected
when generating map: " + ds1 + ", " + ds2);
- },
- LinkedHashMap::new));
+ return dataSourcesMap;
}
+ /**
+ * Returns the element at the specified position in this list.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ */
public DataSource get(int index) {
return dataSources.get(index);
}
@@ -160,9 +167,7 @@ public class DataSources implements Closeable {
* @see <a
href="https://commons.apache.org/proper/commons-io/javadocs/api-2.7/org/apache/commons/io/FilenameUtils.html#wildcardMatch-java.lang.String-java.lang.String-">Apache
Commons IO</a>
*/
public List<DataSource> find(String wildcard) {
- return dataSources.stream()
- .filter(dataSource -> dataSource.match("name", wildcard))
- .collect(Collectors.toList());
+ return find(DataSource.METADATA_NAME, wildcard);
}
/**
@@ -190,4 +195,21 @@ public class DataSources implements Closeable {
"dataSources=" + dataSources +
'}';
}
+
+ private static List<DataSource> getNamedDataSources(Collection<DataSource>
dataSources) {
+ return dataSources.stream()
+ .filter(dataSource ->
StringUtils.isNotEmpty(dataSource.getName()))
+ .collect(Collectors.toList());
+ }
+
+ private Map<String, DataSource> dataSourcesMap(Collection<DataSource>
dataSources) {
+ final List<DataSource> namedDataSources =
getNamedDataSources(dataSources);
+ return namedDataSources.stream().collect(Collectors.toMap(
+ DataSource::getName,
+ identity(),
+ (ds1, ds2) -> {
+ throw new IllegalStateException("Duplicate names detected
when generating data source map: " + ds1 + ", " + ds2);
+ },
+ LinkedHashMap::new));
+ }
}
diff --git
a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java
b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java
index 5dd4360..8ba7905 100644
---
a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java
+++
b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java
@@ -100,9 +100,9 @@ public class DataSourcesTest {
@Test
public void shouldGetMetadataParts() {
- assertEquals(asList("", "pom.xml", ""),
dataSources().getMetadata("fileName"));
- assertEquals(asList("default", "default", "default"),
dataSources().getMetadata("group"));
- assertEquals(asList("", "xml", ""),
dataSources().getMetadata("extension"));
+ assertEquals(asList("pom.xml"), dataSources().getMetadata("fileName"));
+ assertEquals(asList("default"), dataSources().getMetadata("group"));
+ assertEquals(asList("xml"), dataSources().getMetadata("extension"));
assertEquals(asList("unknown", "pom.xml", "server.invalid?foo=bar"),
dataSources().getMetadata("name"));
}
diff --git
a/freemarker-generator-cli/src/app/examples/templates/datasources.ftl
b/freemarker-generator-cli/src/app/examples/templates/datasources.ftl
index 57445ce..32d58b5 100644
--- a/freemarker-generator-cli/src/app/examples/templates/datasources.ftl
+++ b/freemarker-generator-cli/src/app/examples/templates/datasources.ftl
@@ -1,19 +1,19 @@
<#ftl output_format="plainText" strip_whitespace=true>
<#--
- 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.
+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.
-->
Support FreeMarker Directives
==============================================================================
@@ -23,33 +23,33 @@ dataSources?size: ${dataSources?size}
Use FTL Array-style Access
==============================================================================
<#if dataSources?has_content>
- dataSources[0]: ${dataSources[0].name}
+dataSources[0]: ${dataSources[0].name}
<#else>
- No data sources provided ...
+No data sources provided ...
</#if>
Iterate Over DataSources as List
==============================================================================
<#list dataSources as dataSource>
- dataSource[${dataSource?index}] => ${dataSource.uri}<#lt>
+- dataSource[${dataSource?index}] => ${dataSource.name}<#lt>
</#list>
Iterate Over DataSources as Map
==============================================================================
<#list dataSources as name, dataSource>
- dataSource["${name}"] => ${dataSource.uri}<#lt>
+- dataSource["${name}"] => ${dataSource.name}<#lt>
</#list>
Iterate Over DataSources as Values
==============================================================================
-<#list dataSources as dataSource>
- dataSource[${dataSource?index}] => ${dataSource.uri}<#lt>
+<#list dataSources?values as dataSource>
+- dataSource[${dataSource?index}] => ${dataSource.name}<#lt>
</#list>
Get Document Names As Keys
==============================================================================
<#list dataSources?keys as name>
- - ${name}<#lt>
+- ${name}<#lt>
</#list>
Access Underlying DataSources API
@@ -61,39 +61,34 @@ DataSources.find(): ${dataSources?api.find("*")?size}
Iterate Over DataSources Using Wildcard Search
==============================================================================
<#if dataSources?has_content>
- <#list dataSources?api.find("*") as dataSource>
- - ${dataSource.name}
- </#list>
+<#list dataSources?api.find("*") as dataSource>
+- ${dataSource.name}
+</#list>
<#else>
- No data sources provided ...
+No data sources provided ...
</#if>
<#if dataSources?has_content>
- <#list dataSources as dataSource>
- [#${dataSource?counter}] - ${dataSource.name}
-
==============================================================================
+<#list dataSources as dataSource>
+[#${dataSource?counter}] - ${dataSource.name}
+==============================================================================
- Invoke Arbitrary Methods On DataSource
-
---------------------------------------------------------------------------
- <#assign dataSource=dataSources?first>
- Name : ${dataSource.name}
- Nr of lines : ${dataSource.lines?size}
- Content Type : ${dataSource.contentType}
- Charset : ${dataSource.charset}
- Extension : ${dataSource.extension}
- Nr of chars : ${dataSource.text?length}
- Nr of bytes : ${dataSource.bytes?size}
+Invoke Arbitrary Methods On DataSource
+---------------------------------------------------------------------------
+<#assign dataSource=dataSources?first>
+Name : ${dataSource.name}
+Nr of lines : ${dataSource.lines?size}
+Content Type : ${dataSource.contentType}
+Charset : ${dataSource.charset}
+Extension : ${dataSource.extension}
+Nr of chars : ${dataSource.text?length}
+Nr of bytes : ${dataSource.bytes?size}
- Iterating Over Metadata Of A Datasource
-
---------------------------------------------------------------------------
- <#list dataSource.metadata as name, value>
- ${name?right_pad(19)} : ${value}
- </#list>
+Iterating Over Metadata Of A Datasource
+---------------------------------------------------------------------------
+<#list dataSource.metadata as name, value>
+${name?right_pad(19)} : ${value}
+</#list>
- Iterating Over Properties Of A Datasource
-
---------------------------------------------------------------------------
- <#list dataSource.properties as name, value>
- ${name?right_pad(19)} : ${value}
- </#list>
- </#list>
+</#list>
</#if>
\ No newline at end of file
diff --git
a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/model/DataSourcesAdapter.java
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/model/DataSourcesAdapter.java
index 39e903b..3f49654 100644
---
a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/model/DataSourcesAdapter.java
+++
b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/model/DataSourcesAdapter.java
@@ -16,8 +16,6 @@
*/
package org.apache.freemarker.generator.cli.model;
-import freemarker.core._DelayedJQuote;
-import freemarker.core._TemplateModelException;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.MapKeyValuePairIterator;
@@ -31,23 +29,23 @@ import freemarker.template.TemplateModelWithAPISupport;
import freemarker.template.TemplateSequenceModel;
import freemarker.template.WrappingTemplateModel;
import freemarker.template.utility.ObjectWrapperWithAPISupport;
-import org.apache.freemarker.generator.base.datasource.DataSource;
import org.apache.freemarker.generator.base.datasource.DataSources;
import java.io.Serializable;
-import java.util.Map;
-import java.util.SortedMap;
+
+import static java.util.Objects.requireNonNull;
/**
- * Wraps a map of <code>DataSorces</code> into a FreeMarker template model
- * providing sequence and hash type access.
+ * Wraps an instance of <code>DataSources</code> into a FreeMarker template
model
+ * providing sequence and hash type access. If required the
<code>DataSources</code>
+ * API can be accessed using FreeMarkers "?api" built-in.
*/
public class DataSourcesAdapter extends WrappingTemplateModel
implements TemplateHashModelEx2, AdapterTemplateModel,
WrapperTemplateModel, TemplateModelWithAPISupport, TemplateSequenceModel,
Serializable {
+ /** Wrapped instance */
private final DataSources dataSources;
- private final Map<String, DataSource> map;
/**
* Factory method for creating new adapter instances.
@@ -61,92 +59,43 @@ public class DataSourcesAdapter extends
WrappingTemplateModel
}
private DataSourcesAdapter(DataSources dataSources, ObjectWrapper wrapper)
{
- super(wrapper);
- this.dataSources = dataSources;
- this.map = dataSources.toMap();
+ super(requireNonNull(wrapper));
+ this.dataSources = requireNonNull(dataSources);
}
@Override
public TemplateModel get(String key) throws TemplateModelException {
- Object val;
- try {
- val = map.get(key);
- } catch (ClassCastException e) {
- throw new _TemplateModelException(e,
- "ClassCastException while getting Map entry with String
key ",
- new _DelayedJQuote(key));
- } catch (NullPointerException e) {
- throw new _TemplateModelException(e,
- "NullPointerException while getting Map entry with String
key ",
- new _DelayedJQuote(key));
- }
-
- if (val == null) {
- // Check for Character key if this is a single-character string.
- // In SortedMap-s, however, we can't do that safely, as it can
cause ClassCastException.
- if (key.length() == 1 && !(map instanceof SortedMap)) {
- final Character charKey = key.charAt(0);
- try {
- val = map.get(charKey);
- if (val == null) {
- final TemplateModel wrappedNull = wrap(null);
- if (wrappedNull == null || !(map.containsKey(key) ||
map.containsKey(charKey))) {
- return null;
- } else {
- return wrappedNull;
- }
- }
- } catch (ClassCastException e) {
- throw new _TemplateModelException(e,
- "Class casting exception while getting Map entry
with Character key ",
- new _DelayedJQuote(charKey));
- } catch (NullPointerException e) {
- throw new _TemplateModelException(e,
- "NullPointerException while getting Map entry with
Character key ",
- new _DelayedJQuote(charKey));
- }
- } else { // No char key fallback was possible
- final TemplateModel wrappedNull = wrap(null);
- if (wrappedNull == null || !map.containsKey(key)) {
- return null;
- } else {
- return wrappedNull;
- }
- }
- }
-
- return wrap(val);
+ return wrap(dataSources.toMap().get(key));
}
@Override
public boolean isEmpty() {
- return map.isEmpty();
+ return dataSources.isEmpty();
}
@Override
public int size() {
- return map.size();
+ return dataSources.size();
}
@Override
public TemplateCollectionModel keys() {
- return new SimpleCollection(map.keySet(), getObjectWrapper());
+ return new SimpleCollection(dataSources.toMap().keySet(),
getObjectWrapper());
}
@Override
public TemplateCollectionModel values() {
- return new SimpleCollection(map.values(), getObjectWrapper());
+ return new SimpleCollection(dataSources.toMap().values(),
getObjectWrapper());
}
@Override
public KeyValuePairIterator keyValuePairIterator() {
- return new MapKeyValuePairIterator(map, getObjectWrapper());
+ return new MapKeyValuePairIterator(dataSources.toMap(),
getObjectWrapper());
}
@Override
public TemplateModel get(int index) throws TemplateModelException {
- final DataSource[] array = this.dataSources.toArray();
- return index >= 0 && index < array.length ? wrap(array[index]) : null;
+ return index >= 0 && index < dataSources.size() ?
wrap(dataSources.get(index)) : null;
}
@Override