From 5d59eada29da92f26d77b3229bc1296112754f79 Mon Sep 17 00:00:00 2001 From: John Montgomery Date: Fri, 15 Apr 2011 10:01:40 +0100 Subject: [PATCH] Added compiler option to provide defaults for missing values Call missingVariableValue(value) on a Compiler object to get a new version that will insert "value" for missing values (rather than throwing an exception). Useful when you have templates you would rather generated *something* instead of erroring or for when objects may have null values themselves. --- .../com/samskivert/mustache/Mustache.java | 24 +++++++++++++------ .../com/samskivert/mustache/Template.java | 6 +++++ .../com/samskivert/mustache/MustacheTest.java | 21 ++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/samskivert/mustache/Mustache.java b/src/main/java/com/samskivert/mustache/Mustache.java index ad01eae..aca61cf 100644 --- a/src/main/java/com/samskivert/mustache/Mustache.java +++ b/src/main/java/com/samskivert/mustache/Mustache.java @@ -38,6 +38,9 @@ public class Mustache /** Whether or not standards mode is enabled. */ public final boolean standardsMode; + /** Replace missnig values with this value - if null will throw an exception on missing values. */ + public final String missingVariableValue; + /** The template loader in use during this compilation. */ public final TemplateLoader loader; @@ -53,24 +56,32 @@ public class Mustache /** Returns a compiler that either does or does not escape HTML by default. */ public Compiler escapeHTML (boolean escapeHTML) { - return new Compiler(escapeHTML, this.standardsMode, this.loader); + return new Compiler(escapeHTML, this.standardsMode, this.missingVariableValue, 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, this.loader); + return new Compiler(this.escapeHTML, standardsMode, this.missingVariableValue, this.loader); + } + + /** + * Returns a compiler that will replace missing variables with the given value + **/ + public Compiler missingVariableValue (String missingVariableValue) { + return new Compiler(this.escapeHTML, this.standardsMode, missingVariableValue, this.loader); } /** 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); + return new Compiler(this.escapeHTML, this.standardsMode, this.missingVariableValue, loader); } - protected Compiler (boolean escapeHTML, boolean standardsMode, TemplateLoader loader) { + protected Compiler (boolean escapeHTML, boolean standardsMode, String missingVariableValue, TemplateLoader loader) { this.escapeHTML = escapeHTML; this.standardsMode = standardsMode; + this.missingVariableValue = missingVariableValue; this.loader = loader; } } @@ -88,7 +99,7 @@ public class Mustache */ public static Compiler compiler () { - return new Compiler(true, false, FAILING_LOADER); + return new Compiler(true, false, null, FAILING_LOADER); } /** @@ -468,8 +479,7 @@ public class Mustache _escapeHTML = escapeHTML; } @Override public void execute (Template tmpl, Template.Context ctx, Writer out) { - Object value = tmpl.getValue(ctx, _name, _line); - // TODO: configurable behavior on missing values + Object value = tmpl.getValueWithDefault(ctx, _name, _line); if (value == null) { throw new MustacheException( "No key, method or field with name '" + _name + "' on line " + _line); diff --git a/src/main/java/com/samskivert/mustache/Template.java b/src/main/java/com/samskivert/mustache/Template.java index 2abf193..5ef2950 100644 --- a/src/main/java/com/samskivert/mustache/Template.java +++ b/src/main/java/com/samskivert/mustache/Template.java @@ -126,6 +126,12 @@ public class Template return null; } + protected Object getValueWithDefault (Context ctx, String name, int line) + { + Object value = getValue(ctx, name, line); + return value != null? value : _compiler.missingVariableValue; + } + protected Object getValueIn (Object data, String name, int line) { if (data == null) { diff --git a/src/test/java/com/samskivert/mustache/MustacheTest.java b/src/test/java/com/samskivert/mustache/MustacheTest.java index d710d48..f215023 100644 --- a/src/test/java/com/samskivert/mustache/MustacheTest.java +++ b/src/test/java/com/samskivert/mustache/MustacheTest.java @@ -284,6 +284,27 @@ public class MustacheTest "parentProperty", "bar")); } + @Test(expected = MustacheException.class) + public void testMissingValue () { + String tmpl = "{{ missing }} {{ notmissing }}"; + Mustache.compiler().compile(tmpl). + execute(Collections.singletonMap("notmissing", "bar")); + } + + @Test public void testMissingValueWithDefault () { + String tmpl = "{{ missing }}{{ notmissing }}"; + String result = Mustache.compiler().missingVariableValue("").compile(tmpl). + execute(Collections.singletonMap("notmissing", "bar")); + assertEquals("bar", result); + } + + @Test public void testMissingValueWithDefaultNonEmptyString () { + String tmpl = "{{ missing }}{{ notmissing }}"; + String result = Mustache.compiler().missingVariableValue("foo").compile(tmpl). + execute(Collections.singletonMap("notmissing", "bar")); + assertEquals("foobar", result); + } + protected void test (Mustache.Compiler compiler, String expected, String template, Object ctx) { assertEquals(expected, compiler.compile(template).execute(ctx));