View Javadoc

    1   /*
    2    * $Id: MergeIterator.java 497654 2007-01-19 00:21:57Z rgielen $
    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  package org.apache.struts2.components;
    22
    23  import java.io.Writer;
    24  import java.util.ArrayList;
    25  import java.util.Iterator;
    26  import java.util.List;
    27
    28  import org.apache.commons.logging.Log;
    29  import org.apache.commons.logging.LogFactory;
    30  import org.apache.struts2.views.annotations.StrutsTag;
    31  import org.apache.struts2.views.annotations.StrutsTagAttribute;
    32  import org.apache.struts2.components.Param.UnnamedParametric;
    33  import org.apache.struts2.util.MakeIterator;
    34  import org.apache.struts2.util.MergeIteratorFilter;
    35
    36  import com.opensymphony.xwork2.util.ValueStack;
    37
    38  /***
    39   * <!-- START SNIPPET: javadoc -->
    40   * <p>Component for MergeIteratorTag, which job is to merge iterators and successive
    41   * call to the merged iterator will cause each merge iterator to have a chance to
    42   * expose its element, subsequently next call will allow the next iterator to expose
    43   * its element. Once the last iterator is done exposing its element, the first iterator
    44   * is allowed to do so again (unless it is exhausted of entries).</P>
    45   *
    46   * <p>Internally the task are delegated to MergeIteratorFilter</p>
    47   *
    48   * <p>Example if there are 3 lists being merged, each list have 3 entries, the following will
    49   * be the logic.</P>
    50   * <ol>
    51   *      <li>Display first element of the first list</li>
    52   *      <li>Display first element of the second list</li>
    53   *      <li>Display first element of the third list</li>
    54   *      <li>Display second element of the first list</li>
    55   *      <li>Display second element of the second list</li>
    56   *      <li>Display second element of the third list</li>
    57   *      <li>Display third element of the first list</li>
    58   *      <li>Display thrid element of the second list</li>
    59   *      <li>Display third element of the thrid list</li>
    60   * </ol>
    61   * <!-- END SNIPPET: javadoc -->
    62   *
    63   * <!-- START SNIPPET: params -->
    64   * <ul>
    65   *          <li>id (String) - the id where the resultant merged iterator will be stored in the stack's context</li>
    66   * </ul>
    67   * <!-- END SNIPPET: params -->
    68   *
    69   *
    70   * <!-- START SNIPPET: javacode -->
    71   * public class MergeIteratorTagAction extends ActionSupport {
    72   *
    73   *  private List myList1;
    74   *  private List myList2;
    75   *  private List myList3;
    76   *
    77   *  public List getMyList1() {
    78   *      return myList1;
    79   *  }
    80   *
    81   *  public List getMyList2() {
    82   *      return myList2;
    83   *  }
    84   *
    85   *  public List getMyList3() {
    86   *      return myList3;
    87   *  }
    88   *
    89   *
    90   *  public String execute() throws Exception {
    91   *
    92   *      myList1 = new ArrayList();
    93   *      myList1.add("1");
    94   *      myList1.add("2");
    95   *      myList1.add("3");
    96   *
    97   *      myList2 = new ArrayList();
    98   *      myList2.add("a");
    99   *      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  * &lt;s:merge id="myMergedIterator1"&gt;
    114  *      &lt;s:param value="%{myList1}" /&gt;
    115  *      &lt;s:param value="%{myList2}" /&gt;
    116  *      &lt;s:param value="%{myList3}" /&gt;
    117  * &lt;/s:merge&gt;
    118  * &lt;s:iterator value="%{#myMergedIterator1}"&gt;
    119  *      &lt;s:property /&gt;
    120  * &lt;/s:iterator&gt;
    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 " +
    132                 "of a list of iterators into one iterator")
    133 public class MergeIterator extends Component implements UnnamedParametric {
    134
    135     private static final Log _log = LogFactory.getLog(MergeIterator.class);
    136
    137     private MergeIteratorFilter mergeIteratorFilter = null;
    138     private List _parameters;
    139
    140     public MergeIterator(ValueStack stack) {
    141         super(stack);
    142     }
    143
    144     public boolean start(Writer writer) {
    145
    146         mergeIteratorFilter = new MergeIteratorFilter();
    147         _parameters = new ArrayList();
    148
    149         return super.start(writer);
    150     }
    151
    152     public boolean end(Writer writer, String body) {
    153
    154         for (Iterator parametersIterator = _parameters.iterator(); parametersIterator.hasNext(); ) {
    155             Object iteratorEntryObj = parametersIterator.next();
    156             if (! MakeIterator.isIterable(iteratorEntryObj)) {
    157                 _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");
    158                 continue;
    159             }
    160             mergeIteratorFilter.setSource(MakeIterator.convert(iteratorEntryObj));
    161         }
    162
    163         mergeIteratorFilter.execute();
    164
    165         // if id exists, we put it in the stack's context
    166         if (getId() != null && getId().length() > 0) {
    167             getStack().getContext().put(getId(), mergeIteratorFilter);
    168         }
    169
    170         mergeIteratorFilter = null;
    171
    172         return super.end(writer, body);
    173     }
    174
    175     @StrutsTagAttribute(description="The id where the resultant merged iterator will be stored in the stack's context")
    176     public void setId(String id) {
    177         super.setId(id);
    178     }
    179
    180     // == UnnamedParametric interface implementation ---------------------
    181     public void addParameter(Object value) {
    182         _parameters.add(value);
    183     }
    184 }