1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jeuclid.biparser;
20
21 import java.io.StringReader;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.xml.sax.Attributes;
26 import org.xml.sax.InputSource;
27 import org.xml.sax.Locator;
28 import org.xml.sax.SAXException;
29 import org.xml.sax.helpers.DefaultHandler;
30
31
32
33
34
35
36
37
38 public class JEuclidSAXHandler extends DefaultHandler {
39
40
41
42
43 private static final Log LOGGER = LogFactory
44 .getLog(JEuclidSAXHandler.class);
45
46
47 private StringBuffer textBuffer;
48
49
50 private Locator locator;
51
52
53 private final BiTreeCreationHelper treeHelper;
54
55
56 private final String content;
57
58
59 private int position;
60
61
62 private int previousPosition;
63
64
65 private int lastLine;
66
67
68 private int lastColumn;
69
70
71 private final BiTree tree;
72
73
74
75
76
77
78
79
80
81 public JEuclidSAXHandler(final String c, final BiTree t) {
82 this.position = 0;
83 this.previousPosition = 0;
84 this.lastLine = 1;
85 this.lastColumn = 1;
86
87 this.content = c;
88 this.tree = t;
89 this.treeHelper = new BiTreeCreationHelper();
90 }
91
92
93
94
95
96
97
98 @Override
99 public final void setDocumentLocator(final Locator l) {
100 this.locator = l;
101 }
102
103
104
105
106
107
108
109
110
111
112 @Override
113 public final InputSource resolveEntity(final String publicId,
114 final String systemId) {
115 return new InputSource(new StringReader(""));
116 }
117
118
119
120
121
122
123
124 @Override
125 public final void startDocument() {
126 JEuclidSAXHandler.LOGGER.debug("SAX start document, length="
127 + this.content.length());
128 }
129
130
131
132
133
134
135
136 @Override
137 public final void endDocument() throws SAXException {
138 this.tree.setRoot(this.treeHelper.getRoot());
139 JEuclidSAXHandler.LOGGER.debug("SAX end document");
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 @Override
157 public final void startElement(final String namespaceURI,
158 final String sName, final String qName, final Attributes attrs)
159 throws SAXException {
160
161 int startPosition;
162 int length;
163
164 String eName;
165
166 eName = sName;
167 if ("".equals(eName)) {
168
169 eName = qName;
170 }
171
172
173 this.contentPosition();
174
175
176 startPosition = this.content.lastIndexOf("<" + eName,
177 this.position - 1);
178
179 if (this.textBuffer == null) {
180 length = 0;
181 } else {
182 length = this.textBuffer.length();
183 }
184
185 JEuclidSAXHandler.LOGGER.debug("tag-start=" + startPosition
186 + " tag-end=" + this.position + " buffer="
187 + (startPosition - this.previousPosition) + " textbuffer="
188 + length);
189
190
191 if (startPosition - this.previousPosition > 0) {
192 JEuclidSAXHandler.LOGGER.debug("empty length="
193 + (startPosition - this.previousPosition));
194
195 this.treeHelper.createEmtpyNode(startPosition
196 - this.previousPosition);
197 this.textBuffer = null;
198 }
199
200 this.printElement(namespaceURI, eName, true, startPosition, attrs);
201
202
203 this.treeHelper.createBiNode(startPosition, this.position
204 - startPosition, namespaceURI, eName, attrs);
205 }
206
207
208
209
210
211
212
213
214
215
216
217 @Override
218 public final void endElement(final String namespaceURI,
219 final String sName, final String qName) {
220
221 String eName = sName;
222
223 String text;
224
225 int textLength;
226 final String apo = "'";
227
228 if ("".equals(eName)) {
229
230 eName = qName;
231 }
232
233
234 this.contentPosition();
235
236
237 textLength = this.content.lastIndexOf("</", this.position - 1)
238 - this.previousPosition;
239
240
241 if (this.textBuffer != null && this.textBuffer.length() > 0
242 && this.treeHelper.allowNewTextNode()) {
243
244 text = this.textBuffer.toString();
245 this.treeHelper.createTextNode(textLength, text);
246 this.textBuffer = null;
247
248 JEuclidSAXHandler.LOGGER.debug(apo
249 + text.replaceAll(this.nl(), "#") + apo);
250
251 } else if (!this.treeHelper.allowNewTextNode() && textLength > 0) {
252
253 this.treeHelper.createEmtpyNode(textLength);
254 }
255
256
257 this.treeHelper.closeBiNode(this.position);
258
259 this.printElement(namespaceURI, eName, false, this.position, null);
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274 @Override
275 public final void characters(final char[] buf, final int offset,
276 final int len) throws SAXException {
277 final String s = new String(buf, offset, len);
278
279 if (this.textBuffer == null) {
280 this.textBuffer = new StringBuffer(s);
281 } else {
282 this.textBuffer.append(s);
283 }
284 }
285
286
287
288
289
290
291
292 private void contentPosition() {
293 final int line = this.locator.getLineNumber();
294 final int column = this.locator.getColumnNumber();
295 int l;
296
297 this.previousPosition = this.position;
298
299 JEuclidSAXHandler.LOGGER.debug("old line=" + this.lastLine);
300 for (l = this.lastLine; l < line; l = l + 1) {
301 this.position = 1 + this.content
302 .indexOf(this.nl(), this.position);
303
304 }
305
306 if (this.lastLine == line) {
307
308 this.position += column - this.lastColumn;
309 } else {
310
311
312 this.position += column - 2 + this.nl().length();
313 }
314
315 this.lastLine = line;
316 this.lastColumn = column;
317 JEuclidSAXHandler.LOGGER.debug(" - new line=" + this.lastLine
318 + " - old pos=" + this.previousPosition + " new pos="
319 + this.position);
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337 private void printElement(final String namespaceURI, final String name,
338 final boolean open, final int pos, final Attributes attrs) {
339 final StringBuffer sb = new StringBuffer(32);
340
341 sb.append(this.position());
342 sb.append(" - ");
343 sb.append(pos);
344
345 if (open) {
346 sb.append(" <");
347 } else {
348 sb.append(" </");
349 }
350
351 sb.append(name);
352
353 if (attrs != null) {
354 for (int i = 0; i < attrs.getLength(); i = i + 1) {
355
356 String aName = attrs.getLocalName(i);
357
358 if ("".equals(aName)) {
359 aName = attrs.getQName(i);
360 }
361
362 sb.append(' ');
363 sb.append(aName + "=\"" + attrs.getValue(i) + "\"");
364 }
365 }
366
367 if (namespaceURI != null && namespaceURI.length() > 0) {
368 sb.append(' ');
369 sb.append(namespaceURI);
370 }
371 sb.append('>');
372 sb.append(this.nl());
373
374 JEuclidSAXHandler.LOGGER.debug(sb.toString());
375 }
376
377
378
379
380
381
382 private String nl() {
383
384 return "\n";
385
386 }
387
388
389
390
391
392
393 private String position() {
394 final int line = this.locator.getLineNumber();
395 final int column = this.locator.getColumnNumber();
396 final StringBuffer sb = new StringBuffer();
397 final int dez = 10;
398
399 if (line < dez) {
400 sb.append('0');
401 }
402
403 sb.append(line);
404 sb.append('/');
405 if (column < dez) {
406 sb.append('0');
407 }
408
409 sb.append(column);
410 sb.append(':');
411
412 return sb.toString();
413 }
414 }