Access Array item by index in template

This commit is contained in:
Mickael Jeanroy
2013-10-05 22:26:14 +02:00
parent 3af55c2660
commit 98c7a5d38f
2 changed files with 74 additions and 1 deletions
@@ -7,8 +7,12 @@ package com.samskivert.mustache;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@@ -139,7 +143,18 @@ public class Template
} }
// once we step into a composite key, we drop the ability to query our parent // once we step into a composite key, we drop the ability to query our parent
// contexts; that would be weird and confusing // contexts; that would be weird and confusing
data = getValueIn(data, comps[ii].intern(), line); String next = comps[ii].intern();
Integer idx = toNumber(next);
if (idx != null) {
Object nextData = null;
List<Object> c = toList(data);
if (c != null && idx >= 0 && idx < c.size()) {
nextData = c.get(idx);
}
data = nextData;
} else {
data = getValueIn(data, next, line);
}
} }
return checkForMissing(name, line, missingIsNull, data); return checkForMissing(name, line, missingIsNull, data);
} }
@@ -169,6 +184,30 @@ public class Template
return checkForMissing(name, line, missingIsNull, NO_FETCHER_FOUND); return checkForMissing(name, line, missingIsNull, NO_FETCHER_FOUND);
} }
protected static List<Object> toList(Object obj) {
if (obj instanceof Collection) {
return new ArrayList<Object>((Collection) obj);
} else if (obj instanceof Iterator) {
Iterator<Object> it = (Iterator<Object>) obj;
List<Object> lst = new ArrayList<Object>();
while (it.hasNext()) {
lst.add(it.next());
}
return lst;
} else if (obj instanceof Object[]) {
return Arrays.asList((Object[]) obj);
}
return null;
}
protected static Integer toNumber(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException ex) {
return null;
}
}
/** /**
* Returns the value of the specified variable, noting that it is intended to be used as the * Returns the value of the specified variable, noting that it is intended to be used as the
* contents for a segment. Presently this does not do anything special, but eventually this * contents for a segment. Presently this does not do anything special, but eventually this
@@ -87,18 +87,52 @@ public class MustacheTest
"foo", Arrays.asList(context("bar", "baz"), context("bar", "bif")))); "foo", Arrays.asList(context("bar", "baz"), context("bar", "bif"))));
} }
@Test public void testListIndexSection() {
test("baz", "{{#foo.0}}{{bar}}{{/foo.0}}", context(
"foo", Arrays.asList(context("bar", "baz"), context("bar", "bif"))));
}
@Test public void testListItemSection() {
test("baz", "{{foo.0.bar}}", context(
"foo", Arrays.asList(context("bar", "baz"), context("bar", "bif"))));
}
@Test public void testArraySection () { @Test public void testArraySection () {
test("bazbif", "{{#foo}}{{bar}}{{/foo}}", test("bazbif", "{{#foo}}{{bar}}{{/foo}}",
context("foo", new Object[] { context("foo", new Object[] {
context("bar", "baz"), context("bar", "bif") })); context("bar", "baz"), context("bar", "bif") }));
} }
@Test public void testArrayIndexSection () {
test("baz", "{{#foo.0}}{{bar}}{{/foo.0}}",
context("foo", new Object[] {
context("bar", "baz"), context("bar", "bif") }));
}
@Test public void testArrayItemSection () {
test("baz", "{{foo.0.bar}}",
context("foo", new Object[] {
context("bar", "baz"), context("bar", "bif") }));
}
@Test public void testIteratorSection () { @Test public void testIteratorSection () {
test("bazbif", "{{#foo}}{{bar}}{{/foo}}", test("bazbif", "{{#foo}}{{bar}}{{/foo}}",
context("foo", Arrays.asList(context("bar", "baz"), context("foo", Arrays.asList(context("bar", "baz"),
context("bar", "bif")).iterator())); context("bar", "bif")).iterator()));
} }
@Test public void testIteratorIndexSection () {
test("baz", "{{#foo.0}}{{bar}}{{/foo.0}}",
context("foo", Arrays.asList(context("bar", "baz"),
context("bar", "bif")).iterator()));
}
@Test public void testIteratorItemSection () {
test("baz", "{{foo.0.bar}}",
context("foo", Arrays.asList(context("bar", "baz"),
context("bar", "bif")).iterator()));
}
@Test public void testEmptyListSection () { @Test public void testEmptyListSection () {
test("", "{{#foo}}{{bar}}{{/foo}}", context("foo", Collections.emptyList())); test("", "{{#foo}}{{bar}}{{/foo}}", context("foo", Collections.emptyList()));
} }