View Javadoc

1   /*
2    * $Id: IteratorGeneratorTag.java 497654 2007-01-19 00:21:57Z rgielen $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.views.jsp.iterator;
22  
23  import javax.servlet.jsp.JspException;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.struts2.views.annotations.StrutsTag;
28  import org.apache.struts2.views.annotations.StrutsTagAttribute;
29  import org.apache.struts2.util.IteratorGenerator;
30  import org.apache.struts2.util.IteratorGenerator.Converter;
31  import org.apache.struts2.views.jsp.StrutsBodyTagSupport;
32  
33  
34  /***
35   * <!-- START SNIPPET: javadoc -->
36   * <b>NOTE: JSP-TAG</b>
37   *
38   * <p>Generate an iterator based on the val attribute supplied.</P>
39   *
40   * <b>NOTE:</b> The generated iterator will <b>ALWAYS</b> be pushed into the top of the stack, and poped
41   * at the end of the tag.
42   * <!-- END SNIPPET: javadoc -->
43   *
44   * <!-- START SNIPPET: params -->
45   * <ul>
46   *      <li>val* (Object) - the source to be parsed into an iterator </li>
47   *      <li>count (Object) - the max number (Integer, Float, Double, Long, String) entries to be in the iterator</li>
48   *      <li>separator (String) - the separator to be used in separating the <i>val</i> into entries of the iterator</li>
49   *      <li>id (String) - the id to store the resultant iterator into page context, if such id is supplied</li>
50   *      <li>converter (Object) - the converter (must extends off IteratorGenerator.Converter interface) to convert the String entry parsed from <i>val</i> into an object</li>
51   * </ul>
52   * <!-- END SNIPPET: params -->
53   *
54   *
55   * <!-- START SNIPPET: example -->
56   * Example One:
57   * <pre>
58   * Generate a simple iterator
59   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}"&gt;
60   *  &lt;s:iterator&gt;
61   *      &lt;s:property /&gt;&lt;br/&gt;
62   *  &lt;/s:iterator&gt;
63   * &lt;/s:generator&gt;
64   * </pre>
65   * This generates an iterator and print it out using the iterator tag.
66   *
67   * Example Two:
68   * <pre>
69   * Generate an iterator with count attribute
70   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="3"&gt;
71   *  &lt;s:iterator&gt;
72   *      &lt;s:property /&gt;&lt;br/&gt;
73   *  &lt;/s:iterator&gt;
74   * &lt;/s:generator&gt;
75   * </pre>
76   * This generates an iterator, but only 3 entries will be available in the iterator
77   * generated, namely aaa, bbb and ccc respectively because count attribute is set to 3
78   *
79   * Example Three:
80   * <pre>
81   * Generate an iterator with id attribute
82   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="4" separator="," id="myAtt" /&gt;
83   * &lt;%
84   *  Iterator i = (Iterator) pageContext.getAttribute("myAtt");
85   *  while(i.hasNext()) {
86   *      String s = (String) i.next(); %>
87   *      &lt;%=s%&gt; &lt;br/&gt;
88   * &lt;%    }
89   * %&gt;
90   * </pre>
91   * This generates an iterator and put it in the PageContext under the key as specified
92   * by the id attribute.
93   *
94   *
95   * Example Four:
96   * <pre>
97   * Generate an iterator with comparator attribute
98   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" converter="%{myConverter}"&gt;
99   *  &lt;s:iterator&gt;
100  *      &lt;s:property /&gt;&lt;br/&gt;
101  *  &lt;/s:iterator&gt;
102  * &lt;/s:generator&gt;
103  *
104  *
105  * public class GeneratorTagAction extends ActionSupport {
106  *
107  *   ....
108  *
109  *   public Converter getMyConverter() {
110  *      return new Converter() {
111  *          public Object convert(String value) throws Exception {
112  *              return "converter-"+value;
113  *          }
114  *      };
115  *   }
116  *
117  *   ...
118  *
119  * }
120  * </pre>
121  * This will generate an iterator with each entries decided by the converter supplied. With
122  * this converter, it simply add "converter-" to each entries.
123  * <!-- END SNIPPET: example -->
124  *
125  * @see org.apache.struts2.util.IteratorGenerator
126  */
127 @StrutsTag(name="generator", tldTagClass="org.apache.struts2.views.jsp.iterator.IteratorGeneratorTag", 
128         description="Generate an iterator for a iterable source.")
129 public class IteratorGeneratorTag extends StrutsBodyTagSupport {
130 
131     private static final long serialVersionUID = 2968037295463973936L;
132 
133     public static final String DEFAULT_SEPARATOR = ",";
134 
135     private static final Log _log = LogFactory.getLog(IteratorGeneratorTag.class);
136 
137     String countAttr;
138     String separatorAttr;
139     String valueAttr;
140     String converterAttr;
141 
142     IteratorGenerator iteratorGenerator = null;
143 
144     @StrutsTagAttribute(type="Integer",description="The max number entries to be in the iterator")
145     public void setCount(String count) {
146         countAttr = count;
147     }
148 
149     /***
150      * @s.tagattribute required="true" type="String"
151      * description="the separator to be used in separating the <i>val</i> into entries of the iterator"
152      */
153     @StrutsTagAttribute(required=true, description="The separator to be used in separating the <i>val</i> into entries of the iterator")
154     public void setSeparator(String separator) {
155         separatorAttr = separator;
156     }
157 
158     /***
159      * @s.tagattribute required="true"
160      * description="the source to be parsed into an iterator"
161      */
162     @StrutsTagAttribute(required=true, description="The source to be parsed into an iterator")
163     public void setVal(String val) {
164         valueAttr = val;
165     }
166 
167     @StrutsTagAttribute(type="org.apache.struts2.util.IteratorGenerator.Converter",
168             description="The converter to convert the String entry parsed from <i>val</i> into an object")
169     public void setConverter(String aConverter) {
170         converterAttr = aConverter;
171     }
172 
173     /***
174      * @s.tagattribute required="false" type="String"
175      * description="the id to store the resultant iterator into page context, if such id is supplied"
176      */
177     @StrutsTagAttribute(description="The id to store the resultant iterator into page context, if such id is supplied")
178     public void setId(String string) {
179         super.setId(string);
180     }
181 
182     public int doStartTag() throws JspException {
183 
184         // value
185         Object value = findValue(valueAttr);
186 
187         // separator
188         String separator = DEFAULT_SEPARATOR;
189         if (separatorAttr != null && separatorAttr.length() > 0) {
190             separator = findString(separatorAttr);
191         }
192 
193         // TODO: maybe this could be put into an Util class, or there is already one?
194         // count
195         int count = 0;
196         if (countAttr != null && countAttr.length() > 0) {
197             Object countObj = findValue(countAttr);
198             if (countObj instanceof Integer) {
199                 count = ((Integer)countObj).intValue();
200             }
201             else if (countObj instanceof Float) {
202                 count = ((Float)countObj).intValue();
203             }
204             else if (countObj instanceof Long) {
205                 count = ((Long)countObj).intValue();
206             }
207             else if (countObj instanceof Double) {
208                 count = ((Long)countObj).intValue();
209             }
210             else if (countObj instanceof String) {
211                 try {
212                     count = Integer.parseInt((String)countObj);
213                 }
214                 catch(NumberFormatException e) {
215                     _log.warn("unable to convert count attribute ["+countObj+"] to number, ignore count attribute", e);
216                 }
217             }
218         }
219 
220         // converter
221         Converter converter = null;
222         if (converterAttr != null && converterAttr.length() > 0) {
223             converter = (Converter) findValue(converterAttr);
224         }
225 
226 
227         iteratorGenerator = new IteratorGenerator();
228         iteratorGenerator.setValues(value);
229         iteratorGenerator.setCount(count);
230         iteratorGenerator.setSeparator(separator);
231         iteratorGenerator.setConverter(converter);
232 
233         iteratorGenerator.execute();
234 
235 
236 
237         // push resulting iterator into stack
238         getStack().push(iteratorGenerator);
239         if (getId() != null && getId().length() > 0) {
240             // if an id is specified, we have the resulting iterator set into
241             // the pageContext attribute as well
242             pageContext.setAttribute(getId(), iteratorGenerator);
243         }
244 
245         return EVAL_BODY_INCLUDE;
246     }
247 
248     public int doEndTag() throws JspException {
249         // pop resulting iterator from stack at end tag
250         getStack().pop();
251         iteratorGenerator = null; // clean up
252 
253         return EVAL_PAGE;
254     }
255 }