001: /*
002: * $Id: MergeIterator.java 497654 2007-01-19 00:21:57Z rgielen $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.components;
022:
023: import java.io.Writer;
024: import java.util.ArrayList;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.struts2.views.annotations.StrutsTag;
031: import org.apache.struts2.views.annotations.StrutsTagAttribute;
032: import org.apache.struts2.components.Param.UnnamedParametric;
033: import org.apache.struts2.util.MakeIterator;
034: import org.apache.struts2.util.MergeIteratorFilter;
035:
036: import com.opensymphony.xwork2.util.ValueStack;
037:
038: /**
039: * <!-- START SNIPPET: javadoc -->
040: * <p>Component for MergeIteratorTag, which job is to merge iterators and successive
041: * call to the merged iterator will cause each merge iterator to have a chance to
042: * expose its element, subsequently next call will allow the next iterator to expose
043: * its element. Once the last iterator is done exposing its element, the first iterator
044: * is allowed to do so again (unless it is exhausted of entries).</P>
045: *
046: * <p>Internally the task are delegated to MergeIteratorFilter</p>
047: *
048: * <p>Example if there are 3 lists being merged, each list have 3 entries, the following will
049: * be the logic.</P>
050: * <ol>
051: * <li>Display first element of the first list</li>
052: * <li>Display first element of the second list</li>
053: * <li>Display first element of the third list</li>
054: * <li>Display second element of the first list</li>
055: * <li>Display second element of the second list</li>
056: * <li>Display second element of the third list</li>
057: * <li>Display third element of the first list</li>
058: * <li>Display thrid element of the second list</li>
059: * <li>Display third element of the thrid list</li>
060: * </ol>
061: * <!-- END SNIPPET: javadoc -->
062: *
063: * <!-- START SNIPPET: params -->
064: * <ul>
065: * <li>id (String) - the id where the resultant merged iterator will be stored in the stack's context</li>
066: * </ul>
067: * <!-- END SNIPPET: params -->
068: *
069: *
070: * <!-- START SNIPPET: javacode -->
071: * public class MergeIteratorTagAction extends ActionSupport {
072: *
073: * private List myList1;
074: * private List myList2;
075: * private List myList3;
076: *
077: * public List getMyList1() {
078: * return myList1;
079: * }
080: *
081: * public List getMyList2() {
082: * return myList2;
083: * }
084: *
085: * public List getMyList3() {
086: * return myList3;
087: * }
088: *
089: *
090: * public String execute() throws Exception {
091: *
092: * myList1 = new ArrayList();
093: * myList1.add("1");
094: * myList1.add("2");
095: * myList1.add("3");
096: *
097: * myList2 = new ArrayList();
098: * myList2.add("a");
099: * myList2.add("b");
100: * myList2.add("c");
101: *
102: * myList3 = new ArrayList();
103: * myList3.add("A");
104: * myList3.add("B");
105: * myList3.add("C");
106: *
107: * return "done";
108: * }
109: * }
110: * <!-- END SNIPPET: javacode -->
111: *
112: * <!-- START SNIPPET: example -->
113: * <s:merge id="myMergedIterator1">
114: * <s:param value="%{myList1}" />
115: * <s:param value="%{myList2}" />
116: * <s:param value="%{myList3}" />
117: * </s:merge>
118: * <s:iterator value="%{#myMergedIterator1}">
119: * <s:property />
120: * </s:iterator>
121: * <!-- END SNIPPET: example -->
122: *
123: * <!-- START SNIPPET: description -->
124: * This wil generate "1aA2bB3cC".
125: * <!-- START SNIPPET: description -->
126: *
127: * @see org.apache.struts2.util.MergeIteratorFilter
128: * @see org.apache.struts2.views.jsp.iterator.MergeIteratorTag
129: *
130: */
131: @StrutsTag(name="merge",tldTagClass="org.apache.struts2.views.jsp.iterator.MergeIteratorTag",description="Merge the values " + "of a list of iterators into one iterator")
132: public class MergeIterator extends Component implements
133: UnnamedParametric {
134:
135: private static final Log _log = LogFactory
136: .getLog(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
156: .hasNext();) {
157: Object iteratorEntryObj = parametersIterator.next();
158: if (!MakeIterator.isIterable(iteratorEntryObj)) {
159: _log
160: .warn("param with value resolved as "
161: + iteratorEntryObj
162: + " cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator");
163: continue;
164: }
165: mergeIteratorFilter.setSource(MakeIterator
166: .convert(iteratorEntryObj));
167: }
168:
169: mergeIteratorFilter.execute();
170:
171: // if id exists, we put it in the stack's context
172: if (getId() != null && getId().length() > 0) {
173: getStack().getContext().put(getId(), mergeIteratorFilter);
174: }
175:
176: mergeIteratorFilter = null;
177:
178: return super .end(writer, body);
179: }
180:
181: @StrutsTagAttribute(description="The id where the resultant merged iterator will be stored in the stack's context")
182: public void setId(String id) {
183: super .setId(id);
184: }
185:
186: // == UnnamedParametric interface implementation ---------------------
187: public void addParameter(Object value) {
188: _parameters.add(value);
189: }
190: }
|