1 /***
2 *
3 */
4 package net.trajano.twiff.renderer;
5
6 import java.io.IOException;
7 import java.io.PrintWriter;
8 import javax.servlet.http.HttpServletResponse;
9 import org.apache.commons.lang.StringEscapeUtils;
10 import org.xml.sax.Attributes;
11 import org.xml.sax.ContentHandler;
12 import org.xml.sax.Locator;
13 import org.xml.sax.SAXException;
14 import org.xml.sax.ext.LexicalHandler;
15
16 /***
17 * @author Archimedes Trajano
18 */
19 public class XmlRendererHandler implements ContentHandler, LexicalHandler {
20 /***
21 * State if the element is open.
22 */
23 private boolean elementOpen = false;
24
25 /***
26 * The writer
27 */
28 private final PrintWriter writer;
29
30 /***
31 * @param response
32 * @throws IOException
33 */
34 public XmlRendererHandler(final HttpServletResponse response) throws IOException {
35 this.writer = response.getWriter();
36 }
37
38 /***
39 * @param writer
40 */
41 public XmlRendererHandler(final PrintWriter writer) {
42 this.writer = writer;
43 }
44
45 /***
46 * @see org.xml.sax.ContentHandler#characters(char[], int, int)
47 */
48 public void characters(final char[] ch, final int start, final int length) throws SAXException {
49 closeStartElement();
50 writer.write(ch, start, length);
51 }
52
53 /***
54 * Closes an openned start element.
55 */
56 private void closeStartElement() {
57 if (elementOpen) {
58 writer.write('>');
59 elementOpen = false;
60 }
61 }
62
63 /***
64 * @param ch
65 * @param start
66 * @param length
67 * @throws SAXException
68 */
69 public void comment(char[] ch, int start, int length) throws SAXException {
70 closeStartElement();
71 writer.print("<!--");
72 writer.write(ch, start, length);
73 writer.print("-->");
74 }
75
76 /***
77 * @see org.xml.sax.ext.LexicalHandler#endCDATA()
78 */
79 public void endCDATA() throws SAXException {
80 writer.write("]]>");
81 }
82
83 /***
84 * @see org.xml.sax.ContentHandler#endDocument()
85 */
86 public void endDocument() throws SAXException {
87 closeStartElement();
88 }
89
90 /***
91 * @see org.xml.sax.ext.LexicalHandler#endDTD()
92 */
93 public void endDTD() throws SAXException {
94
95 }
96
97 /***
98 * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
99 * java.lang.String, java.lang.String)
100 */
101 public void endElement(final String uri, final String localName, final String qName) throws SAXException {
102 if (elementOpen) {
103 writer.write(" />");
104 elementOpen = false;
105 } else {
106 writer.write('<');
107 writer.write('/');
108 writer.print(qName);
109 writer.write('>');
110 }
111 }
112
113 /***
114 * @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)
115 */
116 public void endEntity(String name) throws SAXException {
117 }
118
119 /***
120 * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
121 */
122 public void endPrefixMapping(String prefix) throws SAXException {
123
124 }
125
126 /***
127 * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
128 */
129 public void ignorableWhitespace(final char[] ch, final int start, final int length) throws SAXException {
130 closeStartElement();
131 writer.write(ch, start, length);
132 }
133
134 /***
135 * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String,
136 * java.lang.String)
137 */
138 public void processingInstruction(String target, String data) throws SAXException {
139
140 }
141
142 /***
143 * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
144 */
145 public void setDocumentLocator(Locator locator) {
146
147 }
148
149 /***
150 * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
151 */
152 public void skippedEntity(String name) throws SAXException {
153
154 }
155
156 /***
157 * @see org.xml.sax.ext.LexicalHandler#startCDATA()
158 */
159 public void startCDATA() throws SAXException {
160 closeStartElement();
161 writer.write("<![CDATA[");
162 }
163
164 /***
165 * @see org.xml.sax.ContentHandler#startDocument()
166 */
167 public void startDocument() throws SAXException {
168
169 }
170
171 /***
172 * @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String,
173 * java.lang.String, java.lang.String)
174 */
175 public void startDTD(String name, String publicId, String systemId) throws SAXException {
176
177 }
178
179 /***
180 * This starts an element. It will check if the twiff component is
181 * specified, if it isn't it just returns the data as is. If it is present
182 * instead of writing directly to the writer, it will set the state that
183 * data gets appened to a string buffer. The buffer will then store all the
184 * data until it reaches the end element.
185 *
186 * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
187 * java.lang.String, java.lang.String, org.xml.sax.Attributes)
188 */
189 public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
190 closeStartElement();
191 writer.write('<');
192 writer.print(qName);
193 for (int i = 0; i < attributes.getLength(); ++i) {
194 writer.print(' ');
195 writer.write(attributes.getQName(i));
196 writer.print('=');
197 writer.print('"');
198 writer.write(StringEscapeUtils.escapeXml(attributes.getValue(i)));
199 writer.print('"');
200 }
201 elementOpen = true;
202 }
203
204 /***
205 * Does nothing.
206 *
207 * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String,
208 * java.lang.String)
209 */
210 public void startPrefixMapping(String prefix, String uri) throws SAXException {
211 }
212
213 /***
214 * Does nothing.
215 *
216 * @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
217 */
218 public void startEntity(String name) throws SAXException {
219
220 }
221 }