in freemarker-core/src/main/java/freemarker/core/IteratorBlock.java [275:362]
private boolean executedNestedContentForCollOrSeqListing(Environment env, TemplateElement[] childBuffer)
throws IOException, TemplateException {
final boolean listNotEmpty;
if (listedValue instanceof TemplateCollectionModel) {
final TemplateCollectionModel collModel = (TemplateCollectionModel) listedValue;
final TemplateModelIterator iterModel
= openedIterator == null ? collModel.iterator()
: ((TemplateModelIterator) openedIterator);
listNotEmpty = iterModel.hasNext();
if (listNotEmpty) {
if (loopVar1Name != null) {
listLoop: do {
loopVar1Value = iterModel.next();
hasNext = iterModel.hasNext();
try {
visibleLoopVar1Name = loopVar1Name; // Makes all loop variables visible in FTL
env.visit(childBuffer);
} catch (BreakOrContinueException br) {
if (br == BreakOrContinueException.BREAK_INSTANCE) {
break listLoop;
}
} finally {
visibleLoopVar1Name = null; // Hides all loop variables in FTL
}
index++;
} while (hasNext);
openedIterator = null;
} else {
// We must reuse this later, because TemplateCollectionModel-s that wrap an Iterator only
// allow one iterator() call. (Also those returned by ?filter, etc. with lazy result generation.)
openedIterator = iterModel;
// Note: Loop variables will only become visible inside #items
env.visit(childBuffer);
}
}
} else if (listedValue instanceof TemplateSequenceModel) {
final TemplateSequenceModel seqModel = (TemplateSequenceModel) listedValue;
final int size = seqModel.size();
listNotEmpty = size != 0;
if (listNotEmpty) {
if (loopVar1Name != null) {
listLoop: for (index = 0; index < size; index++) {
loopVar1Value = seqModel.get(index);
hasNext = (size > index + 1);
try {
visibleLoopVar1Name = loopVar1Name; // Makes all loop variables visible in FTL
env.visit(childBuffer);
} catch (BreakOrContinueException br) {
if (br == BreakOrContinueException.BREAK_INSTANCE) {
break listLoop;
}
} finally {
visibleLoopVar1Name = null; // Hides all loop variables in FTL
}
}
} else {
// Note: Loop variables will only become visible inside #items
env.visit(childBuffer);
}
}
} else if (env.isClassicCompatible()) {
listNotEmpty = true;
if (loopVar1Name != null) {
loopVar1Value = listedValue;
hasNext = false;
}
try {
visibleLoopVar1Name = loopVar1Name; // Makes all loop variables visible in FTL
env.visit(childBuffer);
} catch (BreakOrContinueException br) {
// Silently exit "loop"
} finally {
visibleLoopVar1Name = null; // Hides all loop variables in FTL
}
} else if (listedValue instanceof TemplateHashModelEx
&& !NonSequenceOrCollectionException.isWrappedIterable(listedValue)) {
throw new NonSequenceOrCollectionException(env,
new _ErrorDescriptionBuilder("The value you try to list is ",
new _DelayedAOrAn(new _DelayedFTLTypeDescription(listedValue)),
", thus you must specify two loop variables after the \"as\"; one for the key, and "
+ "another for the value, like ", "<#... as k, v>", ")."
));
} else {
throw new NonSequenceOrCollectionException(
listedExp, listedValue, env);
}
return listNotEmpty;
}