package com.laytonsmith.PureUtilities.Common;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A utility class for building templates using a standard template format.
* The format is limited, but very simple to use. Templates start with two percent
* signs, and end with two percent signs. Arguments may also be passed in. First,
* the template name is given, followed by the pipe character, with the first argument,
* followed by pipe characters separating each argument, finally closing out with
* two percent signs.
*
* This is a simple, no argument template: %%template%%
* This is a one argument template: %%template|arg1%%
* This is a two argument template: %%template|arg1|arg2%%
*
* On the implementation side, the template name and generator are provided. Once
* the template is encountered in the text, the generator is triggered, and the
* text to replace the template is returned.
*/
public class TemplateBuilder {
private final Map<String, Generator> templates;
private static final Pattern PATTERN = Pattern.compile("%%([^\\|%]+)([^%]*?)%%");
private boolean silentFail = true;
/**
* Creates a new TemplateBuilder with no templates in it.
*/
public TemplateBuilder(){
templates = new HashMap<>();
}
/**
* Creates a new TemplateBuilder with the given templates in it.
* @param templates
*/
public TemplateBuilder(Map<String, Generator> templates){
this.templates = new HashMap<>(templates);
}
/**
* Adds a new template to this builder.
* @param name
* @param replacement
*/
public void addTemplate(String name, Generator replacement){
templates.put(name, replacement);
}
/**
* Removes the specified template from this builder.
* @param name
*/
public void removeTemplate(String name){
templates.remove(name);
}
/**
* Sets the silent fail flag. This flag determines whether or not the build
* method will throw an exception if a template is asked for which does not
* exist. If the state is false, (the default) then the template engine will
* silently fail, and replace the template tag with an empty string.
* @param silentFail
*/
public void setSilentFail(boolean silentFail){
this.silentFail = silentFail;
}
/**
* Given the input with possible template tags, parses and replaces any
* templates, returning the rendered string.
* @param template
* @throws IllegalArgumentException If the silent fail flag is false, and
* the input text contains a template which does not exist.
* @return
*/
public String build(String template) throws IllegalArgumentException {
Matcher m = PATTERN.matcher(template);
StringBuilder templateBuilder = new StringBuilder();
int lastMatch = 0;
boolean appended = false;
while(m.find()){
if(!appended){
templateBuilder.append(template.substring(lastMatch, m.start()));
appended = true;
}
String name = m.group(1);
// for(String templateName : templates.keySet()){
// if(templateName.equals(name)){
// templateBuilder.append(templates.get(name));
// lastMatch = m.end();
// appended = false;
// //template = template.replaceAll("%%" + Pattern.quote(name) + ".*?%%", customTemplates.get(name));
// }
// }
String [] tmplArgs = new String[0];
if(m.group(2) != null && !m.group(2).equals("")){
//We have arguments
//remove the initial |, then split
tmplArgs = m.group(2).substring(1).split("\\|");
}
if(templates.containsKey(name)){
String templateValue = templates.get(name).generate(tmplArgs);
templateBuilder.append(templateValue);
} else {
if(!silentFail){
throw new IllegalArgumentException("Template with name \"" + name + "\" was found in the input"
+ " text, but no such template exists.");
}
}
lastMatch = m.end();
appended = false;
}
if(!appended){
templateBuilder.append(template.substring(lastMatch));
}
return templateBuilder.toString();
}
public static interface Generator {
String generate(String ... args);
}
}