|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.apache.velocity.tools.generic.LoopTool
@DefaultKey(value="loop") @ValidScope(value="request") public class LoopTool
A convenience tool to use with #foreach loops. It wraps a list with a custom iterator to provide additional controls and feedback for managing loops.
This tool was originally inspired the now-deprecated IteratorTool, which provided similar base functionality but was somewhat more difficult to understand and use. Rather than try to migrate that implementation via deprecation and new methods, it was simplest to just create an entirely new tool that simplified the original API and was easy to augment with useful new features like support for nested (and nameable) loops, skipping ahead in loops, synchronizing multiple iterators, getting the iteration count of loops, identifying if a loop is on its first or last iteration, and so on.
Most functions of this tool will be obsolete with the release of Velocity 1.7, which will provide $foreach.hasNext, $foreach.isFirst, $foreach.isLast, $foreach.index and $foreach.count automatically. However, this will still be useful for the more advanced sync and skip features. Also, for very complicated nested loops, the loop naming feature may be easier than doing things like $foreach.parent.parent.
Example of use:
Template --- #set( $list = [1..7] ) #set( $others = [3..10] ) #foreach( $item in $loop.watch($list).sync($others, 'other') ) $item -> $loop.other #if( $item >= 5 )$loop.stop()#end #end Output ------ 1 -> 3 2 -> 4 3 -> 5 4 -> 6 5 -> 7 Example tools.xml config (if you want to use this with VelocityView): <tools> <toolbox scope="request"> <tool class="org.apache.velocity.tools.generic.LoopTool"/> </toolbox> </tools>
Nested Class Summary | |
---|---|
static class |
LoopTool.Action
Represents an automatic action taken by a LoopTool.ManagedIterator
when a LoopTool.ActionCondition is satisfied by the subsequent element. |
static class |
LoopTool.ActionCondition
Composition class which associates an LoopTool.Action and LoopTool.ActionCondition
for a LoopTool.ManagedIterator . |
static class |
LoopTool.Comparison
Base condition class for conditions (assumption here is that conditions are all comparative. |
static interface |
LoopTool.Condition
Represents a function into which a LoopTool.ManagedIterator can
pass it's next element to see if an LoopTool.Action should be taken. |
static class |
LoopTool.Equals
Simple condition that checks elements in the iterator for equality to a specified Object. |
static class |
LoopTool.ManagedIterator
Iterator implementation that wraps a standard Iterator
and allows it to be prematurely stopped, skipped ahead, and
associated with a name for advanced nested loop control. |
static class |
LoopTool.SyncedIterator
Simple wrapper to make it easy to keep an arbitray Iterator in sync with a LoopTool.ManagedIterator . |
Field Summary | |
---|---|
private java.util.Stack<LoopTool.ManagedIterator> |
iterators
|
private LoopTool.ManagedIterator |
last
|
Constructor Summary | |
---|---|
LoopTool()
|
Method Summary | |
---|---|
protected LoopTool.ManagedIterator |
findIterator(java.lang.String name)
Finds the LoopTool.ManagedIterator with the specified name
if it is in this instance's iterator stack. |
java.lang.Object |
get(java.lang.String key)
This serves two purposes: Getting the current value of a sync'ed iterator Abbreviate syntax for properties of outer loops |
java.lang.Object |
get(java.lang.String name,
java.lang.String synced)
Asks the loop with the specified name for the current value of the specified sync'ed iterator, if any. |
java.lang.Integer |
getCount()
Returns the number of items the current loop has handled. |
java.lang.Integer |
getCount(java.lang.String name)
Returns the number of items the specified loop has handled. |
int |
getDepth()
Returns the number of loops currently on the stack. |
java.lang.Boolean |
getFirst()
Returns the result of isFirst() . |
java.lang.Integer |
getIndex()
Returns the 0-based index of the item the current loop is handling. |
java.lang.Integer |
getIndex(java.lang.String name)
Returns the 0-based index of the item the specified loop is handling. |
protected static java.util.Iterator |
getIterator(java.lang.Object obj)
Wraps access to ClassUtils.getIterator(java.lang.Object) is a
nice little try/catch block to prevent exceptions from
escaping into the template. |
java.lang.Boolean |
getLast()
Returns the result of isLast() . |
LoopTool.ManagedIterator |
getThis()
Returns the most recent LoopTool.ManagedIterator for this instance. |
java.lang.Boolean |
isFirst()
Returns true if the current loop is on its first iteration. |
java.lang.Boolean |
isFirst(java.lang.String name)
Returns true if the loop with the specified name
is on its first iteration. |
java.lang.Boolean |
isLast()
Returns true if the current loop is on its last iteration. |
java.lang.Boolean |
isLast(java.lang.String name)
Returns true if the loop with the specified name
is on its last iteration. |
protected LoopTool.ManagedIterator |
manage(java.util.Iterator iterator,
java.lang.String name)
|
protected LoopTool.ManagedIterator |
pop()
Don't let templates call this, but allow subclasses and ManagedIterator to have access. |
void |
skip(int number)
Skips ahead the specified number of iterations (if possible). |
private void |
skip(int number,
LoopTool.ManagedIterator iterator)
|
void |
skip(int number,
java.lang.String name)
This tells the specified loop to skip ahead the specified number of iterations. |
void |
stop()
This tells the current loop to stop after the current iteration. |
void |
stop(java.lang.String name)
This is just like stop() except that the stop command is issued
only to the loop/iterator with the specified name. |
void |
stopAll()
This is just like stop() except that the stop command is issued
all the loops being watched by this tool. |
void |
stopTo(java.lang.String name)
This is just like stop(String) except that the stop command is issued
both to the loop/iterator with the specified name and all loops nested within
it. |
LoopTool.ManagedIterator |
sync(java.lang.Object main,
java.lang.Object synced)
|
LoopTool.ManagedIterator |
watch(java.lang.Object obj)
Tells the LoopTool to watch the specified Array, Collection, Map, Iterator, Iterable, Enumeration or POJO with an iterator() method while the template iterates over the values within it. |
LoopTool.ManagedIterator |
watch(java.lang.Object obj,
java.lang.String name)
This is just like watch(Object) except that it also takes
a name which is given to the LoopTool.ManagedIterator that is returned. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
private java.util.Stack<LoopTool.ManagedIterator> iterators
private LoopTool.ManagedIterator last
Constructor Detail |
---|
public LoopTool()
Method Detail |
---|
public LoopTool.ManagedIterator watch(java.lang.Object obj)
Tells the LoopTool to watch the specified Array, Collection, Map, Iterator, Iterable, Enumeration or POJO with an iterator() method while the template iterates over the values within it.
Under the covers, this is returning an iterable wrapper that is also pushed onto this tool's stack. That allows this tool to know which iterator to give later commands (i.e. stop() or skip()).
obj
- an object that Velocity's #foreach directive can iterate over
LoopTool.ManagedIterator
that this tool instance will trackpublic LoopTool.ManagedIterator watch(java.lang.Object obj, java.lang.String name)
watch(Object)
except that it also takes
a name which is given to the LoopTool.ManagedIterator
that is returned.
This allows the user to send stop or skip commands to that specific
iterator even when there are nested iterators within it that are being
watched. If the given name is null
, then this will return
null
even if the object can be watched. Provided names cannot
be null
.
watch(Object)
public LoopTool.ManagedIterator sync(java.lang.Object main, java.lang.Object synced)
protected LoopTool.ManagedIterator manage(java.util.Iterator iterator, java.lang.String name)
public void stop()
public void stop(java.lang.String name)
stop()
except that the stop command is issued
only to the loop/iterator with the specified name.
If no such loop is found with that name, then no stop command is issued.
stop()
public void stopTo(java.lang.String name)
stop(String)
except that the stop command is issued
both to the loop/iterator with the specified name and all loops nested within
it. If no such loop is found with that name, then no stop commands are
issued.
stop()
,
stop(String)
public void stopAll()
stop()
except that the stop command is issued
all the loops being watched by this tool.
stop()
public void skip(int number)
LoopTool.ManagedIterator.exclude(Object)
, any elements
skipped are still considered in the results returned by getCount()
and isFirst()
.
public void skip(int number, java.lang.String name)
skip(int)
private void skip(int number, LoopTool.ManagedIterator iterator)
public java.lang.Boolean isFirst()
true
if the current loop is on its first iteration.
public java.lang.Boolean isFirst(java.lang.String name)
true
if the loop with the specified name
is on its first iteration.
public java.lang.Boolean getFirst()
isFirst()
. Exists to allow $loop.first syntax.
public java.lang.Boolean isLast()
true
if the current loop is on its last iteration.
public java.lang.Boolean isLast(java.lang.String name)
true
if the loop with the specified name
is on its last iteration.
public java.lang.Boolean getLast()
isLast()
. Exists to allow $loop.last syntax.
public java.lang.Object get(java.lang.String key)
This serves two purposes:
First, it searches all the loops being managed for one
with a sync'ed Iterator under the specified name and
returns the current value for that sync'ed iterator,
if any. If there is no sync'ed iterators or none with
that name, then this will check if the specified key
is requesting a "property" of an outer loop (e.g.
$loop.count_foo
or $loop.first_foo
).
This syntax is shorter and clearer than $loop.getCount('foo')
.
If the key starts with a property name and ends with an outer loop
name, then the value of that property for that loop is returned.
public java.lang.Object get(java.lang.String name, java.lang.String synced)
public java.lang.Integer getIndex()
skip(int)
ahead in this loop, those skipped iterations will
still be reflected in the index. If iteration has not begun, this
will return null
.
public java.lang.Integer getIndex(java.lang.String name)
skip(int)
ahead in this loop, those skipped iterations will
still be reflected in the index. If iteration has not begun, this
will return null
.
public java.lang.Integer getCount()
skip(int)
ahead in this loop, those skipped iterations will still be included in
the count.
public java.lang.Integer getCount(java.lang.String name)
skip(int)
ahead in this loop, those skipped iterations will still be included in
the count.
public LoopTool.ManagedIterator getThis()
LoopTool.ManagedIterator
for this instance.
This can be used to access properties like the count, index,
isFirst, isLast, etc which would otherwise fail on the last item
in a loop due to the necessity of popping iterators off the
stack when the last item is retrieved. (See VELTOOLS-124)
public int getDepth()
protected LoopTool.ManagedIterator findIterator(java.lang.String name)
LoopTool.ManagedIterator
with the specified name
if it is in this instance's iterator stack.
protected LoopTool.ManagedIterator pop()
protected static java.util.Iterator getIterator(java.lang.Object obj)
ClassUtils.getIterator(java.lang.Object)
is a
nice little try/catch block to prevent exceptions from
escaping into the template. In the case of such problems,
this will return null
.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |