001: // Copyright (c) 2002, 2003, 2006 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.kawa.sax;
005:
006: import gnu.lists.*;
007: import gnu.xml.*;
008: import org.xml.sax.*;
009: import gnu.mapping.Symbol;
010: import gnu.text.Char;
011: import org.xml.sax.helpers.AttributesImpl;
012:
013: /** Forward Consumer events to a SAX2 ContentHandler.
014: */
015:
016: public class ContentConsumer implements Consumer {
017: ContentHandler out;
018: /** Current nesting of elements. */
019: int nesting = 0;
020: String[] names = new String[15];
021: String attrQName, attrURI, attrLocalName;
022: AttributesImpl attributes = new AttributesImpl();
023: char[] chBuffer;
024: /* #ifdef JAVA5 */
025: // StringBuilder strBuffer = new StringBuilder(200);
026: /* #else */
027: StringBuffer strBuffer = new StringBuffer(200);
028: /* #endif */
029: /** 1 if in start-tag, 2 if in attribute value, 0 otherwise. */
030: int inStartTag;
031:
032: public ContentConsumer() {
033: }
034:
035: public ContentConsumer(ContentHandler handler) {
036: out = handler;
037: }
038:
039: public void error(String method, SAXException ex) {
040: throw new RuntimeException("caught " + ex + " in " + method);
041: }
042:
043: public void endStartTag() {
044: if (inStartTag != 1)
045: return;
046: int i = 3 * (nesting - 1);
047: try {
048: out.startElement(names[i], names[i + 1], names[i + 2],
049: attributes);
050: } catch (SAXException ex) {
051: error("startElement", ex);
052: }
053: attributes.clear();
054: inStartTag = 0;
055: }
056:
057: public void startElement(Object type) {
058: if (inStartTag == 1)
059: endStartTag();
060: flushStrBuffer();
061: int i = 3 * nesting;
062: if (i >= names.length) {
063: String[] tmp = new String[2 * i];
064: System.arraycopy(names, 0, tmp, 0, i);
065: names = tmp;
066: }
067: String namespaceURI, localName;
068: if (type instanceof Symbol) {
069: Symbol sym = (Symbol) type;
070: namespaceURI = sym.getNamespaceURI();
071: localName = sym.getLocalName();
072: } else if (type instanceof XName) {
073: XName sym = (XName) type;
074: namespaceURI = sym.getNamespaceURI();
075: localName = sym.getLocalName();
076: } else {
077: namespaceURI = "";
078: localName = type.toString();
079: }
080: names[i] = namespaceURI;
081: names[i + 1] = localName;
082: names[i + 2] = type.toString();
083: inStartTag = 1;
084: nesting++;
085: }
086:
087: public void startAttribute(Object attrType) {
088: attrURI = ((Symbol) attrType).getNamespaceURI();
089: attrLocalName = ((Symbol) attrType).getLocalName();
090: attrQName = attrType.toString();
091: inStartTag = 2;
092: }
093:
094: public void endAttribute() {
095: attributes.addAttribute(attrURI, attrLocalName, attrQName,
096: "CDATA", strBuffer.toString());
097: strBuffer.setLength(0);
098: inStartTag = 1;
099: }
100:
101: public void startDocument() {
102: try {
103: out.startDocument();
104: } catch (SAXException ex) {
105: error("startDocument", ex);
106: }
107: }
108:
109: public void endDocument() {
110: try {
111: out.endDocument();
112: } catch (SAXException ex) {
113: error("endDocument", ex);
114: }
115: }
116:
117: public void endElement() {
118: endStartTag();
119: flushStrBuffer();
120: nesting--;
121: int i = 3 * nesting;
122: try {
123: out.endElement(names[i], names[i + 1], names[i + 2]);
124: } catch (SAXException ex) {
125: error("endElement", ex);
126: }
127: names[i] = null;
128: names[i + 1] = null;
129: names[i + 2] = null;
130: }
131:
132: void flushStrBuffer() {
133: if (strBuffer.length() > 0) {
134: if (chBuffer == null)
135: chBuffer = new char[200];
136: try {
137: int slen = strBuffer.length();
138: int start = 0;
139: for (;;) {
140: int len = slen - start;
141: if (len <= 0)
142: break;
143: if (len > chBuffer.length)
144: len = chBuffer.length;
145: strBuffer.getChars(start, start + len, chBuffer,
146: start);
147: out.characters(chBuffer, 0, len);
148: start += len;
149: }
150: strBuffer.setLength(0);
151: } catch (SAXException ex) {
152: error("characters", ex);
153: }
154: }
155: }
156:
157: public void write(char[] buf, int off, int len) {
158: if (inStartTag == 1)
159: endStartTag();
160: if (inStartTag == 2)
161: strBuffer.append(buf, off, len);
162: else {
163: flushStrBuffer();
164: try {
165: out.characters(buf, off, len);
166: } catch (SAXException ex) {
167: error("characters", ex);
168: }
169: }
170: }
171:
172: public void write(int v) {
173: if (inStartTag == 1)
174: endStartTag();
175: if (v >= 0x10000) {
176: strBuffer.append((char) (((v - 0x10000) >> 10) + 0xD800));
177: v = (v & 0x3FF) + 0xDC00;
178: }
179: strBuffer.append((char) v);
180: }
181:
182: public void write(String v) {
183: if (inStartTag == 1)
184: endStartTag();
185: strBuffer.append(v);
186: }
187:
188: /* #ifdef use:java.lang.CharSequence */
189: public void write(CharSequence str, int start, int end)
190: /* #else */
191: // public void write (String str, int start, int end)
192: /* #endif */
193: {
194: if (inStartTag == 1)
195: endStartTag();
196: /* #ifdef use:java.lang.CharSequence */
197: /* #ifdef JAVA5 */
198: // strBuffer.append(str, start, end);
199: /* #else */
200: strBuffer.append(str.subSequence(start, end).toString());
201: /* #endif */
202: /* #else */
203: // strBuffer.append(str.substring(start, end));
204: /* #endif */
205: }
206:
207: /* #ifdef JAVA5 */
208: // public ContentConsumer append (char c)
209: // {
210: // write(c);
211: // return this;
212: // }
213: // public ContentConsumer append (CharSequence csq)
214: // {
215: // if (csq == null)
216: // csq = "null";
217: // write(csq, 0, csq.length());
218: // return this;
219: // }
220: // public ContentConsumer append (CharSequence csq, int start, int end)
221: // {
222: // if (csq == null)
223: // csq = "null";
224: // write(csq, start, end);
225: // return this;
226: // }
227: /* #endif */
228:
229: public void writeObject(Object v) {
230: // Maybe prepend ' '? FIXME
231: if (v instanceof Consumable)
232: ((Consumable) v).consume(this );
233: else if (v instanceof SeqPosition) {
234: SeqPosition pos = (SeqPosition) v;
235: pos.sequence.consumeNext(pos.ipos, this );
236: } else if (v instanceof Char)
237: ((Char) v).print(this );
238: else
239: write(v == null ? "(null)" : v.toString());
240: }
241:
242: public void writeBoolean(boolean v) {
243: if (inStartTag == 1)
244: endStartTag();
245: // Maybe prepend ' '? FIXME
246: strBuffer.append(v);
247: }
248:
249: public void writeLong(long v) {
250: if (inStartTag == 1)
251: endStartTag();
252: // Maybe prepend ' '? FIXME
253: strBuffer.append(v);
254: }
255:
256: public void writeInt(int v) {
257: if (inStartTag == 1)
258: endStartTag();
259: // Maybe prepend ' '? FIXME
260: strBuffer.append(v);
261: }
262:
263: public void writeFloat(float v) {
264: if (inStartTag == 1)
265: endStartTag();
266: // Maybe prepend ' '? FIXME
267: strBuffer.append(v);
268: }
269:
270: public void writeDouble(double v) {
271: if (inStartTag == 1)
272: endStartTag();
273: // Maybe prepend ' '? FIXME
274: strBuffer.append(v);
275: }
276:
277: public void finalize() {
278: flushStrBuffer();
279: }
280:
281: public boolean ignoring() {
282: return false;
283: }
284:
285: public void setContentHandler(ContentHandler handler) {
286: out = handler;
287: }
288:
289: public ContentHandler getContentHandler() {
290: return out;
291: }
292: }
|