Modified compound variables to honor null/default configuration. Closes #10.

Kali/Bertrand convinced me that being consistent with other Mustache
implementations is more important than whatever wacky reasons I was harboring
for keeping compound variables different than singleton sections.
This commit is contained in:
Michael Bayne
2011-10-29 14:38:56 -07:00
parent 37884af44d
commit adf116992c
4 changed files with 40 additions and 44 deletions
@@ -85,9 +85,7 @@ public class Mustache
/** Returns a compiler that will use the given value for any variable that is missing, or
* otherwise resolves to null. This is like {@link #nullValue} except that it returns the
* supplied default for missing keys and existing keys that return null values. Note that
* regardless of whether a null or default value is configured, if the resolution of part
* of a compound key results in a missing or null value, an exception will be raised. */
* supplied default for missing keys and existing keys that return null values. */
public Compiler defaultValue (String defaultValue) {
return new Compiler(this.escapeHTML, this.standardsMode, defaultValue, true,
this.loader, this.collector);
@@ -103,10 +101,7 @@ public class Mustache
* <li>In the case of a {@link Map} being used as a context, all possible accessors are
* assumed to exist (but potentially return null), and no exception will ever be
* raised.</li>
* </ul>
* Note that regardless of whether a null or default value is configured, if the resolution
* of part of a compound key results in a missing or null value, an exception will be
* raised. */
* </ul> */
public Compiler nullValue (String nullValue) {
return new Compiler(this.escapeHTML, this.standardsMode, nullValue, false,
this.loader, this.collector);
@@ -93,13 +93,12 @@ public class Template
Object data = getValue(ctx, comps[0].intern(), line, missingIsNull);
for (int ii = 1; ii < comps.length; ii++) {
if (data == NO_FETCHER_FOUND) {
throw new NullPointerException(
if (!missingIsNull) throw new MustacheException(
"Missing context for compound variable '" + name + "' on line " + line +
". '" + comps[ii - 1] + "' was not found.");
return null;
} else if (data == null) {
throw new NullPointerException(
"Null context for compound variable '" + name + "' on line " + line +
". '" + comps[ii - 1] + "' resolved to null.");
return null;
}
// once we step into a composite key, we drop the ability to query our parent
// contexts; that would be weird and confusing
@@ -214,12 +213,9 @@ public class Template
protected Object checkForMissing (String name, int line, boolean missingIsNull, Object value)
{
if (value == NO_FETCHER_FOUND) {
if (missingIsNull) {
return null;
} else {
throw new MustacheException(
"No method or field with name '" + name + "' on line " + line);
}
if (missingIsNull) return null;
throw new MustacheException(
"No method or field with name '" + name + "' on line " + line);
} else {
return value;
}
@@ -259,7 +259,7 @@ public class MustacheTest
execute(context("things", Arrays.asList("bar", "baz", "bif"))));
}
@Test public void testStructuredVariable () {
@Test public void testCompoundVariable () {
test("hello", "{{foo.bar.baz}}", new Object() {
Object foo () {
return new Object() {
@@ -271,25 +271,39 @@ public class MustacheTest
});
}
@Test(expected=NullPointerException.class)
@Test(expected=MustacheException.class)
public void testNullComponentInCompoundVariable () {
// make sure that even if we have a null value configured, we freak out
test(Mustache.compiler().nullValue("foo"), "unused", "{{foo.bar.baz}}", new Object() {
Object foo () {
return new Object() {
Object bar = null;
};
}
test(Mustache.compiler(), "unused", "{{foo.bar.baz}}", new Object() {
Object foo = new Object() {
Object bar = null;
};
});
}
@Test(expected=NullPointerException.class)
@Test(expected=MustacheException.class)
public void testMissingComponentInCompoundVariable () {
// make sure that even if we have a default value configured, we freak out
test(Mustache.compiler().defaultValue("foo"), "unused", "{{foo.bar.baz}}", new Object() {
Object foo () {
return new Object(); // no bar
}
test(Mustache.compiler(), "unused", "{{foo.bar.baz}}", new Object() {
Object foo = new Object(); // no bar
});
}
public void testNullComponentInCompoundVariableWithDefault () {
test(Mustache.compiler().nullValue("null"), "null", "{{foo.bar.baz}}", new Object() {
Object foo = null;
});
test(Mustache.compiler().nullValue("null"), "null", "{{foo.bar.baz}}", new Object() {
Object foo = new Object() {
Object bar = null;
};
});
}
public void testMissingComponentInCompoundVariableWithDefault () {
test(Mustache.compiler().defaultValue("?"), "?", "{{foo.bar.baz}}", new Object() {
// no foo, no bar
});
test(Mustache.compiler().defaultValue("?"), "?", "{{foo.bar.baz}}", new Object() {
Object foo = new Object(); // no bar
});
}