1 // Copyright (c) 2002, 2003, 2006 Per M.A. Bothner. 2 // This is free software; for terms and warranty disclaimer see ./COPYING. 3 4 package gnu.kawa.sax; 5 import gnu.lists.*; 6 import gnu.xml.*; 7 import org.xml.sax.*; 8 import gnu.mapping.Symbol; 9 import gnu.text.Char; 10 import org.xml.sax.helpers.AttributesImpl; 11 12 /** Forward Consumer events to a SAX2 ContentHandler. 13 */ 14 15 public class ContentConsumer implements Consumer 16 { 17 ContentHandler out; 18 /** Current nesting of elements. */ 19 int nesting = 0; 20 String[] names = new String[15]; 21 String attrQName, attrURI, attrLocalName; 22 AttributesImpl attributes = new AttributesImpl(); 23 char[] chBuffer; 24 /* #ifdef JAVA5 */ 25 StringBuilder strBuffer = new StringBuilder(200); 26 /* #else */ 27 // StringBuffer strBuffer = new StringBuffer(200); 28 /* #endif */ 29 /** 1 if in start-tag, 2 if in attribute value, 0 otherwise. */ 30 int inStartTag; 31 ContentConsumer()32 public ContentConsumer () 33 { 34 } 35 ContentConsumer(ContentHandler handler)36 public ContentConsumer (ContentHandler handler) 37 { 38 out = handler; 39 } 40 error(String method, SAXException ex)41 public void error(String method, SAXException ex) 42 { 43 throw new RuntimeException("caught "+ex+" in "+method); 44 } 45 endStartTag()46 public void endStartTag() 47 { 48 if (inStartTag != 1) 49 return; 50 int i = 3 * (nesting - 1); 51 try 52 { 53 out.startElement(names[i], names[i+1], names[i+2], attributes); 54 } 55 catch (SAXException ex) 56 { 57 error("startElement", ex); 58 } 59 attributes.clear(); 60 inStartTag = 0; 61 } 62 startElement(Object type)63 public void startElement (Object type) 64 { 65 if (inStartTag == 1) 66 endStartTag(); 67 flushStrBuffer(); 68 int i = 3 * nesting; 69 if (i >= names.length) 70 { 71 String[] tmp = new String[2 * i]; 72 System.arraycopy(names, 0, tmp, 0, i); 73 names = tmp; 74 } 75 String namespaceURI, localName; 76 if (type instanceof Symbol) 77 { 78 Symbol sym = (Symbol) type; 79 namespaceURI = sym.getNamespaceURI(); 80 localName = sym.getLocalName(); 81 } 82 else if (type instanceof XName) 83 { 84 XName sym = (XName) type; 85 namespaceURI = sym.getNamespaceURI(); 86 localName = sym.getLocalName(); 87 } 88 else 89 { 90 namespaceURI = ""; 91 localName = type.toString(); 92 } 93 names[i] = namespaceURI; 94 names[i+1] = localName; 95 names[i+2] = type.toString(); 96 inStartTag = 1; 97 nesting++; 98 } 99 startAttribute(Object attrType)100 public void startAttribute(Object attrType) 101 { 102 attrURI = ((Symbol) attrType).getNamespaceURI(); 103 attrLocalName = ((Symbol) attrType).getLocalName(); 104 attrQName = attrType.toString(); 105 inStartTag = 2; 106 } 107 endAttribute()108 public void endAttribute() 109 { 110 attributes.addAttribute(attrURI, attrLocalName, attrQName, "CDATA", 111 strBuffer.toString()); 112 strBuffer.setLength(0); 113 inStartTag = 1; 114 } 115 startDocument()116 public void startDocument() 117 { 118 try 119 { 120 out.startDocument(); 121 } 122 catch (SAXException ex) 123 { 124 error("startDocument", ex); 125 } 126 } 127 endDocument()128 public void endDocument() 129 { 130 try 131 { 132 out.endDocument(); 133 } 134 catch (SAXException ex) 135 { 136 error("endDocument", ex); 137 } 138 } 139 endElement()140 public void endElement () 141 { 142 endStartTag(); 143 flushStrBuffer(); 144 nesting--; 145 int i = 3 * nesting; 146 try 147 { 148 out.endElement(names[i], names[i+1], names[i+2]); 149 } 150 catch (SAXException ex) 151 { 152 error("endElement", ex); 153 } 154 names[i] = null; 155 names[i+1] = null; 156 names[i+2] = null; 157 } 158 flushStrBuffer()159 void flushStrBuffer() 160 { 161 if (strBuffer.length() > 0) 162 { 163 if (chBuffer == null) 164 chBuffer = new char[200]; 165 try 166 { 167 int slen = strBuffer.length(); 168 int start = 0; 169 for (;;) 170 { 171 int len = slen - start; 172 if (len <= 0) 173 break; 174 if (len > chBuffer.length) 175 len = chBuffer.length; 176 strBuffer.getChars(start, start + len, chBuffer, start); 177 out.characters(chBuffer, 0, len); 178 start += len; 179 } 180 strBuffer.setLength(0); 181 } 182 catch (SAXException ex) 183 { 184 error("characters", ex); 185 } 186 } 187 } 188 write(char[] buf, int off, int len)189 public void write(char[] buf, int off, int len) 190 { 191 if (inStartTag == 1) 192 endStartTag(); 193 if (inStartTag == 2) 194 strBuffer.append(buf, off, len); 195 else 196 { 197 flushStrBuffer(); 198 try 199 { 200 out.characters(buf, off, len); 201 } 202 catch (SAXException ex) 203 { 204 error("characters", ex); 205 } 206 } 207 } 208 write(int v)209 public void write (int v) 210 { 211 if (inStartTag == 1) 212 endStartTag(); 213 if (v >= 0x10000) 214 { 215 strBuffer.append((char) (((v - 0x10000) >> 10) + 0xD800)); 216 v = (v & 0x3FF) + 0xDC00; 217 } 218 strBuffer.append((char) v); 219 } 220 write(String v)221 public void write (String v) 222 { 223 if (inStartTag == 1) 224 endStartTag(); 225 strBuffer.append(v); 226 } 227 228 /* #ifdef use:java.lang.CharSequence */ write(CharSequence str, int start, int length)229 public void write (CharSequence str, int start, int length) 230 /* #else */ 231 // public void write (String str, int start, int length) 232 /* #endif */ 233 { 234 if (inStartTag == 1) 235 endStartTag(); 236 strBuffer.append(str, start, start+length); 237 } 238 239 /* #ifdef JAVA5 */ append(char c)240 public ContentConsumer append (char c) 241 { 242 write(c); 243 return this; 244 } append(CharSequence csq)245 public ContentConsumer append (CharSequence csq) 246 { 247 if (csq == null) 248 csq = "null"; 249 write(csq, 0, csq.length()); 250 return this; 251 } append(CharSequence csq, int start, int end)252 public ContentConsumer append (CharSequence csq, int start, int end) 253 { 254 if (csq == null) 255 csq = "null"; 256 write(csq, start, end); 257 return this; 258 } 259 /* #endif */ 260 writeObject(Object v)261 public void writeObject(Object v) 262 { 263 // Maybe prepend ' '? FIXME 264 if (v instanceof Consumable) 265 ((Consumable) v).consume(this); 266 else if (v instanceof SeqPosition) 267 { 268 SeqPosition pos = (SeqPosition) v; 269 pos.sequence.consumeNext(pos.ipos, this); 270 } 271 else if (v instanceof Char) 272 ((Char) v).print(this); 273 else 274 write(v == null ? "(null)" : v.toString()); 275 } 276 writeBoolean(boolean v)277 public void writeBoolean(boolean v) 278 { 279 if (inStartTag == 1) 280 endStartTag(); 281 // Maybe prepend ' '? FIXME 282 strBuffer.append(v); 283 } 284 writeLong(long v)285 public void writeLong(long v) 286 { 287 if (inStartTag == 1) 288 endStartTag(); 289 // Maybe prepend ' '? FIXME 290 strBuffer.append(v); 291 } 292 writeInt(int v)293 public void writeInt(int v) 294 { 295 if (inStartTag == 1) 296 endStartTag(); 297 // Maybe prepend ' '? FIXME 298 strBuffer.append(v); 299 } 300 writeFloat(float v)301 public void writeFloat(float v) 302 { 303 if (inStartTag == 1) 304 endStartTag(); 305 // Maybe prepend ' '? FIXME 306 strBuffer.append(v); 307 } 308 writeDouble(double v)309 public void writeDouble(double v) 310 { 311 if (inStartTag == 1) 312 endStartTag(); 313 // Maybe prepend ' '? FIXME 314 strBuffer.append(v); 315 } 316 finalize()317 public void finalize() 318 { 319 flushStrBuffer(); 320 } 321 ignoring()322 public boolean ignoring () 323 { 324 return false; 325 } 326 setContentHandler(ContentHandler handler)327 public void setContentHandler (ContentHandler handler) 328 { 329 out = handler; 330 } 331 getContentHandler()332 public ContentHandler getContentHandler () 333 { 334 return out; 335 } 336 } 337