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