📄 foreach.java
字号:
public boolean getAllowRendering()
{
return innerContext.getAllowRendering();
}
/**
* @see org.apache.velocity.context.InternalContextAdapter#setAllowRendering(boolean v)
*/
public void setAllowRendering(boolean v)
{
innerContext.setAllowRendering(v);
}
}
/**
* Return name of this directive.
* @return The name of this directive.
*/
public String getName()
{
return "foreach";
}
/**
* Return type of this directive.
* @return The type of this directive.
*/
public int getType()
{
return BLOCK;
}
/**
* The name of the variable to use when placing
* the counter value into the context. Right
* now the default is $velocityCount.
*/
private String counterName;
/**
* What value to start the loop counter at.
*/
private int counterInitialValue;
/**
* The maximum number of times we're allowed to loop.
*/
private int maxNbrLoops;
/**
* The reference name used to access each
* of the elements in the list object. It
* is the $item in the following:
*
* #foreach ($item in $list)
*
* This can be used class wide because
* it is immutable.
*/
private String elementKey;
/**
* immutable, so create in init
*/
protected Info uberInfo;
/**
* simple init - init the tree and get the elementKey from
* the AST
* @param rs
* @param context
* @param node
* @throws TemplateInitException
*/
public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
throws TemplateInitException
{
super.init(rs, context, node);
counterName = rsvc.getString(RuntimeConstants.COUNTER_NAME);
counterInitialValue = rsvc.getInt(RuntimeConstants.COUNTER_INITIAL_VALUE);
maxNbrLoops = rsvc.getInt(RuntimeConstants.MAX_NUMBER_LOOPS,
Integer.MAX_VALUE);
if (maxNbrLoops < 1)
{
maxNbrLoops = Integer.MAX_VALUE;
}
/*
* this is really the only thing we can do here as everything
* else is context sensitive
*/
SimpleNode sn = (SimpleNode) node.jjtGetChild(0);
if (sn instanceof ASTReference)
{
elementKey = ((ASTReference) sn).getRootString();
}
else
{
/*
* the default, error-prone way which we'll remove
* TODO : remove if all goes well
*/
elementKey = sn.getFirstToken().image.substring(1);
}
/*
* make an uberinfo - saves new's later on
*/
uberInfo = new Info(context.getCurrentTemplateName(),
getLine(),getColumn());
}
/**
* renders the #foreach() block
* @param context
* @param writer
* @param node
* @return True if the directive rendered successfully.
* @throws IOException
* @throws MethodInvocationException
* @throws ResourceNotFoundException
* @throws ParseErrorException
*/
public boolean render(InternalContextAdapter context,
Writer writer, Node node)
throws IOException, MethodInvocationException, 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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -