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