View Javadoc

1   /*
2    * $Id: MergeIterator.java 451544 2006-09-30 05:38:02Z mrdon $
3    *
4    * Copyright 2006 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  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  * &lt;s:merge id="myMergedIterator1"&gt;
109  *		&lt;s:param value="%{myList1}" /&gt;
110  *		&lt;s:param value="%{myList2}" /&gt;
111  *		&lt;s:param value="%{myList3}" /&gt;
112  * &lt;/s:merge&gt;
113  * &lt;s:iterator value="%{#myMergedIterator1}"&gt;
114  *		&lt;s:property /&gt;
115  * &lt;/s:iterator&gt;
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 		// if id exists, we put it in the stack's context
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     // == UnnamedParametric interface implementation ---------------------
179 	public void addParameter(Object value) {
180 		_parameters.add(value);
181 	}
182 }