001: // ========================================================================
002: // $Id: Composite.java,v 1.6 2004/05/09 20:31:28 gregwilkins Exp $
003: // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
004: // ------------------------------------------------------------------------
005: // Licensed under the Apache License, Version 2.0 (the "License");
006: // you may not use this file except in compliance with the License.
007: // You may obtain a copy of the License at
008: // http://www.apache.org/licenses/LICENSE-2.0
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014: // ========================================================================
015:
016: package org.mortbay.html;
017:
018: import java.io.IOException;
019: import java.io.OutputStream;
020: import java.io.OutputStreamWriter;
021: import java.io.Writer;
022: import java.util.ArrayList;
023:
024: /* -------------------------------------------------------------------- */
025: /** HTML Composite Element.
026: * <p>This class is can be used a either an abstract or concrete
027: * holder of other HTML elements.
028: * Used directly, it allow multiple HTML Elements to be added which
029: * are produced sequentially.
030: * Derived used of Composite may wrap each contain Element in
031: * special purpose HTML tags (e.g. list).
032: *
033: * <p>Notes<br>
034: * Elements are added to the Composite either as HTML Elements or as
035: * Strings. Other objects added to the Composite are converted to Strings
036: * @see Element
037: * @version $Id: Composite.java,v 1.6 2004/05/09 20:31:28 gregwilkins Exp $
038: * @author Greg Wilkins
039: */
040: public class Composite extends Element {
041: /* ----------------------------------------------------------------- */
042: /** The vector of elements in this Composite.
043: */
044: protected ArrayList elements = new ArrayList(8);
045:
046: /* ----------------------------------------------------------------- */
047: protected Composite nest = null;
048:
049: /* ----------------------------------------------------------------- */
050: /** Default constructor.
051: */
052: public Composite() {
053: }
054:
055: /* ----------------------------------------------------------------- */
056: /** Default constructor.
057: */
058: public Composite(String attributes) {
059: super (attributes);
060: }
061:
062: /* ----------------------------------------------------------------- */
063: /** Add an Object to the Composite by converting it to a Element or.
064: * String
065: * @param o The Object to add. If it is a String or Element, it is
066: * added directly, otherwise toString() is called.
067: * @return This Composite (for chained commands)
068: */
069: public Composite add(Object o) {
070: if (nest != null)
071: nest.add(o);
072: else {
073: if (o != null) {
074: if (o instanceof Element) {
075: if (o instanceof Page)
076: throw new IllegalArgumentException(
077: "Can't insert Page in Composite");
078: elements.add(o);
079: } else if (o instanceof String)
080: elements.add(o);
081: else
082: elements.add(o.toString());
083: }
084: }
085: return this ;
086: }
087:
088: /* ----------------------------------------------------------------- */
089: /** Nest a Composite within a Composite.
090: * The passed Composite is added to this Composite. Adds to
091: * this composite are actually added to the nested Composite.
092: * Calls to nest are passed the nested Composite
093: * @return The Composite to unest on to return to the original
094: * state.
095: */
096: public Composite nest(Composite c) {
097: if (nest != null)
098: return nest.nest(c);
099: else {
100: add(c);
101: nest = c;
102: }
103: return this ;
104: }
105:
106: /* ----------------------------------------------------------------- */
107: /** Explicit set of the Nested component.
108: * No add is performed. setNest() obeys any current nesting and
109: * sets the nesting of the nested component.
110: */
111: public Composite setNest(Composite c) {
112: if (nest != null)
113: nest.setNest(c);
114: else
115: nest = c;
116: return this ;
117: }
118:
119: /* ----------------------------------------------------------------- */
120: /** Recursively unnest the composites.
121: */
122: public Composite unnest() {
123: if (nest != null)
124: nest.unnest();
125: nest = null;
126: return this ;
127: }
128:
129: /* ----------------------------------------------------------------- */
130: /** The number of Elements in this Composite.
131: * @return The number of elements in this Composite
132: */
133: public int size() {
134: return elements.size();
135: }
136:
137: /* ----------------------------------------------------------------- */
138: /** Write the composite.
139: * The default implementation writes the elements sequentially. May
140: * be overridden for more specialized behaviour.
141: * @param out Writer to write the element to.
142: */
143: public void write(Writer out) throws IOException {
144: for (int i = 0; i < elements.size(); i++) {
145: Object element = elements.get(i);
146:
147: if (element instanceof Element)
148: ((Element) element).write(out);
149: else if (element == null)
150: out.write("null");
151: else
152: out.write(element.toString());
153: }
154: }
155:
156: /* ----------------------------------------------------------------- */
157: /** Contents of the composite.
158: */
159: public String contents() {
160: StringBuffer buf = new StringBuffer();
161: synchronized (buf) {
162: for (int i = 0; i < elements.size(); i++) {
163: Object element = elements.get(i);
164: if (element == null)
165: buf.append("null");
166: else
167: buf.append(element.toString());
168: }
169: }
170: return buf.toString();
171: }
172:
173: /* ------------------------------------------------------------ */
174: /** Empty the contents of this Composite .
175: */
176: public Composite reset() {
177: elements.clear();
178: return unnest();
179: }
180:
181: /* ----------------------------------------------------------------- */
182: /* Flush is a package method used by Page.flush() to locate the
183: * most nested composite, write out and empty its contents.
184: */
185: void flush(Writer out) throws IOException {
186: if (nest != null)
187: nest.flush(out);
188: else {
189: write(out);
190: elements.clear();
191: }
192: }
193:
194: /* ----------------------------------------------------------------- */
195: /* Flush is a package method used by Page.flush() to locate the
196: * most nested composite, write out and empty its contents.
197: */
198: void flush(OutputStream out) throws IOException {
199: flush(new OutputStreamWriter(out));
200: }
201:
202: /* ----------------------------------------------------------------- */
203: /* Flush is a package method used by Page.flush() to locate the
204: * most nested composite, write out and empty its contents.
205: */
206: void flush(OutputStream out, String encoding) throws IOException {
207: flush(new OutputStreamWriter(out, encoding));
208: }
209:
210: /* ------------------------------------------------------------ */
211: /** Replace an object within the composite.
212: */
213: public boolean replace(Object oldObj, Object newObj) {
214: if (nest != null) {
215: return nest.replace(oldObj, newObj);
216: } else {
217: int sz = elements.size();
218: for (int i = 0; i < sz; i++) {
219: if (elements.get(i) == oldObj) {
220: elements.set(i, newObj);
221: return true;
222: }
223: }
224: }
225:
226: return false;
227: }
228:
229: }
|