KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > taglib > logic > IterateTag


1 /*
2  * $Id: IterateTag.java 56513 2004-11-03 19:20:47Z niallp $
3  *
4  * Copyright 1999-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.apache.struts.taglib.logic;
20
21 import java.lang.reflect.Array JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.Enumeration JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import javax.servlet.jsp.JspException JavaDoc;
30 import javax.servlet.jsp.tagext.BodyTagSupport JavaDoc;
31
32 import org.apache.struts.util.IteratorAdapter;
33 import org.apache.struts.taglib.TagUtils;
34 import org.apache.struts.util.MessageResources;
35
36 /**
37  * Custom tag that iterates the elements of a collection, which can be
38  * either an attribute or the property of an attribute. The collection
39  * can be any of the following: an array of objects, an Enumeration,
40  * an Iterator, a Collection (which includes Lists, Sets and Vectors),
41  * or a Map (which includes Hashtables) whose elements will be iterated over.
42  *
43  * @version $Rev: 56513 $ $Date: 2004-11-03 19:20:47 +0000 (Wed, 03 Nov 2004) $
44  */

45
46 public class IterateTag extends BodyTagSupport JavaDoc {
47
48     // ----------------------------------------------------- Instance Variables
49

50     /**
51      * Iterator of the elements of this collection, while we are actually
52      * running.
53      */

54     protected Iterator JavaDoc iterator = null;
55
56     /**
57      * The number of elements we have already rendered.
58      */

59     protected int lengthCount = 0;
60
61     /**
62      * The actual length value (calculated in the start tag).
63      */

64     protected int lengthValue = 0;
65
66     /**
67      * The message resources for this package.
68      */

69     protected static MessageResources messages =
70         MessageResources.getMessageResources("org.apache.struts.taglib.logic.LocalStrings");
71
72     /**
73      * The actual offset value (calculated in the start tag).
74      */

75     protected int offsetValue = 0;
76
77     /**
78      * Has this tag instance been started?
79      */

80     protected boolean started = false;
81
82     // ------------------------------------------------------------- Properties
83

84     /**
85      * The collection over which we will be iterating.
86      */

87     protected Object JavaDoc collection = null;
88
89     public Object JavaDoc getCollection() {
90         return (this.collection);
91     }
92
93     public void setCollection(Object JavaDoc collection) {
94         this.collection = collection;
95     }
96
97     /**
98      * The name of the scripting variable to be exposed.
99      */

100     protected String JavaDoc id = null;
101
102     public String JavaDoc getId() {
103         return (this.id);
104     }
105
106     public void setId(String JavaDoc id) {
107         this.id = id;
108     }
109
110     /**
111      * <p>Return the zero-relative index of the current iteration through the
112      * loop. If you specify an <code>offset</code>, the first iteration
113      * through the loop will have that value; otherwise, the first iteration
114      * will return zero.</p>
115      *
116      * <p>This property is read-only, and gives nested custom tags access to
117      * this information. Therefore, it is <strong>only</strong> valid in
118      * between calls to <code>doStartTag()</code> and <code>doEndTag()</code>.
119      * </p>
120      */

121     public int getIndex() {
122         if (started)
123             return (offsetValue + lengthCount - 1);
124         else
125             return (0);
126     }
127
128     /**
129      * The name of the scripting variable to be exposed as the current index.
130      */

131     protected String JavaDoc indexId = null;
132
133     public String JavaDoc getIndexId() {
134         return (this.indexId);
135     }
136
137     public void setIndexId(String JavaDoc indexId) {
138         this.indexId = indexId;
139     }
140
141     /**
142      * The length value or attribute name (<=0 means no limit).
143      */

144     protected String JavaDoc length = null;
145
146     public String JavaDoc getLength() {
147         return (this.length);
148     }
149
150     public void setLength(String JavaDoc length) {
151         this.length = length;
152     }
153
154     /**
155      * The name of the collection or owning bean.
156      */

157     protected String JavaDoc name = null;
158
159     public String JavaDoc getName() {
160         return (this.name);
161     }
162
163     public void setName(String JavaDoc name) {
164         this.name = name;
165     }
166
167     /**
168      * The starting offset (zero relative).
169      */

170     protected String JavaDoc offset = null;
171
172     public String JavaDoc getOffset() {
173         return (this.offset);
174     }
175
176     public void setOffset(String JavaDoc offset) {
177         this.offset = offset;
178     }
179
180     /**
181      * The property name containing the collection.
182      */

183     protected String JavaDoc property = null;
184
185     public String JavaDoc getProperty() {
186         return (this.property);
187     }
188
189     public void setProperty(String JavaDoc property) {
190         this.property = property;
191     }
192
193     /**
194      * The scope of the bean specified by the name property, if any.
195      */

196     protected String JavaDoc scope = null;
197
198     public String JavaDoc getScope() {
199         return (this.scope);
200     }
201
202     public void setScope(String JavaDoc scope) {
203         this.scope = scope;
204     }
205
206     /**
207      * The Java class of each exposed element of the collection.
208      */

209     protected String JavaDoc type = null;
210
211     public String JavaDoc getType() {
212         return (this.type);
213     }
214
215     public void setType(String JavaDoc type) {
216         this.type = type;
217     }
218
219     // --------------------------------------------------------- Public Methods
220

221     /**
222      * Construct an iterator for the specified collection, and begin
223      * looping through the body once per element.
224      *
225      * @exception JspException if a JSP exception has occurred
226      */

227     public int doStartTag() throws JspException JavaDoc {
228
229         // Acquire the collection we are going to iterate over
230
Object JavaDoc collection = this.collection;
231         if (collection == null) {
232             collection = TagUtils.getInstance().lookup(pageContext, name, property, scope);
233         }
234
235         if (collection == null) {
236             JspException JavaDoc e = new JspException JavaDoc(messages.getMessage("iterate.collection"));
237             TagUtils.getInstance().saveException(pageContext, e);
238             throw e;
239         }
240
241         // Construct an iterator for this collection
242
if (collection.getClass().isArray()) {
243             try {
244                 // If we're lucky, it is an array of objects
245
// that we can iterate over with no copying
246
iterator = Arrays.asList((Object JavaDoc[]) collection).iterator();
247             } catch (ClassCastException JavaDoc e) {
248                 // Rats -- it is an array of primitives
249
int length = Array.getLength(collection);
250                 ArrayList JavaDoc c = new ArrayList JavaDoc(length);
251                 for (int i = 0; i < length; i++) {
252                     c.add(Array.get(collection, i));
253                 }
254                 iterator = c.iterator();
255             }
256         } else if (collection instanceof Collection JavaDoc) {
257             iterator = ((Collection JavaDoc) collection).iterator();
258         } else if (collection instanceof Iterator JavaDoc) {
259             iterator = (Iterator JavaDoc) collection;
260         } else if (collection instanceof Map JavaDoc) {
261             iterator = ((Map JavaDoc) collection).entrySet().iterator();
262         } else if (collection instanceof Enumeration JavaDoc) {
263             iterator = new IteratorAdapter((Enumeration JavaDoc) collection);
264         } else {
265             JspException JavaDoc e = new JspException JavaDoc(messages.getMessage("iterate.iterator"));
266             TagUtils.getInstance().saveException(pageContext, e);
267             throw e;
268         }
269
270         // Calculate the starting offset
271
if (offset == null) {
272             offsetValue = 0;
273         } else {
274             try {
275                 offsetValue = Integer.parseInt(offset);
276             } catch (NumberFormatException JavaDoc e) {
277                 Integer JavaDoc offsetObject = (Integer JavaDoc) TagUtils.getInstance().lookup(pageContext, offset, null);
278                 if (offsetObject == null) {
279                     offsetValue = 0;
280                 } else {
281                     offsetValue = offsetObject.intValue();
282                 }
283             }
284         }
285         if (offsetValue < 0) {
286             offsetValue = 0;
287         }
288
289         // Calculate the rendering length
290
if (length == null) {
291             lengthValue = 0;
292         } else {
293             try {
294                 lengthValue = Integer.parseInt(length);
295             } catch (NumberFormatException JavaDoc e) {
296                 Integer JavaDoc lengthObject = (Integer JavaDoc) TagUtils.getInstance().lookup(pageContext, length, null);
297                 if (lengthObject == null) {
298                     lengthValue = 0;
299                 } else {
300                     lengthValue = lengthObject.intValue();
301                 }
302             }
303         }
304         if (lengthValue < 0) {
305             lengthValue = 0;
306         }
307         lengthCount = 0;
308
309         // Skip the leading elements up to the starting offset
310
for (int i = 0; i < offsetValue; i++) {
311             if (iterator.hasNext()) {
312                 iterator.next();
313             }
314         }
315
316         // Store the first value and evaluate, or skip the body if none
317
if (iterator.hasNext()) {
318             Object JavaDoc element = iterator.next();
319             if (element == null) {
320                 pageContext.removeAttribute(id);
321             } else {
322                 pageContext.setAttribute(id, element);
323             }
324             lengthCount++;
325             started = true;
326             if (indexId != null) {
327                 pageContext.setAttribute(indexId, new Integer JavaDoc(getIndex()));
328             }
329             return (EVAL_BODY_TAG);
330         } else {
331             return (SKIP_BODY);
332         }
333
334     }
335
336     /**
337      * Make the next collection element available and loop, or
338      * finish the iterations if there are no more elements.
339      *
340      * @exception JspException if a JSP exception has occurred
341      */

342     public int doAfterBody() throws JspException JavaDoc {
343
344         // Render the output from this iteration to the output stream
345
if (bodyContent != null) {
346             TagUtils.getInstance().writePrevious(pageContext, bodyContent.getString());
347             bodyContent.clearBody();
348         }
349
350         // Decide whether to iterate or quit
351
if ((lengthValue > 0) && (lengthCount >= lengthValue)) {
352             return (SKIP_BODY);
353         }
354
355         if (iterator.hasNext()) {
356             Object JavaDoc element = iterator.next();
357             if (element == null) {
358                 pageContext.removeAttribute(id);
359             } else {
360                 pageContext.setAttribute(id, element);
361             }
362             lengthCount++;
363             if (indexId != null) {
364                 pageContext.setAttribute(indexId, new Integer JavaDoc(getIndex()));
365             }
366             return (EVAL_BODY_TAG);
367         } else {
368             return (SKIP_BODY);
369         }
370
371     }
372
373     /**
374      * Clean up after processing this enumeration.
375      *
376      * @exception JspException if a JSP exception has occurred
377      */

378     public int doEndTag() throws JspException JavaDoc {
379
380         // Clean up our started state
381
started = false;
382         iterator = null;
383
384         // Continue processing this page
385
return (EVAL_PAGE);
386
387     }
388
389     /**
390      * Release all allocated resources.
391      */

392     public void release() {
393
394         super.release();
395
396         iterator = null;
397         lengthCount = 0;
398         lengthValue = 0;
399         offsetValue = 0;
400
401         id = null;
402         collection = null;
403         length = null;
404         name = null;
405         offset = null;
406         property = null;
407         scope = null;
408         started = false;
409
410     }
411
412 }
413
Popular Tags