View Javadoc

1   /*
2    * $Id: MergeIterator.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.components;
23  
24  import java.io.Writer;
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import org.apache.struts2.components.Param.UnnamedParametric;
30  import org.apache.struts2.util.MakeIterator;
31  import org.apache.struts2.util.MergeIteratorFilter;
32  import org.apache.struts2.views.annotations.StrutsTag;
33  import org.apache.struts2.views.annotations.StrutsTagAttribute;
34  
35  import com.opensymphony.xwork2.util.ValueStack;
36  import com.opensymphony.xwork2.util.logging.Logger;
37  import com.opensymphony.xwork2.util.logging.LoggerFactory;
38  
39  /***
40   * <!-- START SNIPPET: javadoc -->
41   * <p>Component for MergeIteratorTag, which job is to merge iterators and successive
42   * call to the merged iterator will cause each merge iterator to have a chance to
43   * expose its element, subsequently next call will allow the next iterator to expose
44   * its element. Once the last iterator is done exposing its element, the first iterator
45   * is allowed to do so again (unless it is exhausted of entries).</P>
46   *
47   * <p>Internally the task are delegated to MergeIteratorFilter</p>
48   *
49   * <p>Example if there are 3 lists being merged, each list have 3 entries, the following will
50   * be the logic.</P>
51   * <ol>
52   *      <li>Display first element of the first list</li>
53   *      <li>Display first element of the second list</li>
54   *      <li>Display first element of the third list</li>
55   *      <li>Display second element of the first list</li>
56   *      <li>Display second element of the second list</li>
57   *      <li>Display second element of the third list</li>
58   *      <li>Display third element of the first list</li>
59   *      <li>Display thrid element of the second list</li>
60   *      <li>Display third element of the thrid list</li>
61   * </ol>
62   * <!-- END SNIPPET: javadoc -->
63   *
64   * <!-- START SNIPPET: params -->
65   * <ul>
66   *          <li>id (String) - the id where the resultant merged iterator will be stored in the stack's context</li>
67   * </ul>
68   * <!-- END SNIPPET: params -->
69   *
70   *
71   * <!-- START SNIPPET: javacode -->
72   * public class MergeIteratorTagAction extends ActionSupport {
73   *
74   *  private List myList1;
75   *  private List myList2;
76   *  private List myList3;
77   *
78   *  public List getMyList1() {
79   *      return myList1;
80   *  }
81   *
82   *  public List getMyList2() {
83   *      return myList2;
84   *  }
85   *
86   *  public List getMyList3() {
87   *      return myList3;
88   *  }
89   *
90   *
91   *  public String execute() throws Exception {
92   *
93   *      myList1 = new ArrayList();
94   *      myList1.add("1");
95   *      myList1.add("2");
96   *      myList1.add("3");
97   *
98   *      myList2 = new ArrayList();
99   *      myList2.add("a");
100  *      myList2.add("b");
101  *      myList2.add("c");
102  *
103  *      myList3 = new ArrayList();
104  *      myList3.add("A");
105  *      myList3.add("B");
106  *      myList3.add("C");
107  *
108  *      return "done";
109  *  }
110  * }
111  * <!-- END SNIPPET: javacode -->
112  *
113  * <!-- START SNIPPET: example -->
114  * &lt;s:merge var="myMergedIterator1"&gt;
115  *      &lt;s:param value="%{myList1}" /&gt;
116  *      &lt;s:param value="%{myList2}" /&gt;
117  *      &lt;s:param value="%{myList3}" /&gt;
118  * &lt;/s:merge&gt;
119  * &lt;s:iterator value="%{#myMergedIterator1}"&gt;
120  *      &lt;s:property /&gt;
121  * &lt;/s:iterator&gt;
122  * <!-- END SNIPPET: example -->
123  *
124  * <!-- START SNIPPET: description -->
125  * This wil generate "1aA2bB3cC".
126  * <!-- START SNIPPET: description -->
127  *
128  * @see org.apache.struts2.util.MergeIteratorFilter
129  * @see org.apache.struts2.views.jsp.iterator.MergeIteratorTag
130  *
131  */
132 @StrutsTag(name="merge", tldTagClass="org.apache.struts2.views.jsp.iterator.MergeIteratorTag", description="Merge the values " +
133                 "of a list of iterators into one iterator")
134 public class MergeIterator extends ContextBean implements UnnamedParametric {
135 
136     private static final Logger LOG = LoggerFactory.getLogger(MergeIterator.class);
137 
138     private MergeIteratorFilter mergeIteratorFilter = null;
139     private List _parameters;
140 
141     public MergeIterator(ValueStack stack) {
142         super(stack);
143     }
144 
145     public boolean start(Writer writer) {
146 
147         mergeIteratorFilter = new MergeIteratorFilter();
148         _parameters = new ArrayList();
149 
150         return super.start(writer);
151     }
152 
153     public boolean end(Writer writer, String body) {
154 
155         for (Iterator parametersIterator = _parameters.iterator(); parametersIterator.hasNext(); ) {
156             Object iteratorEntryObj = parametersIterator.next();
157             if (! MakeIterator.isIterable(iteratorEntryObj)) {
158                 LOG.warn("param with value resolved as "+iteratorEntryObj+" cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator");
159                 continue;
160             }
161             mergeIteratorFilter.setSource(MakeIterator.convert(iteratorEntryObj));
162         }
163 
164         mergeIteratorFilter.execute();
165 
166         // if id exists, we put it in the stack's context
167         putInContext(mergeIteratorFilter);
168 
169         mergeIteratorFilter = null;
170 
171         return super.end(writer, body);
172     }
173 
174     @StrutsTagAttribute(description="The name where the resultant merged iterator will be stored in the stack's context")
175     public void setVar(String var) {
176         super.setVar(var);
177     }
178 
179     // == UnnamedParametric interface implementation ---------------------
180     public void addParameter(Object value) {
181         _parameters.add(value);
182     }
183 }