View Javadoc

    1   // ========================================================================
    2   // $Id: Composite.java,v 1.6 2004/05/09 20:31:28 gregwilkins Exp $
    3   // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
    4   // ------------------------------------------------------------------------
    5   // Licensed under the Apache License, Version 2.0 (the "License");
    6   // you may not use this file except in compliance with the License.
    7   // You may obtain a copy of the License at
    8   // http://www.apache.org/licenses/LICENSE-2.0
    9   // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  // ========================================================================
    15
    16  package org.mortbay.html;
    17  import java.io.IOException;
    18  import java.io.OutputStream;
    19  import java.io.OutputStreamWriter;
    20  import java.io.Writer;
    21  import java.util.ArrayList;
    22
    23
    24  /* -------------------------------------------------------------------- */
    25  /** HTML Composite Element.
    26   * <p>This class is can be used a either an abstract or concrete
    27   * holder of other HTML elements.
    28   * Used directly, it allow multiple HTML Elements to be added which
    29   * are produced sequentially.
    30   * Derived used of Composite may wrap each contain Element in
    31   * special purpose HTML tags (e.g. list).
    32   *
    33   * <p>Notes<br>
    34   * Elements are added to the Composite either as HTML Elements or as
    35   * Strings.  Other objects added to the Composite are converted to Strings
    36   * @see Element
    37   * @version $Id: Composite.java,v 1.6 2004/05/09 20:31:28 gregwilkins Exp $
    38   * @author Greg Wilkins
    39  */
    40  public class Composite extends Element
    41  {
    42      /* ----------------------------------------------------------------- */
    43      /** The vector of elements in this Composite.
    44       */
    45      protected ArrayList elements= new ArrayList(8);
    46
    47      /* ----------------------------------------------------------------- */
    48      protected Composite nest=null;
    49
    50      /* ----------------------------------------------------------------- */
    51      /** Default constructor.
    52       */
    53      public Composite()
    54      {}
    55
    56      /* ----------------------------------------------------------------- */
    57      /** Default constructor.
    58       */
    59      public Composite(String attributes)
    60      {
    61          super(attributes);
    62      }
    63
    64      /* ----------------------------------------------------------------- */
    65      /** Add an Object to the Composite by converting it to a Element or.
    66       * String
    67       * @param o The Object to add. If it is a String or Element, it is
    68       * added directly, otherwise toString() is called.
    69       * @return This Composite (for chained commands)
    70       */
    71      public Composite add(Object o)
    72      {
    73          if (nest!=null)
    74              nest.add(o);
    75          else
    76          {
    77              if (o!=null)
    78              {
    79                  if (o instanceof Element)
    80                  {
    81                      if(o instanceof Page)
    82                          throw new IllegalArgumentException("Can't insert Page in Composite");
    83                      elements.add(o);
    84                  }
    85                  else if (o instanceof String)
    86                      elements.add(o);
    87                  else
    88                      elements.add(o.toString());
    89              }
    90          }
    91          return this;
    92      }
    93
    94      /* ----------------------------------------------------------------- */
    95      /** Nest a Composite within a Composite.
    96       * The passed Composite is added to this Composite. Adds to
    97       * this composite are actually added to the nested Composite.
    98       * Calls to nest are passed the nested Composite
    99       * @return The Composite to unest on to return to the original
    100      * state.
    101      */
    102     public Composite nest(Composite c)
    103     {
    104         if (nest!=null)
    105             return nest.nest(c);
    106         else
    107         {
    108             add(c);
    109             nest=c;
    110         }
    111         return this;
    112     }
    113
    114     /* ----------------------------------------------------------------- */
    115     /** Explicit set of the Nested component.
    116      * No add is performed. setNest() obeys any current nesting and
    117      * sets the nesting of the nested component.
    118      */
    119     public Composite setNest(Composite c)
    120     {
    121         if (nest!=null)
    122             nest.setNest(c);
    123         else
    124             nest=c;
    125         return this;
    126     }
    127
    128     /* ----------------------------------------------------------------- */
    129     /** Recursively unnest the composites.
    130      */
    131     public Composite unnest()
    132     {
    133         if (nest!=null)
    134             nest.unnest();
    135         nest = null;
    136         return this;
    137     }
    138
    139
    140     /* ----------------------------------------------------------------- */
    141     /** The number of Elements in this Composite.
    142      * @return The number of elements in this Composite
    143      */
    144     public int size()
    145     {
    146         return elements.size();
    147     }
    148
    149     /* ----------------------------------------------------------------- */
    150     /** Write the composite.
    151      * The default implementation writes the elements sequentially. May
    152      * be overridden for more specialized behaviour.
    153      * @param out Writer to write the element to.
    154      */
    155     public void write(Writer out)
    156          throws IOException
    157     {
    158         for (int i=0; i <elements.size() ; i++)
    159         {
    160             Object element = elements.get(i);
    161
    162             if (element instanceof Element)
    163                 ((Element)element).write(out);
    164             else if (element==null)
    165                 out.write("null");
    166             else
    167                 out.write(element.toString());
    168         }
    169     }
    170
    171     /* ----------------------------------------------------------------- */
    172     /** Contents of the composite.
    173      */
    174     public String contents()
    175     {
    176         StringBuffer buf = new StringBuffer();
    177         synchronized(buf)
    178         {
    179             for (int i=0; i <elements.size() ; i++)
    180             {
    181                 Object element = elements.get(i);
    182                 if (element==null)
    183                     buf.append("null");
    184                 else
    185                     buf.append(element.toString());
    186             }
    187         }
    188         return buf.toString();
    189     }
    190
    191     /* ------------------------------------------------------------ */
    192     /** Empty the contents of this Composite .
    193      */
    194     public Composite reset()
    195     {
    196         elements.clear();
    197         return unnest();
    198     }
    199
    200     /* ----------------------------------------------------------------- */
    201     /* Flush is a package method used by Page.flush() to locate the
    202      * most nested composite, write out and empty its contents.
    203      */
    204     void flush(Writer out)
    205          throws IOException
    206     {
    207         if (nest!=null)
    208             nest.flush(out);
    209         else
    210         {
    211             write(out);
    212             elements.clear();
    213         }
    214     }
    215
    216     /* ----------------------------------------------------------------- */
    217     /* Flush is a package method used by Page.flush() to locate the
    218      * most nested composite, write out and empty its contents.
    219      */
    220     void flush(OutputStream out)
    221          throws IOException
    222     {
    223         flush(new OutputStreamWriter(out));
    224     }
    225
    226     /* ----------------------------------------------------------------- */
    227     /* Flush is a package method used by Page.flush() to locate the
    228      * most nested composite, write out and empty its contents.
    229      */
    230     void flush(OutputStream out, String encoding)
    231          throws IOException
    232     {
    233         flush(new OutputStreamWriter(out,encoding));
    234     }
    235
    236     /* ------------------------------------------------------------ */
    237     /** Replace an object within the composite.
    238      */
    239     public boolean replace(Object oldObj, Object newObj)
    240     {
    241         if (nest != null)
    242         {
    243             return nest.replace(oldObj, newObj);
    244         }
    245         else
    246         {
    247             int sz = elements.size();
    248             for (int i = 0; i < sz; i++)
    249             {
    250                 if (elements.get(i) == oldObj)
    251                 {
    252                     elements.set(i,newObj);
    253                     return true;
    254                 }
    255             }
    256         }
    257
    258         return false;
    259     }
    260
    261 }