View Javadoc

1   /*
2    * $Id: IteratorGeneratorTag.java 651946 2008-04-27 13:41:38Z apetrelli $
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  
22  package org.apache.struts2.views.jsp.iterator;
23  
24  import javax.servlet.jsp.JspException;
25  
26  import org.apache.struts2.util.IteratorGenerator;
27  import org.apache.struts2.util.IteratorGenerator.Converter;
28  import org.apache.struts2.views.annotations.StrutsTag;
29  import org.apache.struts2.views.annotations.StrutsTagAttribute;
30  import org.apache.struts2.views.jsp.StrutsBodyTagSupport;
31  
32  import com.opensymphony.xwork2.util.logging.Logger;
33  import com.opensymphony.xwork2.util.logging.LoggerFactory;
34  
35  
36  /***
37   * <!-- START SNIPPET: javadoc -->
38   * <b>NOTE: JSP-TAG</b>
39   *
40   * <p>Generate an iterator based on the val attribute supplied.</P>
41   *
42   * <b>NOTE:</b> The generated iterator will <b>ALWAYS</b> be pushed into the top of the stack, and poped
43   * at the end of the tag.
44   * <!-- END SNIPPET: javadoc -->
45   *
46   * <!-- START SNIPPET: params -->
47   * <ul>
48   *      <li>val* (Object) - the source to be parsed into an iterator </li>
49   *      <li>count (Object) - the max number (Integer, Float, Double, Long, String) entries to be in the iterator</li>
50   *      <li>separator (String) - the separator to be used in separating the <i>val</i> into entries of the iterator</li>
51   *      <li>var (String) - the name to store the resultant iterator into page context, if such name is supplied</li>
52   *      <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>
53   * </ul>
54   * <!-- END SNIPPET: params -->
55   *
56   *
57   * <!-- START SNIPPET: example -->
58   * Example One:
59   * <pre>
60   * Generate a simple iterator
61   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}"&gt;
62   *  &lt;s:iterator&gt;
63   *      &lt;s:property /&gt;&lt;br/&gt;
64   *  &lt;/s:iterator&gt;
65   * &lt;/s:generator&gt;
66   * </pre>
67   * This generates an iterator and print it out using the iterator tag.
68   *
69   * Example Two:
70   * <pre>
71   * Generate an iterator with count attribute
72   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="3"&gt;
73   *  &lt;s:iterator&gt;
74   *      &lt;s:property /&gt;&lt;br/&gt;
75   *  &lt;/s:iterator&gt;
76   * &lt;/s:generator&gt;
77   * </pre>
78   * This generates an iterator, but only 3 entries will be available in the iterator
79   * generated, namely aaa, bbb and ccc respectively because count attribute is set to 3
80   *
81   * Example Three:
82   * <pre>
83   * Generate an iterator with var attribute
84   * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="4" separator="," var="myAtt" /&gt;
85   * &lt;%
86   *  Iterator i = (Iterator) pageContext.getAttribute("myAtt");
87   *  while(i.hasNext()) {
88   *      String s = (String) i.next(); %>
89   *      &lt;%=s%&gt; &lt;br/&gt;
90   * &lt;%    }
91   * %&gt;
92   * </pre>
93   * This generates an iterator and put it in the PageContext under the key as specified
94   * by the var attribute.
95   *
96   *
97   * Example Four:
98   * <pre>
99   * Generate an iterator with comparator attribute
100  * &lt;s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" converter="%{myConverter}"&gt;
101  *  &lt;s:iterator&gt;
102  *      &lt;s:property /&gt;&lt;br/&gt;
103  *  &lt;/s:iterator&gt;
104  * &lt;/s:generator&gt;
105  *
106  *
107  * public class GeneratorTagAction extends ActionSupport {
108  *
109  *   ....
110  *
111  *   public Converter getMyConverter() {
112  *      return new Converter() {
113  *          public Object convert(String value) throws Exception {
114  *              return "converter-"+value;
115  *          }
116  *      };
117  *   }
118  *
119  *   ...
120  *
121  * }
122  * </pre>
123  * This will generate an iterator with each entries decided by the converter supplied. With
124  * this converter, it simply add "converter-" to each entries.
125  * <!-- END SNIPPET: example -->
126  *
127  * @see org.apache.struts2.util.IteratorGenerator
128  */
129 @StrutsTag(name="generator", tldTagClass="org.apache.struts2.views.jsp.iterator.IteratorGeneratorTag",
130         description="Generate an iterator for a iterable source.")
131 public class IteratorGeneratorTag extends StrutsBodyTagSupport {
132 
133     private static final long serialVersionUID = 2968037295463973936L;
134 
135     public static final String DEFAULT_SEPARATOR = ",";
136 
137     private static final Logger LOG = LoggerFactory.getLogger(IteratorGeneratorTag.class);
138 
139     String countAttr;
140     String separatorAttr;
141     String valueAttr;
142     String converterAttr;
143     String var;
144     IteratorGenerator iteratorGenerator = null;
145 
146     @StrutsTagAttribute(type="Integer",description="The max number entries to be in the iterator")
147     public void setCount(String count) {
148         countAttr = count;
149     }
150 
151     /***
152      * @s.tagattribute required="true" type="String"
153      * description="the separator to be used in separating the <i>val</i> into entries of the iterator"
154      */
155     @StrutsTagAttribute(required=true, description="The separator to be used in separating the <i>val</i> into entries of the iterator")
156     public void setSeparator(String separator) {
157         separatorAttr = separator;
158     }
159 
160     /***
161      * @s.tagattribute required="true"
162      * description="the source to be parsed into an iterator"
163      */
164     @StrutsTagAttribute(required=true, description="The source to be parsed into an iterator")
165     public void setVal(String val) {
166         valueAttr = val;
167     }
168 
169     @StrutsTagAttribute(type="org.apache.struts2.util.IteratorGenerator.Converter",
170             description="The converter to convert the String entry parsed from <i>val</i> into an object")
171     public void setConverter(String aConverter) {
172         converterAttr = aConverter;
173     }
174 
175     @StrutsTagAttribute(description="Deprecated. Use 'var' instead")
176     public void setId(String string) {
177         setVar(string);
178     }
179 
180     @StrutsTagAttribute(description="The name to store the resultant iterator into page context, if such name is supplied")
181     public void setVar(String var) {
182         this.var = var;
183     }
184 
185     public int doStartTag() throws JspException {
186 
187         // value
188         Object value = findValue(valueAttr);
189 
190         // separator
191         String separator = DEFAULT_SEPARATOR;
192         if (separatorAttr != null && separatorAttr.length() > 0) {
193             separator = findString(separatorAttr);
194         }
195 
196         // TODO: maybe this could be put into an Util class, or there is already one?
197         // count
198         int count = 0;
199         if (countAttr != null && countAttr.length() > 0) {
200             Object countObj = findValue(countAttr);
201             if (countObj instanceof Number) {
202                 count = ((Number)countObj).intValue();
203             }
204             else if (countObj instanceof String) {
205                 try {
206                     count = Integer.parseInt((String)countObj);
207                 }
208                 catch(NumberFormatException e) {
209                     LOG.warn("unable to convert count attribute ["+countObj+"] to number, ignore count attribute", e);
210                 }
211             }
212         }
213 
214         // converter
215         Converter converter = null;
216         if (converterAttr != null && converterAttr.length() > 0) {
217             converter = (Converter) findValue(converterAttr);
218         }
219 
220 
221         iteratorGenerator = new IteratorGenerator();
222         iteratorGenerator.setValues(value);
223         iteratorGenerator.setCount(count);
224         iteratorGenerator.setSeparator(separator);
225         iteratorGenerator.setConverter(converter);
226 
227         iteratorGenerator.execute();
228 
229         // Push resulting iterator on stack and put into
230         // stack context if we have a "var" specified.
231         getStack().push(iteratorGenerator);
232         if (var != null && var.length() > 0) {
233             getStack().getContext().put(var, iteratorGenerator);
234         }
235 
236         return EVAL_BODY_INCLUDE;
237     }
238 
239     public int doEndTag() throws JspException {
240         // pop resulting iterator from stack at end tag
241         getStack().pop();
242         iteratorGenerator = null; // clean up
243 
244         return EVAL_PAGE;
245     }
246 }