Revamped iterating over arrays to be GWT-compatible.
We no longer use reflection for any of that; we have a suite of primitive array helpers that do what is needed.
This commit is contained in:
@@ -3,9 +3,7 @@
|
||||
|
||||
package com.samskivert.mustache;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -13,17 +11,6 @@ import java.util.Map;
|
||||
*/
|
||||
public class DefaultCollector extends BasicCollector
|
||||
{
|
||||
@Override
|
||||
public Iterator<?> toIterator (final Object value) {
|
||||
Iterator<?> iter = super.toIterator(value);
|
||||
if (iter != null) return iter;
|
||||
|
||||
if (value.getClass().isArray()) {
|
||||
return Arrays.asList((Object[])value).iterator();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K,V> Map<K,V> createFetcherCache () {
|
||||
return new HashMap<K,V>();
|
||||
|
||||
@@ -22,6 +22,15 @@ public abstract class BasicCollector implements Mustache.Collector
|
||||
if (value instanceof Iterator<?>) {
|
||||
return (Iterator<?>)value;
|
||||
}
|
||||
if (value.getClass().isArray()) {
|
||||
final ArrayHelper helper = arrayHelper(value);
|
||||
return new Iterator<Object>() {
|
||||
private int _count = helper.length(value), _idx;
|
||||
@Override public boolean hasNext () { return _idx < _count; }
|
||||
@Override public Object next () { return helper.get(value, _idx++); }
|
||||
@Override public void remove () { throw new UnsupportedOperationException(); }
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -36,15 +45,7 @@ public abstract class BasicCollector implements Mustache.Collector
|
||||
if (c >= '0' && c <= '9') {
|
||||
if (ctx instanceof List<?>) return LIST_FETCHER;
|
||||
if (ctx instanceof Iterator<?>) return ITER_FETCHER;
|
||||
if (ctx instanceof Object[]) return OBJECT_ARRAY_FETCHER;
|
||||
if (ctx instanceof boolean[]) return BOOLEAN_ARRAY_FETCHER;
|
||||
if (ctx instanceof byte[]) return BYTE_ARRAY_FETCHER;
|
||||
if (ctx instanceof char[]) return CHAR_ARRAY_FETCHER;
|
||||
if (ctx instanceof short[]) return SHORT_ARRAY_FETCHER;
|
||||
if (ctx instanceof int[]) return INT_ARRAY_FETCHER;
|
||||
if (ctx instanceof long[]) return LONG_ARRAY_FETCHER;
|
||||
if (ctx instanceof float[]) return FLOAT_ARRAY_FETCHER;
|
||||
if (ctx instanceof double[]) return DOUBLE_ARRAY_FETCHER;
|
||||
if (ctx.getClass().isArray()) return arrayHelper(ctx);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -54,6 +55,19 @@ public abstract class BasicCollector implements Mustache.Collector
|
||||
* a standard {@link Map} implementation or something like {@code ConcurrentHashMap}. */
|
||||
public abstract <K,V> Map<K,V> createFetcherCache ();
|
||||
|
||||
protected static ArrayHelper arrayHelper (Object ctx) {
|
||||
if (ctx instanceof Object[]) return OBJECT_ARRAY_HELPER;
|
||||
if (ctx instanceof boolean[]) return BOOLEAN_ARRAY_HELPER;
|
||||
if (ctx instanceof byte[]) return BYTE_ARRAY_HELPER;
|
||||
if (ctx instanceof char[]) return CHAR_ARRAY_HELPER;
|
||||
if (ctx instanceof short[]) return SHORT_ARRAY_HELPER;
|
||||
if (ctx instanceof int[]) return INT_ARRAY_HELPER;
|
||||
if (ctx instanceof long[]) return LONG_ARRAY_HELPER;
|
||||
if (ctx instanceof float[]) return FLOAT_ARRAY_HELPER;
|
||||
if (ctx instanceof double[]) return DOUBLE_ARRAY_HELPER;
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() {
|
||||
public Object get (Object ctx, String name) throws Exception {
|
||||
Map<?,?> map = (Map<?,?>)ctx;
|
||||
@@ -87,7 +101,13 @@ public abstract class BasicCollector implements Mustache.Collector
|
||||
}
|
||||
};
|
||||
|
||||
protected static abstract class ArrayFetcher implements Mustache.VariableFetcher {
|
||||
protected static final Mustache.VariableFetcher THIS_FETCHER = new Mustache.VariableFetcher() {
|
||||
public Object get (Object ctx, String name) throws Exception {
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
|
||||
protected static abstract class ArrayHelper implements Mustache.VariableFetcher {
|
||||
public Object get (Object ctx, String name) throws Exception {
|
||||
try {
|
||||
return get(ctx, Integer.parseInt(name));
|
||||
@@ -97,40 +117,44 @@ public abstract class BasicCollector implements Mustache.Collector
|
||||
return Template.NO_FETCHER_FOUND;
|
||||
}
|
||||
}
|
||||
public abstract int length (Object ctx);
|
||||
protected abstract Object get (Object ctx, int index);
|
||||
}
|
||||
|
||||
protected static final ArrayFetcher OBJECT_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper OBJECT_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((Object[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((Object[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher BOOLEAN_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper BOOLEAN_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((boolean[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((boolean[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher BYTE_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper BYTE_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((byte[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((byte[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher CHAR_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper CHAR_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((char[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((char[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher SHORT_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper SHORT_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((short[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((short[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher INT_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper INT_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((int[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((int[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher LONG_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper LONG_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((long[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((long[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher FLOAT_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper FLOAT_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((float[])ctx)[index]; }
|
||||
@Override public int length (Object ctx) { return ((float[])ctx).length; }
|
||||
};
|
||||
protected static final ArrayFetcher DOUBLE_ARRAY_FETCHER = new ArrayFetcher() {
|
||||
protected static final ArrayHelper DOUBLE_ARRAY_HELPER = new ArrayHelper() {
|
||||
@Override protected Object get (Object ctx, int index) { return ((double[])ctx)[index]; }
|
||||
};
|
||||
|
||||
protected static final Mustache.VariableFetcher THIS_FETCHER = new Mustache.VariableFetcher() {
|
||||
public Object get (Object ctx, String name) throws Exception {
|
||||
return ctx;
|
||||
}
|
||||
@Override public int length (Object ctx) { return ((double[])ctx).length; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,24 +20,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class DefaultCollector extends BasicCollector
|
||||
{
|
||||
@Override
|
||||
public Iterator<?> toIterator (final Object value) {
|
||||
Iterator<?> iter = super.toIterator(value);
|
||||
if (iter != null) return iter;
|
||||
|
||||
if (value.getClass().isArray()) {
|
||||
return new AbstractList<Object>() {
|
||||
public int size () {
|
||||
return Array.getLength(value);
|
||||
}
|
||||
public Object get (int idx) {
|
||||
return Array.get(value, idx);
|
||||
}
|
||||
}.iterator();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
|
||||
Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);
|
||||
|
||||
Reference in New Issue
Block a user