[ 
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]

Reply via email to