package com.floreysoft.jmte.token; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import com.floreysoft.jmte.TemplateContext; import com.floreysoft.jmte.util.Util; public class ForEachToken extends ExpressionToken { public static final String FOREACH = "foreach"; private final String varName; private final String separator; private transient Iterator<Object> iterator; private transient int index; public ForEachToken(String expression, String varName, String separator) { super(expression); this.varName = varName; this.separator = separator != null ? separator : ""; this.index = -1; } public ForEachToken(List<String> segments, String expression, String varName, String separator) { super(segments, expression); this.varName = varName; this.separator = separator != null ? separator : ""; this.index = -1; } @Override public String getText() { if (text == null) { text = FOREACH + " " + getExpression() + " " + varName + ((separator == null || separator.isEmpty()) ? "" : " " + separator); } return text; } @Override @SuppressWarnings("unchecked") public Object evaluate(TemplateContext context) { Object value = evaluatePlain(context); final Iterable<Object> iterable; if (value == null) { iterable = Collections.emptyList(); } else if (value instanceof Map) { iterable = ((Map) value).entrySet(); } else if (value instanceof Iterable) { iterable = ((Iterable) value); } else { List<Object> arrayAsList = Util.arrayAsList(value); if (arrayAsList != null) { iterable = arrayAsList; } else { // we have a single value here and simply wrap it in a List iterable = Collections.singletonList(value); } } return iterable; } public Iterator<Object> iterator() { return getIterator(); } public String getVarName() { return varName; } public String getSeparator() { return separator; } public boolean isLast() { return !iterator().hasNext(); } public boolean isFirst() { return index == 0; } public int getIndex() { return index; } public void setIterable(Iterable<Object> iterable) { this.iterator = iterable.iterator(); } public void setIterator(Iterator<Object> iterator) { this.iterator = iterator; } public Iterator<Object> getIterator() { return iterator; } public Object advance() { index++; return iterator.next(); } public void resetIndex() { index = -1; } }