@Override
public final ProcessorResult processElement(final Arguments arguments, final Element element) {
final NestableNode parentNode = element.getParent();
final IterationSpec iterationSpec =
getIterationSpec(arguments, element);
final boolean removeHostIterationElement =
removeHostIterationElement(arguments, element);
final String iteratedElementName =
getIteratedElementName(arguments, element);
final String iterVar = iterationSpec.getIterVarName();
final String statusVar = iterationSpec.getStatusVarName();
final Object iteratedObject = iterationSpec.getIteratedObject();
final List<?> list = EvaluationUtil.evaluateAsIterable(iteratedObject);
final int size = list.size();
int index = 0;
for (final Object obj : list) {
Element iterElement = null;
if (removeHostIterationElement) {
// We can safely clone the host element because we will remove it below
iterElement = (Element) element.cloneNode(parentNode, false);
} else {
// We do not clone the iteration element with the same name because that
// would probably result in an infinite loop as the iteration processor
// would be applied once and again. Instead, we create iterated elements
// with a new name (iteratedElementName).
if (iteratedElementName == null) {
throw new TemplateProcessingException(
"Cannot specify null iterated element name if the host iteration element is not being removed");
}
iterElement = element.cloneElementNodeWithNewName(parentNode, iteratedElementName, false);
}
parentNode.insertBefore(element, iterElement);
/*
* Prepare local variables that will be available for each iteration item
*/
final Map<String,Object> nodeLocalVariables = new HashMap<String,Object>(4, 1.0f);
nodeLocalVariables.put(iterVar, obj);
final StatusVar status =
new StatusVar(index, index + 1, size, obj);
if (statusVar != null) {
nodeLocalVariables.put(statusVar, status);
} else {
nodeLocalVariables.put(iterVar + DEFAULT_STATUS_VAR_SUFFIX, status);
}
if (removeHostIterationElement) {
final List<Node> children = iterElement.getChildren();
for (final Node child : children) {
child.setAllNodeLocalVariables(nodeLocalVariables);
}
parentNode.extractChild(iterElement);
} else {
iterElement.setAllNodeLocalVariables(nodeLocalVariables);
processClonedHostIterationElement(arguments, iterElement);
}
index++;
}
parentNode.removeChild(element);
return ProcessorResult.OK;
}