Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/struts/taglib/logic/IterateTag.java


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;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.Collection;
25  import java.util.Enumeration;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  import javax.servlet.jsp.JspException;
30  import javax.servlet.jsp.tagext.BodyTagSupport;
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 11:20:47 -0800 (Wed, 03 Nov 2004) $
44   */
45  
46  public class IterateTag extends BodyTagSupport {
47  
48      // ----------------------------------------------------- Instance Variables
49  
50      /**
51       * Iterator of the elements of this collection, while we are actually
52       * running.
53       */
54      protected Iterator 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 collection = null;
88  
89      public Object getCollection() {
90          return (this.collection);
91      }
92  
93      public void setCollection(Object collection) {
94          this.collection = collection;
95      }
96  
97      /**
98       * The name of the scripting variable to be exposed.
99       */
100     protected String id = null;
101 
102     public String getId() {
103         return (this.id);
104     }
105 
106     public void setId(String 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 indexId = null;
132 
133     public String getIndexId() {
134         return (this.indexId);
135     }
136 
137     public void setIndexId(String indexId) {
138         this.indexId = indexId;
139     }
140 
141     /**
142      * The length value or attribute name (<=0 means no limit).
143      */
144     protected String length = null;
145 
146     public String getLength() {
147         return (this.length);
148     }
149 
150     public void setLength(String length) {
151         this.length = length;
152     }
153 
154     /**
155      * The name of the collection or owning bean.
156      */
157     protected String name = null;
158 
159     public String getName() {
160         return (this.name);
161     }
162 
163     public void setName(String name) {
164         this.name = name;
165     }
166 
167     /**
168      * The starting offset (zero relative).
169      */
170     protected String offset = null;
171 
172     public String getOffset() {
173         return (this.offset);
174     }
175 
176     public void setOffset(String offset) {
177         this.offset = offset;
178     }
179 
180     /**
181      * The property name containing the collection.
182      */
183     protected String property = null;
184 
185     public String getProperty() {
186         return (this.property);
187     }
188 
189     public void setProperty(String 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 scope = null;
197 
198     public String getScope() {
199         return (this.scope);
200     }
201 
202     public void setScope(String scope) {
203         this.scope = scope;
204     }
205 
206     /**
207      * The Java class of each exposed element of the collection.
208      */
209     protected String type = null;
210 
211     public String getType() {
212         return (this.type);
213     }
214 
215     public void setType(String 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 {
228 
229         // Acquire the collection we are going to iterate over
230         Object collection = this.collection;
231         if (collection == null) {
232             collection = TagUtils.getInstance().lookup(pageContext, name, property, scope);
233         }
234 
235         if (collection == null) {
236             JspException e = new JspException(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[]) collection).iterator();
247             } catch (ClassCastException e) {
248                 // Rats -- it is an array of primitives
249                 int length = Array.getLength(collection);
250                 ArrayList c = new ArrayList(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) {
257             iterator = ((Collection) collection).iterator();
258         } else if (collection instanceof Iterator) {
259             iterator = (Iterator) collection;
260         } else if (collection instanceof Map) {
261             iterator = ((Map) collection).entrySet().iterator();
262         } else if (collection instanceof Enumeration) {
263             iterator = new IteratorAdapter((Enumeration) collection);
264         } else {
265             JspException e = new JspException(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 e) {
277                 Integer offsetObject = (Integer) 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 e) {
296                 Integer lengthObject = (Integer) 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 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(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 {
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 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(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 {
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 }