public boolean render(InternalContextAdapter context,
Writer writer,
Node node) throws MethodInvocationException, IOException, ResourceNotFoundException, ParseErrorException {
/*
* do our introspection to see what our collection is
*/
Object listObject = node.jjtGetChild(2).value(context);
if (listObject == null)
return false;
Iterator i = null;
try
{
i = rsvc.getUberspect().getIterator(listObject, uberInfo);
}
/**
* pass through application level runtime exceptions
*/
catch( RuntimeException e )
{
throw e;
}
catch(Exception ee)
{
rsvc.getLog().error("Error getting iterator for #foreach", ee);
}
if (i == null)
{
return false;
}
int counter = counterInitialValue;
boolean maxNbrLoopsExceeded = false;
/*
* save the element key if there is one, and the loop counter
*/
Object o = context.get(elementKey);
Object savedCounter = context.get(counterName);
/*
* Instantiate the null holder context if a null value
* is returned by the foreach iterator. Only one instance is
* created - it's reused for every null value.
*/
NullHolderContext nullHolderContext = null;
while (!maxNbrLoopsExceeded && i.hasNext())
{
// TODO: JDK 1.4+ - > valueOf()
context.localPut(counterName , new Integer(counter));
Object value = i.next();
context.localPut(elementKey, value);
/*
* If the value is null, use the special null holder context
*/
if( value == null )
{
if( nullHolderContext == null )
{
// lazy instantiation
nullHolderContext = new NullHolderContext(elementKey, context);
}
node.jjtGetChild(3).render(nullHolderContext, writer);
}
else
{
node.jjtGetChild(3).render(context, writer);
}
counter++;
// Determine whether we're allowed to continue looping.
// ASSUMPTION: counterInitialValue is not negative!
maxNbrLoopsExceeded = (counter - counterInitialValue) >= maxNbrLoops;
}
/*
* restores the loop counter (if we were nested)
* if we have one, else just removes
*/
if (savedCounter != null)
{
context.put(counterName, savedCounter);
}
else
{
context.remove(counterName);
}
/*
* restores element key if exists
* otherwise just removes
*/
if (o != null)
{
context.put(elementKey, o);
}
else
{
context.remove(elementKey);
}
return true;
}
renders the #foreach() block |