Cleaned up contributed template loading support. Moved MustacheTemplateLoader

into inner interface Mustache.TemplateLoader, eliminated top-level
UnsupportedTemplateLoader. Eliminated static configuration of active template
loader in favor of per-Compiler configured template loader, which is how all
other configuration is handled.More complex tests are needed, but will have to
wait until I'm less sleep deprived.
This commit is contained in:
Michael Bayne
2011-04-13 11:49:59 -07:00
parent e8641ba4fa
commit ce389bd293
4 changed files with 43 additions and 61 deletions
@@ -30,49 +30,65 @@ import java.util.List;
public class Mustache
{
/** An interface to the Mustache compilation process. See {@link Mustache}. */
public static class Compiler {
public static class Compiler
{
/** Whether or not HTML entities are escaped by default. */
public final boolean escapeHTML;
/** Whether or not standards mode is enabled. */
public final boolean standardsMode;
/** The template loader in use during this compilation. */
public final TemplateLoader loader;
/** Compiles the supplied template into a repeatedly executable intermediate form. */
public Template compile (String template)
{
public Template compile (String template) {
return compile(new StringReader(template));
}
/** Compiles the supplied template into a repeatedly executable intermediate form. */
public Template compile (Reader source)
{
public Template compile (Reader source) {
return Mustache.compile(source, this);
}
/** Returns a compiler that either does or does not escape HTML by default. */
public Compiler escapeHTML (boolean escapeHTML) {
return new Compiler(escapeHTML, this.standardsMode);
return new Compiler(escapeHTML, this.standardsMode, this.loader);
}
/** Returns a compiler that either does or does not use standards mode. Standards mode
* disables the non-standard JMustache extensions like looking up missing names in a parent
* context. */
public Compiler standardsMode (boolean standardsMode) {
return new Compiler(this.escapeHTML, standardsMode);
return new Compiler(this.escapeHTML, standardsMode, this.loader);
}
protected Compiler (boolean escapeHTML, boolean standardsMode) {
/** Returns a compiler configured to use the supplied template loader to handle partials. */
public Compiler withLoader (TemplateLoader loader) {
return new Compiler(this.escapeHTML, this.standardsMode, loader);
}
protected Compiler (boolean escapeHTML, boolean standardsMode, TemplateLoader loader) {
this.escapeHTML = escapeHTML;
this.standardsMode = standardsMode;
this.loader = loader;
}
}
/** Used to handle partials. */
public interface TemplateLoader
{
/** Returns a reader for the template with the supplied name.
* @throws Exception if the template could not be loaded for any reason. */
public Reader getTemplate (String name) throws Exception;
}
/**
* Returns a compiler that escapes HTML by default and does not use standards mode.
*/
public static Compiler compiler ()
{
return new Compiler(true, false);
return new Compiler(true, false, FAILING_LOADER);
}
/**
@@ -244,12 +260,6 @@ public class Mustache
protected static final int MATCHING_END = 2;
protected static final int TAG = 3;
private static MustacheTemplateLoader templateLoader = UnsupportedTemplateLoader.INSTANCE;
public static void setTemplateLoader(MustacheTemplateLoader _templateLoader) {
templateLoader = _templateLoader;
}
protected static class Accumulator {
public Accumulator (Compiler compiler) {
_compiler = compiler;
@@ -296,7 +306,7 @@ public class Mustache
case '>':
_segs.add(new IncludedTemplateSegment(tag1, _compiler));
return this;
case '^':
requireNoNewlines(tag, tagLine);
return new Accumulator(_compiler) {
@@ -377,7 +387,7 @@ public class Mustache
protected static class IncludedTemplateSegment extends Template.Segment {
public IncludedTemplateSegment (final String templateName, final Compiler compiler) {
try {
template = compiler.compile(templateLoader.getTemplate(templateName));
template = compiler.compile(compiler.loader.getTemplate(templateName));
} catch (Exception e) {
throw new IllegalArgumentException("unable to load " + templateName, e);
}
@@ -387,7 +397,7 @@ public class Mustache
}
private final Template template;
}
/** A helper class for named segments. */
protected static abstract class NamedSegment extends Template.Segment {
protected NamedSegment (String name, int line) {
@@ -509,4 +519,10 @@ public class Mustache
{ "<", "&lt;" },
{ ">", "&gt;" },
};
protected static final TemplateLoader FAILING_LOADER = new TemplateLoader() {
public Reader getTemplate (String name) {
throw new UnsupportedOperationException("Template loading not configured");
}
};
}
@@ -1,19 +0,0 @@
package com.samskivert.mustache;
import java.io.Reader;
/**
*
* @author Sean Scanlon <sean.scanlon@gmail.com>
*/
public interface MustacheTemplateLoader {
/**
* load a {@code Mustache} template from a given file.
*
* @param filename
* @return a string {@code Mustache} template
*/
public Reader getTemplate(String filename) throws Exception;
}
@@ -1,19 +0,0 @@
package com.samskivert.mustache;
import java.io.Reader;
/**
* loading partials/other templates is not supported. in this {@link MustacheTemplateLoader}
*
* @author Sean Scanlon <sean.scanlon@gmail.com>
*
*/
public enum UnsupportedTemplateLoader implements MustacheTemplateLoader {
INSTANCE;
public Reader getTemplate(String filename) {
throw new UnsupportedOperationException("template loading is not supported");
}
}
@@ -28,12 +28,11 @@ public class MustacheTest
@Test
public void testTemplateIncludeBehavior () {
Mustache.setTemplateLoader(new MustacheTemplateLoader() {
public Reader getTemplate(String filename) {
test(Mustache.compiler().withLoader(new Mustache.TemplateLoader() {
public Reader getTemplate (String name) {
return new StringReader("inside:{{bar}}");
}
});
test("foo inside:foo foo", "{{bar}} {{>foo}} {{bar}}", context("bar", "foo"));
}), "foo inside:foo foo", "{{bar}} {{>foo}} {{bar}}", context("bar", "foo"));
}
@Test public void testSimpleVariable () {
@@ -275,9 +274,14 @@ public class MustacheTest
"parentProperty", "bar"));
}
protected void test (Mustache.Compiler compiler, String expected, String template, Object ctx)
{
assertEquals(expected, compiler.compile(template).execute(ctx));
}
protected void test (String expected, String template, Object ctx)
{
assertEquals(expected, Mustache.compiler().compile(template).execute(ctx));
test(Mustache.compiler(), expected, template, ctx);
}
protected static Object context (Object... data)