Last active
July 3, 2016 15:07
-
-
Save juangamnik/74260c068e918935994c9720108b8897 to your computer and use it in GitHub Desktop.
Enhancing Mustache via an if-statement with EL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package info.mustacheexample; | |
import com.github.mustachejava.*; | |
import javax.el.*; | |
import java.beans.FeatureDescriptor; | |
import java.io.IOException; | |
import java.io.StringReader; | |
import java.io.StringWriter; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
import java.util.function.Function; | |
public class MustacheExample { | |
public static void main(String[] args) { | |
// helper function for evaluating the end of the expression by counting | |
// opening and closing braces. | |
final Function<String, Integer> calcEndIndexOfExpression = s -> { | |
int i = 0; | |
int open = 0; | |
for(char c : s.toCharArray()) { | |
switch(c) { | |
case '(': | |
open++; | |
break; | |
case ')': | |
open--; | |
break; | |
} | |
if(open == 0) { | |
return i; | |
} | |
i++; | |
} | |
return -1; | |
}; | |
// The template to evaluate | |
final String template = | |
"a is {{#if}}(a <= 3)not {{/if}}greater than three. " + | |
"b is {{#if}}(b <= (4 + 1))not {{/if}}greater than 5."; | |
StringWriter sw = new StringWriter(); | |
// the context for the el expression. | |
final Map<String, Object> context = new HashMap<>(); | |
context.put("a", 100); | |
context.put("b", 5); | |
final ExpressionFactory factory = ExpressionFactory.newInstance(); | |
final ELContext elContext = new MustacheELContext(context); | |
final Map<String, TemplateFunction> functions = new HashMap<>(); | |
// add a template function to mustache evaluating `{{#if}}` expressions. | |
functions.put("if", str -> { | |
// extract the expression. | |
final Integer endIndex = calcEndIndexOfExpression.apply(str); | |
if (endIndex <= 0) { | |
return str; | |
} | |
final String expression = str.substring(1, endIndex); | |
// evaluate the expression (only boolean expressions are allowed). | |
if((Boolean) factory.createValueExpression(elContext, | |
"${" + expression + "}", Boolean.class) | |
.getValue(elContext)) { | |
final String content = str.substring(endIndex + 1); | |
return content; | |
} | |
return ""; | |
}); | |
// Execute the complete example. | |
try { | |
final MustacheFactory mf = new DefaultMustacheFactory(); | |
final Mustache mustache = mf.compile(new StringReader(template), null); | |
mustache.execute(sw, new Object[] {context, functions}).flush(); | |
} | |
catch (NumberFormatException | IOException | MustacheException e) { | |
throw new IllegalArgumentException(e); | |
} | |
// prints: a is greater than three. b is not greater than 5. | |
System.out.println(sw.toString()); | |
} | |
private static class MustacheELContext extends ELContext { | |
private MustacheELResolver resolver; | |
private MustacheELContext(Object o) { | |
this.resolver = new MustacheELResolver(o); | |
} | |
@Override | |
public VariableMapper getVariableMapper() { | |
return null; | |
} | |
@Override | |
public FunctionMapper getFunctionMapper() { | |
return null; | |
} | |
@Override | |
public ELResolver getELResolver() { | |
return resolver; | |
} | |
} | |
private static class MustacheELResolver extends ELResolver { | |
private CompositeELResolver delegate = new CompositeELResolver(); | |
private Object o; | |
public MustacheELResolver(Object o) { | |
this.o = o; | |
delegate.add(new MapELResolver(true)); | |
delegate.add(new BeanELResolver(true)); | |
} | |
@Override | |
public Class<?> getCommonPropertyType(ELContext arg0, Object base) { | |
if (base == null) { | |
base = o; | |
} | |
return delegate.getCommonPropertyType(arg0, base); | |
} | |
@Override | |
public Iterator<FeatureDescriptor> getFeatureDescriptors( | |
ELContext arg0, Object base) { | |
if (base == null) | |
base = o; | |
return delegate.getFeatureDescriptors(arg0, base); | |
} | |
@Override | |
public Class<?> getType(ELContext arg0, Object base, Object arg2) { | |
if (base == null) | |
base = o; | |
return delegate.getType(arg0, base, arg2); | |
} | |
@Override | |
public Object getValue(ELContext arg0, Object base, Object arg2) { | |
if (base == null) | |
base = o; | |
return delegate.getValue(arg0, base, arg2); | |
} | |
@Override | |
public boolean isReadOnly(ELContext arg0, Object base, Object arg2) { | |
if (base == null) { | |
base = o; | |
} | |
return delegate.isReadOnly(arg0, base, arg2); | |
} | |
@Override | |
public void setValue(ELContext arg0, Object base, Object arg2, | |
Object arg3) { | |
if (base == null) | |
base = o; | |
delegate.setValue(arg0, base, arg2, arg3); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>info.mustacheexample</groupId> | |
<artifactId>mustache-example</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-compiler-plugin</artifactId> | |
<version>3.5.1</version> | |
<configuration> | |
<source>1.8</source> | |
<target>1.8</target> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
<dependencies> | |
<dependency> | |
<groupId>com.github.spullara.mustache.java</groupId> | |
<artifactId>compiler</artifactId> | |
<version>0.9.1</version> | |
</dependency> | |
<dependency> | |
<groupId>org.eclipse.jetty.orbit</groupId> | |
<artifactId>com.sun.el</artifactId> | |
<version>2.2.0.v201303151357</version> | |
</dependency> | |
<dependency> | |
<groupId>javax.el</groupId> | |
<artifactId>javax.el-api</artifactId> | |
<version>2.2.4</version> | |
<type>jar</type> | |
</dependency> | |
</dependencies> | |
</project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment