package org.jtwig.render.node.renderer;
import org.jtwig.model.tree.ForLoopNode;
import org.jtwig.render.RenderRequest;
import org.jtwig.render.expression.CalculateExpressionService;
import org.jtwig.render.node.RenderNodeService;
import org.jtwig.renderable.Renderable;
import org.jtwig.renderable.impl.CompositeRenderable;
import org.jtwig.util.LoopCursor;
import org.jtwig.value.WrappedCollection;
import org.jtwig.value.context.StaticVariableValueContext;
import org.jtwig.value.context.ValueContext;
import org.jtwig.value.convert.Converter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
public class ForLoopNodeRender implements NodeRender<ForLoopNode> {
public static final String LOOP = "loop";
@Override
public Renderable render(RenderRequest request, ForLoopNode node) {
Converter<WrappedCollection> collectionConverter = request.getEnvironment().getValueEnvironment().getCollectionConverter();
RenderNodeService renderNodeService = request.getEnvironment().getRenderEnvironment().getRenderNodeService();
CalculateExpressionService calculateExpressionService = request.getEnvironment().getRenderEnvironment().getCalculateExpressionService();
Object collectionJtwigValue = calculateExpressionService.calculate(request, node.getExpression());
WrappedCollection valueCollection = collectionConverter.convert(collectionJtwigValue).or(WrappedCollection.singleton(collectionJtwigValue));
if (valueCollection == null) valueCollection = WrappedCollection.empty();
ValueContext parentContext = request.getRenderContext().getCurrent(ValueContext.class);
LoopCursor loopCursor = new LoopCursor(parentContext, valueCollection);
StaticVariableValueContext newValueContext = new StaticVariableValueContext(parentContext, LOOP, loopCursor);
request.getRenderContext().start(ValueContext.class, newValueContext);
Iterator<Map.Entry<String, Object>> iterator = valueCollection.iterator();
Collection<Renderable> renderables = new ArrayList<>(valueCollection.size());
while (iterator.hasNext()) {
Map.Entry<String, Object> item = iterator.next();
newValueContext.with(node.getVariableExpression().getIdentifier(), item.getValue());
if (node.getKeyVariableExpression().isPresent()) {
newValueContext.with(node.getKeyVariableExpression().get().getIdentifier(), item.getKey());
}
renderables.add(renderNodeService.render(request, node.getContent()));
loopCursor.step();
}
request.getRenderContext().end(ValueContext.class);
return new CompositeRenderable(renderables);
}
}