dion 2004/10/17 22:40:44 Modified: jelly/src/java/org/apache/commons/jelly/tags/core ForEachTag.java Log: Add loop status var Revision Changes Path 1.29 +182 -14 jakarta-commons/jelly/src/java/org/apache/commons/jelly/tags/core/ForEachTag.java Index: ForEachTag.java =================================================================== RCS file: /home/cvs/jakarta-commons/jelly/src/java/org/apache/commons/jelly/tags/core/ForEachTag.java,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- ForEachTag.java 9 Sep 2004 12:27:54 -0000 1.28 +++ ForEachTag.java 18 Oct 2004 05:40:44 -0000 1.29 @@ -18,6 +18,8 @@ import java.util.Iterator; +import javax.servlet.jsp.jstl.core.LoopTagStatus; + import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.MissingAttributeException; import org.apache.commons.jelly.TagSupport; @@ -54,6 +56,9 @@ * as the given variable name. */ private String indexVar; + + /** variable to hold loop status */ + private String statusVar; /** The starting index value */ private int begin; @@ -82,6 +87,7 @@ try { if (items != null) { Iterator iter = items.evaluateAsIterator(context); + if (log.isDebugEnabled()) { log.debug("Iterating through: " + iter); } @@ -90,8 +96,22 @@ for (index = 0; index < begin && iter.hasNext(); index++ ) { iter.next(); } + + // set up the status + LoopStatus status = null; + if (statusVar != null) + { + // set up statii as required by JSTL + Integer statusBegin = (begin == 0) ? null : new Integer(begin); + Integer statusEnd = (end == Integer.MAX_VALUE) ? null : new Integer(end); + Integer statusStep = (step == 1) ? null : new Integer(step); + status = new LoopStatus(statusBegin, statusEnd, statusStep); + context.setVariable(statusVar, status); + } - while (iter.hasNext() && index < end) { + boolean firstTime = true; + int count = 0; + while (iter.hasNext() && index <= end) { Object value = iter.next(); if (var != null) { context.setVariable(var, value); @@ -99,16 +119,36 @@ if (indexVar != null) { context.setVariable(indexVar, new Integer(index)); } - invokeBody(output); - - // now we need to move to next index + // set the status var up + if (statusVar != null) { + count++; + status.setCount(count); + status.setCurrent(value); + status.setFirst(firstTime); + status.setIndex(index); + // set first time up for the next iteration. + if (firstTime) { + firstTime = !firstTime; + } + } + // now we need to work out the next index for status isLast + // and also advance the iterator and index for the loop. + boolean finished = false; index++; - for ( int i = 1; i < step; i++, index++ ) { + for ( int i = 1; i < step && !finished; i++, index++ ) { if ( ! iter.hasNext() ) { - return; + finished = true; + } + else { + iter.next(); } - iter.next(); } + + if (statusVar != null) { + status.setLast(finished || !iter.hasNext() || index > end); + } + invokeBody(output); + } } else { @@ -120,13 +160,34 @@ if ( varName == null ) { varName = indexVar; } + // set up the status + LoopStatus status = null; + if (statusVar != null) + { + // set up statii as required by JSTL + Integer statusBegin = new Integer(begin); + Integer statusEnd = new Integer(end); + Integer statusStep = new Integer(step); + status = new LoopStatus(statusBegin, statusEnd, statusStep); + context.setVariable(statusVar, status); + } + int count = 0; for (index = begin; index <= end; index += step ) { + Object value = new Integer(index); if (varName != null) { - Object value = new Integer(index); context.setVariable(varName, value); } + // set the status var up + if (status != null) { + count++; + status.setIndex(index); + status.setCount(count); + status.setCurrent(value); + status.setFirst(index == begin); + status.setLast(index > end - step); + } invokeBody(output); } } @@ -182,12 +243,119 @@ } /** - * Sets the variable name to export the current index to. - * This does the same thing as #setIndexVar(), but is consistent - * with the <a href="http://java.sun.com/products/jsp/jstl/">JSTL</a> - * syntax. + * Sets the variable name to export the current status to. + * The status is an implementation of the JSTL LoopTagStatus interface that provides + * the following bean properties: + * <ul> + * <li>current - the current value of the loop items being iterated</li> + * <li>index - the current index of the items being iterated</li> + * <li>first - true if this is the first iteration, false otherwise</li> + * <li>last - true if this is the last iteration, false otherwise</li> + * <li>begin - the starting index of the loop</li> + * <li>step - the stepping value of the loop</li> + * <li>end - the end index of the loop</li> + * </ul> */ public void setVarStatus(String var) { - setIndexVar( var ); + this.statusVar = var; + } + + /** + * Holds the status of the loop. + */ + public static final class LoopStatus implements LoopTagStatus + { + private Integer begin; + private int count; + private Object current; + private Integer end; + private int index; + private Integer step; + private boolean first; + private boolean last; + + public LoopStatus(Integer begin, Integer end, Integer step) { + this.begin = begin; + this.end = end; + this.step = step; + } + /** + * @return Returns the begin. + */ + public Integer getBegin() { + return begin; + } + /** + * @return Returns the count. + */ + public int getCount() { + return count; + } + /** + * @return Returns the current. + */ + public Object getCurrent() { + return current; + } + /** + * @return Returns the end. + */ + public Integer getEnd() { + return end; + } + /** + * @return Returns the first. + */ + public boolean isFirst() { + return first; + } + /** + * @return Returns the index. + */ + public int getIndex() { + return index; + } + /** + * @return Returns the last. + */ + public boolean isLast() { + return last; + } + /** + * @return Returns the step. + */ + public Integer getStep() { + return step; + } + /** + * @param count The count to set. + */ + public void setCount(int count) { + this.count = count; + } + /** + * @param current The current to set. + */ + public void setCurrent(Object current) { + this.current = current; + } + /** + * @param first The first to set. + */ + public void setFirst(boolean first) { + this.first = first; + } + /** + * @param last The last to set. + */ + public void setLast(boolean last) { + this.last = last; + } + /** + * @param index The index to set. + */ + public void setIndex(int index) { + this.index = index; + } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]