org.bndtools.templating.engine.mustache.MustacheTemplateEngine Maven / Gradle / Ivy
The newest version!
package org.bndtools.templating.engine.mustache;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import org.bndtools.templating.Resource;
import org.bndtools.templating.ResourceMap;
import org.bndtools.templating.ResourceType;
import org.bndtools.templating.StringResource;
import org.bndtools.templating.TemplateEngine;
import org.eclipse.core.runtime.IProgressMonitor;
import org.osgi.service.component.annotations.Component;
import com.github.mustachejava.DefaultMustacheFactory;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Instructions;
import aQute.lib.io.IO;
@Component(name = "org.bndtools.templating.engine.mustache", property = {
"name=mustache", "version=0.8.18"
})
public class MustacheTemplateEngine implements TemplateEngine {
private static final String TEMPLATE_PROPERTIES = "_template.properties";
private static final String DEFAULT_PROPERTIES = "_defaults.properties";
private static final String DEFAULT_LEFT_DELIM = "{{";
private static final String DEFAULT_RIGHT_DELIM = "}}";
private static class TemplateSettings {
String leftDelim = DEFAULT_LEFT_DELIM;
String rightDelim = DEFAULT_RIGHT_DELIM;
Instructions preprocessMatch = new Instructions("*");
Instructions ignore = null;
private TemplateSettings() {}
static TemplateSettings readFrom(Properties props) {
TemplateSettings settings = new TemplateSettings();
if (props != null) {
settings.leftDelim = props.getProperty("leftDelim", DEFAULT_LEFT_DELIM);
settings.rightDelim = props.getProperty("rightDelim", DEFAULT_RIGHT_DELIM);
String process = props.getProperty("process", Constants.DEFAULT_PREPROCESSS_MATCHERS);
String processBefore = props.getProperty("process.before", null);
if (processBefore != null)
process = processBefore + ", " + process;
String processAfter = props.getProperty("process.after", null);
if (processAfter != null)
process = process + ", " + processAfter;
settings.preprocessMatch = new Instructions(process);
String ignore = props.getProperty("ignore", null);
settings.ignore = ignore != null ? new Instructions(ignore) : null;
}
return settings;
}
}
@Override
public Map getTemplateParameters(ResourceMap inputs, IProgressMonitor monitor) throws Exception {
final Map params = new HashMap<>();
final Properties defaults = readDefaults(inputs);
TemplateSettings settings = readSettings(inputs);
DefaultMustacheFactory factory = new DefaultMustacheFactory();
AccumulateNamesObjectHandler namesAccumulator = new AccumulateNamesObjectHandler(factory.getObjectHandler());
factory.setObjectHandler(namesAccumulator);
int counter = 0;
for (Entry entry : inputs.entries()) {
String inputPath = entry.getKey();
factory.compile(new StringReader(inputPath), "mapping", settings.leftDelim, settings.rightDelim)
.execute(new StringWriter(), Collections.emptyMap());
Resource source = entry.getValue();
if (settings.ignore == null || !settings.ignore.matches(inputPath)) {
if (source.getType() == ResourceType.File && settings.preprocessMatch.matches(inputPath)) {
try (Reader reader = IO.reader(source.getContent(), source.getTextEncoding())) {
factory.compile(reader, "temp" + (counter++), settings.leftDelim, settings.rightDelim)
.execute(new StringWriter(), Collections.emptyMap())
.toString();
}
}
}
}
for (String param : namesAccumulator.getNames()) {
params.put(param, defaults.getProperty(param));
}
return params;
}
@Override
public ResourceMap generateOutputs(ResourceMap inputs, Map> parameters,
IProgressMonitor monitor) throws Exception {
TemplateSettings settings = readSettings(inputs);
Properties defaults = readDefaults(inputs);
ResourceMap outputs = new ResourceMap();
final Map flattenedParams = flattenParameters(parameters);
applyDefaults(defaults, flattenedParams);
DefaultMustacheFactory mustacheFactory = new DefaultMustacheFactory();
mustacheFactory.setObjectHandler(new CheckMissingObjectHandler(mustacheFactory.getObjectHandler()));
for (Entry entry : inputs.entries()) {
String inputPath = entry.getKey();
Resource source = entry.getValue();
StringWriter writer = new StringWriter();
mustacheFactory.compile(new StringReader(inputPath), "mapping", settings.leftDelim, settings.rightDelim)
.execute(writer, flattenedParams);
String outputPath = writer.toString();
if (settings.ignore == null || !settings.ignore.matches(inputPath)) {
Resource output;
switch (source.getType()) {
case Folder :
output = source;
break;
case File :
if (settings.preprocessMatch.matches(inputPath)) {
// This file should be processed with the template
// engine
try (Reader reader = IO.reader(source.getContent(), source.getTextEncoding())) {
StringWriter rendered = new StringWriter();
mustacheFactory.compile(reader, outputPath, settings.leftDelim, settings.rightDelim)
.execute(rendered, flattenedParams);
output = new StringResource(rendered.toString());
}
} else {
// This file should be directly copied
output = source;
}
break;
default :
throw new IllegalArgumentException("Unknown resource type " + source.getType());
}
outputs.put(outputPath, output);
}
}
return outputs;
}
private static void applyDefaults(Properties defaults, Map params) {
for (Enumeration> defaultsEnum = defaults.propertyNames(); defaultsEnum.hasMoreElements();) {
String name = (String) defaultsEnum.nextElement();
String value = defaults.getProperty(name, null);
if (!params.containsKey(name))
params.put(name, value);
}
}
private static TemplateSettings readSettings(ResourceMap inputs) throws IOException, UnsupportedEncodingException {
Properties settingsProp = new Properties();
Resource settingsResource = inputs.remove(TEMPLATE_PROPERTIES);
if (settingsResource != null) {
if (settingsResource.getType() != ResourceType.File)
throw new IllegalArgumentException(
String.format("Template settings resource %s must be a file; found resource type %s.",
TEMPLATE_PROPERTIES, settingsResource.getType()));
try (Reader reader = new InputStreamReader(settingsResource.getContent(),
settingsResource.getTextEncoding())) {
settingsProp.load(reader);
}
}
TemplateSettings settings = TemplateSettings.readFrom(settingsProp);
return settings;
}
private static Properties readDefaults(ResourceMap inputs) throws IOException {
Properties props = new Properties();
Resource defaultsResource = inputs.remove(DEFAULT_PROPERTIES);
if (defaultsResource != null) {
if (defaultsResource.getType() != ResourceType.File)
throw new IllegalArgumentException(
String.format("Default properties resource %s must be a file; found resource type %s",
DEFAULT_PROPERTIES, defaultsResource.getType()));
try (Reader reader = new InputStreamReader(defaultsResource.getContent(),
defaultsResource.getTextEncoding())) {
props.load(reader);
}
}
return props;
}
private static Map flattenParameters(Map> parameters) {
Map flattened = new HashMap<>(parameters.size());
for (Entry> entry : parameters.entrySet()) {
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy