[
https://issues.apache.org/jira/browse/VELTOOLS-124?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Nathan Bubna resolved VELTOOLS-124.
-----------------------------------
Resolution: Fixed
Fix Version/s: 2.0
Unfortunately, there is no alternative time to pop the last iterator from the
stack. There is no way to have the #foreach directive notify the LoopTool
that #end was reached. It's just not possible without hacking Velocity Engine
itself.
However, Velocity 1.7 will soon have a beta release and hopefully a final
release shortly thereafter. With that release is the advent of the $foreach
"control" object. That will provide $foreach.count $foreach.index
$foreach.last $foreach.first and $foreach.hasNext to all #foreach loops. It
will also provide access to $foreach.parent and $foreach.parent.parent and so
on up to $foreach.topmost to provide access to all those properties in nested
situations. Oh, and the #break directive is upgraded to accept a #break(
$foreach.parent ) argument and so on.
All that is to say that the LoopTool will soon be only useful for the sync,
skip and stop condition features, which are not affected by this bug.
Still, in the short term, i've got a solution for those wishing to always have
accurate index, count, etc properties. I've provided access to the underlying
ManagedIterator wrapper:
#foreach( $i in $loop.watch([1..3]) )
#set( $this = $loop.this )
i[$this.index]=$i;
#end
The $loop.this reference will always provide the ManagedIterator from the most
recent $loop.watch() call. Along with this, i have actually "fixed" this
specific bug in some situations by using that "last" iterator reference. So,
in simple situations like the example you gave, things should work fine.
However, in nested loop situations, things get messy once you start getting
beyond the first #end on the final iteration(s) of the nested #foreach calls.
Your only reliable bet in that situation is to grab the $loop.this reference at
the top of each #foreach and use those to get what you need or to otherwise not
reference $loop properties directly after the first #end.
Though, again, for index/count/first/last/hasNext properties, the only proper
solution is the upcoming $foreach reference in Velocity 1.7. Once $foreach is
well established, those properties of $loop should probably just be removed.
> LoopTool fails to retrieve $loop.index, $loop.first etc for the last element
> in a collection.
> ---------------------------------------------------------------------------------------------
>
> Key: VELTOOLS-124
> URL: https://issues.apache.org/jira/browse/VELTOOLS-124
> Project: Velocity Tools
> Issue Type: Bug
> Components: GenericTools
> Affects Versions: 2.x
> Environment: velocity-tools-2.0-beta4 with velocity-1.6.2
> Reporter: Sergiy Kovalchuk
> Fix For: 2.0, 2.x
>
>
> $loop.index, $loop.first and other LoopTool methods (that depend on iterator)
> return null for the last element in a collection.
> Try to run:
> #set( $list = [1..3] )
> #foreach($i in $loop.watch($list))
> i[${loop.index}]=$i;
> #end
> The result is:
> i[0]=1; i[1]=2; i[${loop.index}]=3;
> I tried to investigate it a little, and seems like the problem is inside
> "cacheNext(boolean popWhenDone)".
> First it checks if (!iterator.hasNext()) and if not then removes this
> iterator from the stack. But later in this method it retrieves next element
> from a collection "this.next = iterator.next();". Seems like it causes
> removing iterator too early, when calling ${loop.index} on the last element
> the iterator is already removed.
> Thanks.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]