Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.jelly.tags.core.ForEachTag |
89% |
100% |

1 |  |
     /*
2 |  |
      * Copyright 2002,2004 The Apache Software Foundation.
3 |  |
      *
4 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
5 |  |
      * you may not use this file except in compliance with the License.
6 |  |
      * You may obtain a copy of the License at
7 |  |
      *
8 |  |
      *      http://www.apache.org/licenses/LICENSE-2.0
9 |  |
      *
10 |  |
      * Unless required by applicable law or agreed to in writing, software
11 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
12 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  |
      * See the License for the specific language governing permissions and
14 |  |
      * limitations under the License.
15 |  |
      */
16 |  |
17 |  |
     package org.apache.commons.jelly.tags.core;
18 |  |
19 |  |
     import java.util.Iterator;
20 |  |
21 |  |
     import javax.servlet.jsp.jstl.core.LoopTagStatus;
22 |  |
23 |  |
     import org.apache.commons.jelly.JellyTagException;
24 |  |
     import org.apache.commons.jelly.MissingAttributeException;
25 |  |
     import org.apache.commons.jelly.TagSupport;
26 |  |
     import org.apache.commons.jelly.XMLOutput;
27 |  |
     import org.apache.commons.jelly.expression.Expression;
28 |  |
     import org.apache.commons.jelly.impl.BreakException;
29 |  |
     import org.apache.commons.logging.Log;
30 |  |
     import org.apache.commons.logging.LogFactory;
31 |  |
32 |  |
     /**
33 |  |
       * Iterates over a collection, iterator or an array of objects.
34 |  |
       * Uses the same syntax as the <a href="http://java.sun.com/products/jsp/jstl/">JSTL</a>
35 |  |
       * <code>forEach</code> tag does.
36 |  |
       *
37 |  |
       * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
38 |  |
       * @version $Revision: 155420 $
39 |  |
       */
