001 // =========================================================================== 002 // Copyright (c) 1996 Mort Bay Consulting Pty. Ltd. All rights reserved. 003 // $Id: Composite.java,v 1.1 2004/03/23 13:59:49 laurent Exp $ 004 // --------------------------------------------------------------------------- 005 006 package org.objectweb.jac.aspects.gui.web.html; 007 008 // Laurent Martelli <laurent@aopsys.com> - 21 mar. 2004: 009 // Added add(int position, Object element) method 010 011 import java.io.IOException; 012 import java.io.OutputStream; 013 import java.io.OutputStreamWriter; 014 import java.io.Writer; 015 import java.util.ArrayList; 016 import org.mortbay.util.Code; 017 import org.mortbay.html.Page; 018 019 /* -------------------------------------------------------------------- */ 020 /** HTML Composite Element. 021 * <p>This class is can be used a either an abstract or concrete 022 * holder of other HTML elements. 023 * Used directly, it allow multiple HTML Elements to be added which 024 * are produced sequentially. 025 * Derived used of Composite may wrap each contain Element in 026 * special purpose HTML tags (e.g. list). 027 * 028 * <p>Notes<br> 029 * Elements are added to the Composite either as HTML Elements or as 030 * Strings. Other objects added to the Composite are converted to Strings 031 * @see Element 032 * @version $Id: Composite.java,v 1.1 2004/03/23 13:59:49 laurent Exp $ 033 * @author Greg Wilkins 034 */ 035 public class Composite extends Element 036 { 037 /* ----------------------------------------------------------------- */ 038 /** The vector of elements in this Composite. 039 */ 040 protected ArrayList elements= new ArrayList(8); 041 042 /* ----------------------------------------------------------------- */ 043 protected Composite nest=null; 044 045 /* ----------------------------------------------------------------- */ 046 /** Default constructor. 047 */ 048 public Composite() 049 {} 050 051 /* ----------------------------------------------------------------- */ 052 /** Default constructor. 053 */ 054 public Composite(String attributes) 055 { 056 super(attributes); 057 } 058 059 /* ----------------------------------------------------------------- */ 060 /** Add an Object to the Composite by converting it to a Element or. 061 * String 062 * @param o The Object to add. If it is a String or Element, it is 063 * added directly, otherwise toString() is called. 064 * @return This Composite (for chained commands) 065 */ 066 public Composite add(Object o) 067 { 068 return add(elements.size(),o); 069 } 070 071 072 /* ----------------------------------------------------------------- */ 073 /** Add an Object to the Composite by converting it to a Element or. 074 * String 075 * @param o The Object to add. If it is a String or Element, it is 076 * added directly, otherwise toString() is called. 077 * @param position the position at which to insert the object 078 * @return This Composite (for chained commands) 079 */ 080 public Composite add(int position, Object o) 081 { 082 if (nest!=null) 083 nest.add(position,o); 084 else 085 { 086 if (o!=null) 087 { 088 if (o instanceof Element) 089 { 090 Code.assertTrue(!(o instanceof Page), 091 "Can't insert Page in Composite"); 092 elements.add(position,o); 093 } 094 else if (o instanceof String) 095 elements.add(position,o); 096 else 097 elements.add(position,o.toString()); 098 } 099 } 100 return this; 101 } 102 103 /* ----------------------------------------------------------------- */ 104 /** Nest a Composite within a Composite. 105 * The passed Composite is added to this Composite. Adds to 106 * this composite are actually added to the nested Composite. 107 * Calls to nest are passed the nested Composite 108 * @return The Composite to unest on to return to the original 109 * state. 110 */ 111 public Composite nest(Composite c) 112 { 113 if (nest!=null) 114 return nest.nest(c); 115 else 116 { 117 add(c); 118 nest=c; 119 } 120 return this; 121 } 122 123 /* ----------------------------------------------------------------- */ 124 /** Explicit set of the Nested component. 125 * No add is performed. setNest() obeys any current nesting and 126 * sets the nesting of the nested component. 127 */ 128 public Composite setNest(Composite c) 129 { 130 if (nest!=null) 131 nest.setNest(c); 132 else 133 nest=c; 134 return this; 135 } 136 137 /* ----------------------------------------------------------------- */ 138 /** Recursively unnest the composites. 139 */ 140 public Composite unnest() 141 { 142 if (nest!=null) 143 nest.unnest(); 144 nest = null; 145 return this; 146 } 147 148 149 /* ----------------------------------------------------------------- */ 150 /** The number of Elements in this Composite. 151 * @return The number of elements in this Composite 152 */ 153 public int size() 154 { 155 return elements.size(); 156 } 157 158 /* ----------------------------------------------------------------- */ 159 /** Write the composite. 160 * The default implementation writes the elements sequentially. May 161 * be overridden for more specialized behaviour. 162 * @param out Writer to write the element to. 163 */ 164 public void write(Writer out) 165 throws IOException 166 { 167 for (int i=0; i <elements.size() ; i++) 168 { 169 Object element = elements.get(i); 170 171 if (element instanceof Element) 172 ((Element)element).write(out); 173 else if (element==null) 174 out.write("null"); 175 else 176 out.write(element.toString()); 177 } 178 } 179 180 /* ----------------------------------------------------------------- */ 181 /** Contents of the composite. 182 */ 183 public String contents() 184 { 185 StringBuffer buf = new StringBuffer(); 186 synchronized(buf) 187 { 188 for (int i=0; i <elements.size() ; i++) 189 { 190 Object element = elements.get(i); 191 if (element==null) 192 buf.append("null"); 193 else 194 buf.append(element.toString()); 195 } 196 } 197 return buf.toString(); 198 } 199 200 /* ------------------------------------------------------------ */ 201 /** Empty the contents of this Composite . 202 */ 203 public Composite reset() 204 { 205 elements.clear(); 206 return unnest(); 207 } 208 209 /* ----------------------------------------------------------------- */ 210 /* Flush is a package method used by Page.flush() to locate the 211 * most nested composite, write out and empty its contents. 212 */ 213 void flush(Writer out) 214 throws IOException 215 { 216 if (nest!=null) 217 nest.flush(out); 218 else 219 { 220 write(out); 221 elements.clear(); 222 } 223 } 224 225 /* ----------------------------------------------------------------- */ 226 /* Flush is a package method used by Page.flush() to locate the 227 * most nested composite, write out and empty its contents. 228 */ 229 void flush(OutputStream out) 230 throws IOException 231 { 232 flush(new OutputStreamWriter(out)); 233 } 234 235 /* ----------------------------------------------------------------- */ 236 /* Flush is a package method used by Page.flush() to locate the 237 * most nested composite, write out and empty its contents. 238 */ 239 void flush(OutputStream out, String encoding) 240 throws IOException 241 { 242 flush(new OutputStreamWriter(out,encoding)); 243 } 244 245 /* ------------------------------------------------------------ */ 246 /** Replace an object within the composite. 247 */ 248 public boolean replace(Object oldObj, Object newObj) 249 { 250 if (nest != null) 251 { 252 return nest.replace(oldObj, newObj); 253 } 254 else 255 { 256 int sz = elements.size(); 257 for (int i = 0; i < sz; i++) 258 { 259 if (elements.get(i) == oldObj) 260 { 261 elements.set(i,newObj); 262 return true; 263 } 264 } 265 } 266 267 return false; 268 } 269 270 }