You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2010/04/07 18:47:56 UTC
svn commit: r931617 -
/velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java
Author: nbubna
Date: Wed Apr 7 16:47:56 2010
New Revision: 931617
URL: http://svn.apache.org/viewvc?rev=931617&view=rev
Log:
VELTOOLS-124 provide quasi-fix for count-base properties on last iteration, as well as getThis() to offer a reliable workaround in nested loop situations
Modified:
velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java
Modified: velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java?rev=931617&r1=931616&r2=931617&view=diff
==============================================================================
--- velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java (original)
+++ velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LoopTool.java Wed Apr 7 16:47:56 2010
@@ -49,13 +49,12 @@ import org.apache.velocity.tools.config.
* on its first or last iteration, and so on.
* </p>
* <p>
- * Most usage, of course, will probably never go much beyond the
- * simple {@link #watch(Object)}, {@link ManagedIterator#sync(Object)},
- * {@link ManagedIterator#stop(Object)}, {@link #isFirst},
- * {@link #isLast},and maybe {@link #getCount} or {@link #getIndex}
- * methods, if even that much. However, it is with complicated nested
- * #foreach loops and varying "break" conditions, that this tool can
- * probably do the most to simplify your templates.
+ * 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.
* </p>
* <p>
* Example of use:
@@ -94,6 +93,7 @@ import org.apache.velocity.tools.config.
public class LoopTool
{
private Stack<ManagedIterator> iterators = new Stack<ManagedIterator>();
+ private ManagedIterator last;
/**
* <p>Tells the LoopTool to watch the specified Array, Collection, Map,
@@ -117,6 +117,7 @@ public class LoopTool
ManagedIterator managed = manage(iterator, null);
iterators.push(managed);
+ this.last = managed;
return managed;
}
@@ -145,6 +146,7 @@ public class LoopTool
ManagedIterator managed = manage(iterator, name);
iterators.push(managed);
+ this.last = managed;
return managed;
}
@@ -306,11 +308,11 @@ public class LoopTool
*/
public Boolean isFirst()
{
- if (iterators.empty())
+ if (last != null)
{
- return null;
+ return last.isFirst();
}
- return iterators.peek().isFirst();
+ return null;
}
/**
@@ -341,11 +343,11 @@ public class LoopTool
*/
public Boolean isLast()
{
- if (iterators.empty())
+ if (last != null)
{
- return null;
+ return last.isLast();
}
- return iterators.peek().isLast();
+ return null;
}
/**
@@ -381,7 +383,7 @@ public class LoopTool
* 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.
- * {@code $loop.foo_count} or {@code $loop.foo_first}).
+ * {@code $loop.count_foo} or {@code $loop.first_foo}).
* This syntax is shorter and clearer than {@code $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.
@@ -480,11 +482,11 @@ public class LoopTool
*/
public Integer getCount()
{
- if (iterators.empty())
+ if (last != null)
{
- return null;
+ return last.getCount();
}
- return iterators.peek().getCount();
+ return null;
}
/**
@@ -505,8 +507,22 @@ public class LoopTool
}
/**
- * Returns the number of loops currently on the stack to tell
- * how deeply nested the current loop is.
+ * Returns the most recent {@link 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 ManagedIterator getThis()
+ {
+ return last;
+ }
+
+ /**
+ * Returns the number of loops currently on the stack.
+ * This is only useful for debugging, as iterators are
+ * popped off the stack at the start of their final iteration,
+ * making this frequently "incorrect".
*/
public int getDepth()
{
@@ -535,9 +551,9 @@ public class LoopTool
* Don't let templates call this, but allow subclasses
* and ManagedIterator to have access.
*/
- protected void pop()
+ protected ManagedIterator pop()
{
- iterators.pop();
+ return iterators.pop();
}
@@ -632,6 +648,22 @@ public class LoopTool
}
/**
+ * Returns the result of {@link #isFirst}. Exists to allow $loop.this.first syntax.
+ */
+ public boolean getFirst()
+ {
+ return isFirst();
+ }
+
+ /**
+ * Returns the result of {@link #isLast}. Exists to allow $loop.this.last syntax.
+ */
+ public boolean getLast()
+ {
+ return isLast();
+ }
+
+ /**
* Returns true if there are more elements in the iterator
* being managed by this instance which satisfy all the
* {@link ActionCondition}s set for this instance. Returns
@@ -642,6 +674,14 @@ public class LoopTool
return hasNext(true);
}
+ /**
+ * Returns the result of {@link #hasNext}. Exists to allow $loop.this.hasNext syntax.
+ */
+ public boolean getHasNext()
+ {
+ return hasNext(false);//no need to pop, #foreach will always call hasNext()
+ }
+
// version that lets isLast check w/o popping this from the stack
private boolean hasNext(boolean popWhenDone)
{
@@ -757,6 +797,14 @@ public class LoopTool
}
/**
+ * Returns the 0-based index of the current item.
+ */
+ public int getIndex()
+ {
+ return count - 1;
+ }
+
+ /**
* Returns the next element that meets the set {@link ActionCondition}s
* (if any) in the iterator being managed. If there are none left, then
* this will throw a {@link NoSuchElementException}.