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 }