40 |  |
     public class ForEachTag extends TagSupport {
41 |  |
42 |  |
         /** The Log to which logging calls will be made. */
43 | 546 |
         private static final Log log = LogFactory.getLog(ForEachTag.class);
44 |  |
45 |  |
         /** Holds the variable name to export for the item being iterated over. */
46 |  |
         private Expression items;
47 |  |
48 |  |
         /**
49 |  |
          * If specified then the current item iterated through will be defined
50 |  |
          * as the given variable name.
51 |  |
          */
52 |  |
         private String var;
53 |  |
54 |  |
         /**
55 |  |
          * If specified then the current index counter will be defined
56 |  |
          * as the given variable name.
57 |  |
          */
58 |  |
         private String indexVar;
59 |  |
60 |  |
         /** variable to hold loop status */
61 |  |
         private String statusVar;
62 |  |
63 |  |
         /** The starting index value */
64 |  |
         private int begin;
65 |  |
66 |  |
         /** The ending index value */
67 | 351 |
         private int end = Integer.MAX_VALUE;
68 |  |
69 |  |
         /** The index increment step */
70 | 351 |
         private int step = 1;
71 |  |
72 |  |
         /** The iteration index */
73 |  |
         private int index;
74 |  |
75 | 351 |
         public ForEachTag() {
76 | 351 |
         }
77 |  |
78 |  |
         // Tag interface
79 |  |
80 |  |
         //-------------------------------------------------------------------------
81 |  |
         public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException {
82 |  |
83 | 351 |
             if (log.isDebugEnabled()) {
84 | 0 |
                 log.debug("running with items: " + items);
85 |  |
             }
86 |  |
87 |  |
             try {
88 | 351 |
                 if (items != null) {
89 | 52 |
                     Iterator iter = items.evaluateAsIterator(context);
90 |  |
91 | 52 |
                     if (log.isDebugEnabled()) {
92 | 0 |
                         log.debug("Iterating through: " + iter);
93 |  |
                     }
94 |  |
95 |  |
                     // ignore the first items of the iterator
96 | 78 |
                     for (index = 0; index < begin && iter.hasNext(); index++ ) {
97 | 26 |
                         iter.next();
98 |  |
                     }
99 |  |
100 |  |
                     // set up the status
101 | 52 |
                     LoopStatus status = null;
102 | 52 |
                     if (statusVar != null)
103 |  |
                     {
104 |  |
                         // set up statii as required by JSTL
105 | 13 |
                         Integer statusBegin = (begin == 0) ? null : new Integer(begin);
106 | 13 |
                         Integer statusEnd = (end == Integer.MAX_VALUE) ? null : new Integer(end);
107 | 13 |
                         Integer statusStep = (step == 1) ? null : new Integer(step);
108 | 13 |
                         status = new LoopStatus(statusBegin, statusEnd, statusStep);
109 | 13 |
                         context.setVariable(statusVar, status);
110 |  |
                     }
111 |  |
112 | 52 |
                     boolean firstTime = true;
113 | 52 |
                     int count = 0;
114 | 195 |
                     while (iter.hasNext() && index <= end) {
115 | 143 |
                         Object value = iter.next();
116 | 143 |
                         if (var != null) {
117 | 143 |
                             context.setVariable(var, value);
118 |  |
                         }
119 | 143 |
                         if (indexVar != null) {
120 | 0 |
                             context.setVariable(indexVar, new Integer(index));
121 |  |
                         }
122 |  |
                         // set the status var up
123 | 143 |
                         if (statusVar != null) {
124 | 39 |
                             count++;
125 | 39 |
                             status.setCount(count);
126 | 39 |
                             status.setCurrent(value);
127 | 39 |
                             status.setFirst(firstTime);
128 | 39 |
                             status.setIndex(index);
129 |  |
                             // set first time up for the next iteration.
130 | 39 |
                             if (firstTime) {
131 | 13 |
                                 firstTime = !firstTime;
132 |  |
                             }
133 |  |
                         }
134 |  |
                         // now we need to work out the next index for status isLast
135 |  |
                         // and also advance the iterator and index for the loop.
136 | 143 |
                         boolean finished = false;
137 | 143 |
                         index++;
138 | 182 |
                         for ( int i = 1; i < step && !finished; i++, index++ ) {
139 | 39 |
                             if ( ! iter.hasNext() ) {
140 | 0 |
                                finished = true;
141 | 0 |
                             }
142 |  |
                             else {
143 | 39 |
                                 iter.next();
144 |  |
                             }
145 |  |
                         }
146 |  |
147 | 143 |
                         if (statusVar != null) {
148 | 39 |
                             status.setLast(finished || !iter.hasNext() || index > end);
149 |  |
                         }
150 | 143 |
                         invokeBody(output);
151 |  |
152 | 143 |
                     }
153 | 52 |
                 }
154 |  |
                 else {
155 | 299 |
                     if ( end == Integer.MAX_VALUE && begin == 0 ) {
156 | 0 |
                         throw new MissingAttributeException( "items" );
157 |  |
                     }
158 |  |
                     else {
159 | 299 |
                         String varName = var;
160 | 299 |
                         if ( varName == null ) {
161 | 0 |
                             varName = indexVar;
162 |  |
                         }
163 |  |
                         // set up the status
164 | 299 |
                         LoopStatus status = null;
165 | 299 |
                         if (statusVar != null)
166 |  |
                         {
167 |  |
                             // set up statii as required by JSTL
168 | 13 |
                             Integer statusBegin = new Integer(begin);
169 | 13 |
                             Integer statusEnd = new Integer(end);
170 | 13 |
                             Integer statusStep = new Integer(step);
171 | 13 |
                             status = new LoopStatus(statusBegin, statusEnd, statusStep);
172 | 13 |
                             context.setVariable(statusVar, status);
173 |  |
                         }
174 |  |
175 | 299 |
                         int count = 0;
176 | 1716 |
                         for (index = begin; index <= end; index += step ) {
177 |  |
178 | 1599 |
                             Object value = new Integer(index);
179 | 1599 |
                             if (varName != null) {
180 | 1599 |
                                 context.setVariable(varName, value);
181 |  |
                             }
182 |  |
                             // set the status var up
183 | 1599 |
                             if (status != null) {
184 | 39 |
                                 count++;
185 | 39 |
                                 status.setIndex(index);
186 | 39 |
                                 status.setCount(count);
187 | 39 |
                                 status.setCurrent(value);
188 | 39 |
                                 status.setFirst(index == begin);
189 | 39 |
                                 status.setLast(index > end - step);
190 |  |
                             }
191 | 1599 |
                             invokeBody(output);
192 |  |
                         }
193 |  |
                     }
194 |  |
                 }
195 |  |
             }
196 | 182 |
             catch (BreakException e) {
197 | 182 |
                 if (log.isDebugEnabled()) {
198 | 0 |
                     log.debug("loop terminated by break: " + e, e);
199 |  |
                 }
200 | 169 |
             }
201 | 351 |
         }
202 |  |
203 |  |
         // Properties
204 |  |
         //-------------------------------------------------------------------------
205 |  |
206 |  |
         /**
207 |  |
          * Sets the expression used to iterate over.
208 |  |
          * This expression could resolve to an Iterator, Collection, Map, Array,
209 |  |
          * Enumeration or comma separated String.
210 |  |
          */
211 |  |
         public void setItems(Expression items) {
212 | 52 |
             this.items = items;
213 | 52 |
         }
214 |  |
215 |  |
         /** Sets the variable name to export for the item being iterated over
216 |  |
          */
217 |  |
         public void setVar(String var) {
218 | 351 |
             this.var = class="keyword">var;
219 | 351 |
         }
220 |  |
221 |  |
         /** Sets the variable name to export the current index counter to
222 |  |
          */
223 |  |
         public void setIndexVar(String indexVar) {
224 | 0 |
             this.indexVar = indexVar;
225 | 0 |
         }
226 |  |
227 |  |
         /** Sets the starting index value
228 |  |
          */
229 |  |
         public void setBegin(int begin) {
230 | 312 |
             this.begin = begin;
231 | 312 |
         }
232 |  |
233 |  |
         /** Sets the ending index value
234 |  |
          */
235 |  |
         public void setEnd(int end) {
236 | 312 |
             this.end = end;
237 | 312 |
         }
238 |  |
239 |  |
         /** Sets the index increment step
240 |  |
          */
241 |  |
         public void setStep(int step) {
242 | 26 |
             this.step = step;
243 | 26 |
         }
244 |  |
245 |  |
         /**
246 |  |
          * Sets the variable name to export the current status to.
247 |  |
          * The status is an implementation of the JSTL LoopTagStatus interface that provides
248 |  |
          * the following bean properties:
249 |  |
          * <ul>
250 |  |
          *   <li>current - the current value of the loop items being iterated</li>
251 |  |
          *   <li>index   - the current index of the items being iterated</li>
252 |  |
          *   <li>first   - true if this is the first iteration, false otherwise</li>
253 |  |
          *   <li>last    - true if this is the last iteration, false otherwise</li>
254 |  |
          *   <li>begin   - the starting index of the loop</li>
255 |  |
          *   <li>step    - the stepping value of the loop</li>
256 |  |
          *   <li>end     - the end index of the loop</li>
257 |  |
          * </ul>
258 |  |
          */
259 |  |
         public void setVarStatus(String var) {
260 | 26 |
             this.statusVar = var;
261 | 26 |
         }
262 |  |
263 |  |
         /**
264 |  |
          * Holds the status of the loop.
265 |  |
          */
266 |  |
         public static final class LoopStatus implements LoopTagStatus
267 |  |
         {
268 |  |
             private Integer begin;
269 |  |
             private int count;
270 |  |
             private Object current;
271 |  |
             private Integer end;
272 |  |
             private int index;
273 |  |
             private Integer step;
274 |  |
             private boolean first;
275 |  |
             private boolean last;
276 |  |
277 |  |
             public LoopStatus(Integer begin, Integer end, Integer step) {
278 |  |
                 this.begin = begin;
279 |  |
                 this.end = end;
280 |  |
                 this.step = step;
281 |  |
             }
282 |  |
             /**
283 |  |
              * @return Returns the begin.
284 |  |
              */
285 |  |
             public Integer getBegin() {
286 |  |
                 return begin;
287 |  |
             }
288 |  |
             /**
289 |  |
              * @return Returns the count.
290 |  |
              */
291 |  |
             public int getCount() {
292 |  |
                 return count;
293 |  |
             }
294 |  |
             /**
295 |  |
              * @return Returns the current.
296 |  |
              */
297 |  |
             public Object getCurrent() {
298 |  |
                 return current;
299 |  |
             }
300 |  |
             /**
301 |  |
              * @return Returns the end.
302 |  |
              */
303 |  |
             public Integer getEnd() {
304 |  |
                 return end;
305 |  |
             }
306 |  |
             /**
307 |  |
              * @return Returns the first.
308 |  |
              */
309 |  |
             public boolean isFirst() {
310 |  |
                 return first;
311 |  |
             }
312 |  |
             /**
313 |  |
              * @return Returns the index.
314 |  |
              */
315 |  |
             public int getIndex() {
316 |  |
                 return index;
317 |  |
             }
318 |  |
             /**
319 |  |
              * @return Returns the last.
320 |  |
              */
321 |  |
             public boolean isLast() {
322 |  |
                 return last;
323 |  |
             }
324 |  |
             /**
325 |  |
              * @return Returns the step.
326 |  |
              */
327 |  |
             public Integer getStep() {
328 |  |
                 return step;
329 |  |
             }
330 |  |
             /**
331 |  |
              * @param count The count to set.
332 |  |
              */
333 |  |
             public void setCount(int count) {
334 |  |
                 this.count = count;
335 |  |
             }
336 |  |
             /**
337 |  |
              * @param current The current to set.
338 |  |
              */
339 |  |
             public void setCurrent(Object current) {
340 |  |
                 this.current = current;
341 |  |
             }
342 |  |
             /**
343 |  |
              * @param first The first to set.
344 |  |
              */
345 |  |
             public void setFirst(boolean first) {
346 |  |
                 this.first = first;
347 |  |
             }
348 |  |
             /**
349 |  |
              * @param last The last to set.
350 |  |
              */
351 |  |
             public void setLast(boolean last) {
352 |  |
                 this.last = last;
353 |  |
             }
354 |  |
             /**
355 |  |
              * @param index The index to set.
356 |  |
              */
357 |  |
             public void setIndex(int index) {
358 |  |
                 this.index = index;
359 |  |
             }
360 |  |
         }
361 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.