1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.xmlhammer.gui.output;
24
25 import java.io.IOException;
26 import java.lang.reflect.InvocationTargetException;
27 import java.net.URI;
28
29 import javax.swing.SwingUtilities;
30 import javax.swing.tree.DefaultTreeModel;
31 import javax.swing.tree.MutableTreeNode;
32 import javax.xml.transform.TransformerException;
33
34 import org.apache.log4j.Logger;
35 import org.bounce.util.URIUtils;
36 import org.w3c.dom.Attr;
37 import org.w3c.dom.Comment;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.NamedNodeMap;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.ProcessingInstruction;
42 import org.w3c.dom.Text;
43 import org.xml.sax.SAXParseException;
44 import org.xmlhammer.ResultModel;
45 import org.xmlhammer.model.project.Error;
46 import org.xmlhammer.model.project.Fatal;
47 import org.xmlhammer.model.project.Message;
48 import org.xmlhammer.model.project.Output;
49 import org.xmlhammer.model.project.Type;
50 import org.xmlhammer.model.project.Valid;
51 import org.xmlhammer.model.project.Warning;
52
53 /***
54 * The model for the result tree.
55 *
56 * @version $Revision: 1.23 $, $Date: 2007/07/04 19:42:48 $
57 * @author Edwin Dankert <edankert@gmail.com>
58 */
59
60 public class ResultTreeModel extends DefaultTreeModel implements ResultModel {
61 private static final long serialVersionUID = 1057354554421210781L;
62 private static final int TEXT_LIMIT = 256;
63 private Output output = null;
64 private URI base = null;
65 public int inserted = 0;
66 public int fired = 0;
67
68 public ResultTreeModel(Output output) {
69 super(new RootNode());
70
71 this.output = output;
72 }
73
74 public ResultTreeModel(Output output, URI base) {
75 super(new RootNode());
76
77 Logger.getLogger(this.getClass()).debug("ResultTreeModel( "+output+", "+base+")");
78
79 this.output = output;
80 this.base = base;
81 }
82
83 public void addWarning( URI src, SAXParseException exception) {
84 Warning warning = new Warning();
85
86 warning.setSrc(src.toString());
87 warning.setClazz(exception.getClass().getName());
88
89 warning.setMessage( exception.getMessage());
90 warning.setLocalizedMessage( exception.getLocalizedMessage());
91 warning.setLine( exception.getLineNumber());
92 warning.setColumn( exception.getColumnNumber());
93 warning.setSystemId( exception.getSystemId());
94 warning.setPublicId( exception.getPublicId());
95
96 output.getWarning().add( warning);
97
98 addNode( src, new WarningNode(src, warning));
99 }
100
101 public void addWarning( URI src, TransformerException exception) {
102 Warning warning = new Warning();
103
104 warning.setSrc(src.toString());
105 warning.setClazz(exception.getClass().getName());
106
107 warning.setMessage( exception.getMessage());
108 warning.setLocalizedMessage( exception.getLocalizedMessage());
109
110 if (exception.getLocator() != null) {
111 warning.setLine( exception.getLocator().getLineNumber());
112 warning.setColumn( exception.getLocator().getColumnNumber());
113 warning.setSystemId( exception.getLocator().getSystemId());
114 warning.setPublicId( exception.getLocator().getPublicId());
115 } else {
116 warning.setLine(-1);
117 warning.setColumn(-1);
118 warning.setSystemId(null);
119 warning.setPublicId(null);
120 }
121
122 output.getWarning().add( warning);
123
124 addNode(src, new WarningNode(src, warning));
125 }
126
127 public void addValid( URI src) {
128 Valid valid = new Valid();
129
130 valid.setSrc( src.toString());
131
132 output.setValid( valid);
133
134 addValidNode( src, true);
135 }
136
137 public void addError( URI src, SAXParseException exception) {
138 Error error = new Error();
139
140 error.setSrc(URIUtils.toString(src));
141 error.setClazz(exception.getClass().getName());
142
143 error.setMessage( exception.getMessage());
144 error.setLocalizedMessage( exception.getLocalizedMessage());
145 error.setLine( exception.getLineNumber());
146 error.setColumn( exception.getColumnNumber());
147 error.setSystemId( exception.getSystemId());
148 error.setPublicId( exception.getPublicId());
149
150 output.getError().add( error);
151
152 addNode( src, new ErrorNode(src, error));
153 }
154
155 public void addError( URI src, TransformerException exception) {
156 Error error = new Error();
157
158 error.setSrc(URIUtils.toString(src));
159 error.setClazz(exception.getClass().getName());
160
161 error.setMessage( exception.getMessage());
162 error.setLocalizedMessage( exception.getLocalizedMessage());
163 if (exception.getLocator() != null) {
164 error.setLine( exception.getLocator().getLineNumber());
165 error.setColumn( exception.getLocator().getColumnNumber());
166 error.setSystemId( exception.getLocator().getSystemId());
167 error.setPublicId( exception.getLocator().getPublicId());
168 } else {
169 error.setLine(-1);
170 error.setColumn(-1);
171 error.setSystemId(null);
172 error.setPublicId(null);
173 }
174
175 output.getError().add( error);
176
177 addNode(src, new ErrorNode(src, error));
178 }
179
180 public void addFatal( URI src, SAXParseException exception) {
181 Fatal fatal = new Fatal();
182
183 fatal.setSrc(URIUtils.toString(src));
184 fatal.setClazz(exception.getClass().getName());
185
186 fatal.setMessage( exception.getMessage());
187 fatal.setLocalizedMessage( exception.getLocalizedMessage());
188 fatal.setLine( exception.getLineNumber());
189 fatal.setColumn( exception.getColumnNumber());
190 fatal.setSystemId( exception.getSystemId());
191 fatal.setPublicId( exception.getPublicId());
192
193 output.getFatal().add( fatal);
194
195 addNode( src, new FatalNode(src, fatal));
196 }
197
198 public void addFatal( URI src, TransformerException exception) {
199 Fatal fatal = new Fatal();
200
201 fatal.setSrc(URIUtils.toString(src));
202 fatal.setClazz(exception.getClass().getName());
203
204 fatal.setMessage( exception.getMessage());
205 fatal.setLocalizedMessage( exception.getLocalizedMessage());
206
207 if (exception.getLocator() != null) {
208 fatal.setLine( exception.getLocator().getLineNumber());
209 fatal.setColumn( exception.getLocator().getColumnNumber());
210 fatal.setSystemId( exception.getLocator().getSystemId());
211 fatal.setPublicId( exception.getLocator().getPublicId());
212 } else {
213 fatal.setLine(-1);
214 fatal.setColumn(-1);
215 fatal.setSystemId(null);
216 fatal.setPublicId(null);
217 }
218
219 output.getFatal().add( fatal);
220
221 addNode( src, new FatalNode(src, fatal));
222 }
223
224 public void addFatal( URI src, IOException exception) {
225 Fatal fatal = new Fatal();
226
227 fatal.setSrc(URIUtils.toString(src));
228 fatal.setClazz(exception.getClass().getName());
229
230 fatal.setMessage( exception.getMessage());
231 fatal.setLocalizedMessage( exception.getLocalizedMessage());
232 fatal.setLine( -1);
233 fatal.setColumn( -1);
234
235 output.getFatal().add( fatal);
236
237 addNode( src, new FatalNode(src, fatal));
238 }
239
240 public void addValue( URI src, Object object) {
241 ResultNode resultNode = null;
242
243 if ( object instanceof Element) {
244 resultNode = createElementNode(src, (Element)object);
245 } else if ( object instanceof Attr) {
246 resultNode = createAttributeNode( src, (Attr)object);
247 } else if ( object instanceof Text) {
248 resultNode = createTextNode( src, (Text)object);
249 } else if ( object instanceof Comment) {
250 resultNode = createCommentNode( src, (Comment)object);
251 } else if ( object instanceof ProcessingInstruction) {
252 resultNode = createProcessingInstructionNode( src, (ProcessingInstruction)object);
253 } else if ( object instanceof Boolean) {
254 if (((Boolean)object)) {
255 resultNode = createBooleanNode( src, (Boolean)object);
256 }
257 } else if ( object instanceof String) {
258 if (object.toString().length() > 0) {
259 resultNode = createStringNode( src, (String)object);
260 }
261 } else if ( object instanceof Number) {
262 if (((Number)object).intValue() != 0) {
263 resultNode = createNumberNode( src, (Number)object);
264 }
265 } else {
266 resultNode = createValueNode( src, object);
267 }
268
269 if (resultNode != null) {
270 addNode( src, resultNode);
271 }
272 }
273
274 private ElementNode createElementNode( URI src, Element element) {
275 org.xmlhammer.model.project.Element value = new org.xmlhammer.model.project.Element();
276
277 value.setSrc(URIUtils.toString(src));
278
279 value.setLocalName( element.getLocalName());
280 value.setBaseURI( element.getBaseURI());
281 value.setClazz( element.getClass().getName());
282 value.setNamespaceURI( element.getNamespaceURI());
283 value.setNodeName( element.getNodeName());
284 value.setNodeValue( limitString(element.getNodeValue(), TEXT_LIMIT));
285 value.setPrefix( element.getPrefix());
286 value.setTagName( element.getTagName());
287 value.setTextContent( limitString(element.getTextContent(), TEXT_LIMIT));
288 value.setPath(getPath(element));
289 value.setText(limitString(element.getFirstChild(), TEXT_LIMIT).trim());
290 value.setContext(getContext(element, limitString(element.getFirstChild(), TEXT_LIMIT).trim()));
291
292 Type type = new Type();
293 type.setName(element.getSchemaTypeInfo().getTypeName());
294 type.setNamespace(element.getSchemaTypeInfo().getTypeNamespace());
295 value.setType( type);
296
297 return new ElementNode(src, value);
298 }
299
300 private TextNode createTextNode( URI src, Text text) {
301 org.xmlhammer.model.project.Text value = new org.xmlhammer.model.project.Text();
302
303 value.setSrc(URIUtils.toString(src));
304
305 value.setLocalName( text.getLocalName());
306 value.setBaseURI( text.getBaseURI());
307 value.setClazz( text.getClass().getName());
308 value.setNamespaceURI( text.getNamespaceURI());
309 value.setNodeName( text.getNodeName());
310 value.setNodeValue( limitString(text.getNodeValue(), TEXT_LIMIT));
311 value.setPrefix( text.getPrefix());
312 value.setTextContent( limitString(text.getTextContent(), TEXT_LIMIT));
313 value.setPath(getPath(text.getParentNode())+"/text()");
314 value.setContext(getContext(text.getParentNode(), limitString(text.getNodeValue(), TEXT_LIMIT)));
315
316 value.setData( limitString(text.getData(), TEXT_LIMIT));
317 value.setElementContentWhitespace( text.isElementContentWhitespace());
318 value.setWholeText( text.getWholeText());
319
320 return new TextNode(src, value);
321 }
322
323 private AttributeNode createAttributeNode( URI src, Attr attribute) {
324 org.xmlhammer.model.project.Attribute value = new org.xmlhammer.model.project.Attribute();
325
326 value.setSrc(URIUtils.toString(src));
327
328 value.setLocalName( attribute.getLocalName());
329 value.setBaseURI( attribute.getBaseURI());
330 value.setClazz( attribute.getClass().getName());
331 value.setNamespaceURI( attribute.getNamespaceURI());
332 value.setNodeName( attribute.getNodeName());
333 value.setNodeValue( attribute.getNodeValue());
334 value.setPrefix( attribute.getPrefix());
335 value.setName( attribute.getName());
336 value.setId( attribute.isId());
337 value.setSpecified( attribute.getSpecified());
338 value.setValue( attribute.getValue());
339 value.setTextContent(attribute.getTextContent());
340 value.setPath(getPath(attribute.getOwnerElement())+"/@"+attribute.getNodeName());
341 value.setContext(getContext(attribute.getOwnerElement(), limitString(attribute.getOwnerElement().getNodeValue(), TEXT_LIMIT)));
342
343 Type type = new Type();
344 type.setName(attribute.getSchemaTypeInfo().getTypeName());
345 type.setNamespace(attribute.getSchemaTypeInfo().getTypeNamespace());
346 value.setType( type);
347
348 return new AttributeNode(src, value);
349 }
350
351 private CommentNode createCommentNode( URI src, Comment comment) {
352 org.xmlhammer.model.project.Comment value = new org.xmlhammer.model.project.Comment();
353
354 value.setSrc(URIUtils.toString(src));
355
356 value.setLocalName( comment.getLocalName());
357 value.setBaseURI( comment.getBaseURI());
358 value.setClazz( comment.getClass().getName());
359 value.setNamespaceURI( comment.getNamespaceURI());
360 value.setNodeName( comment.getNodeName());
361 value.setNodeValue( limitString(comment.getNodeValue(), TEXT_LIMIT));
362 value.setPrefix( comment.getPrefix());
363 value.setTextContent( limitString(comment.getTextContent(), TEXT_LIMIT));
364 value.setPath(getPath(comment.getParentNode())+"/comment()");
365 value.setContext(getContext(comment.getParentNode(), writeComment(limitString(comment.getNodeValue(), TEXT_LIMIT))));
366
367 value.setData( limitString(comment.getData(), TEXT_LIMIT));
368 value.setLength( comment.getLength());
369
370 return new CommentNode(src, value);
371 }
372
373 private ProcessingInstructionNode createProcessingInstructionNode( URI src, ProcessingInstruction pi) {
374 org.xmlhammer.model.project.ProcessingInstruction value = new org.xmlhammer.model.project.ProcessingInstruction();
375
376 value.setSrc(URIUtils.toString(src));
377
378 value.setLocalName( pi.getLocalName());
379 value.setBaseURI( pi.getBaseURI());
380 value.setClazz( pi.getClass().getName());
381 value.setNamespaceURI( pi.getNamespaceURI());
382 value.setNodeName( pi.getNodeName());
383 value.setNodeValue( limitString(pi.getNodeValue(), TEXT_LIMIT));
384 value.setPrefix( pi.getPrefix());
385 value.setTextContent( limitString(pi.getTextContent(), TEXT_LIMIT));
386 value.setPath(getPath(pi.getParentNode())+"/processing-instruction()");
387 value.setContext(getContext(pi.getParentNode(), writePI(pi)));
388
389 value.setData( limitString(pi.getData(), TEXT_LIMIT));
390 value.setTarget( pi.getTarget());
391
392 return new ProcessingInstructionNode(src, value);
393 }
394
395 private ValueNode createBooleanNode( URI src, Boolean bool) {
396 org.xmlhammer.model.project.Boolean value = new org.xmlhammer.model.project.Boolean();
397
398 value.setSrc(URIUtils.toString(src));
399 value.setClazz( bool.getClass().getName());
400 value.setValue( bool.toString());
401
402 return new ValueNode(src, value);
403 }
404
405 private ValueNode createStringNode( URI src, String string) {
406 org.xmlhammer.model.project.String value = new org.xmlhammer.model.project.String();
407
408 value.setSrc(URIUtils.toString(src));
409 value.setClazz(string.getClass().getName());
410 value.setValue(string.toString());
411
412 return new ValueNode(src, value);
413 }
414
415 private ValueNode createNumberNode( URI src, Number number) {
416 org.xmlhammer.model.project.Number value = new org.xmlhammer.model.project.Number();
417
418 value.setSrc(URIUtils.toString(src));
419 value.setClazz(number.getClass().getName());
420 value.setValue(number.toString());
421
422 return new ValueNode(src, value);
423 }
424
425 private ValueNode createValueNode( URI src, Object object) {
426 org.xmlhammer.model.project.Object value = new org.xmlhammer.model.project.Object();
427
428 value.setSrc(URIUtils.toString(src));
429 value.setClazz(object.getClass().getName());
430 value.setValue(object.toString());
431
432 return new ValueNode(src, value);
433 }
434
435 public void addMessage(URI src, String type, String value) {
436 Message message = new Message();
437 message.setSrc(URIUtils.toString(src));
438 message.setType(type);
439 message.setValue(value);
440
441 addNode(src, new MessageNode(src, message));
442 }
443
444 public Output getOutput() {
445 return output;
446 }
447
448
449 private void addValidNode( final URI src, final boolean valid) {
450 try {
451 SwingUtilities.invokeAndWait( new Runnable() {
452 public void run() {
453 MutableTreeNode root = resolveDirectory( (MutableTreeNode)getRoot(), base, src);
454 insertNode( root, new URINode( src, valid));
455 }
456 });
457 } catch (InterruptedException e) {
458 Logger.getLogger(this.getClass()).error( "Unexpected Error", e);
459 } catch (InvocationTargetException e) {
460 Logger.getLogger(this.getClass()).error( "Unexpected Error", e);
461 }
462 }
463
464
465 private void addNode( final URI src, final ResultNode node) {
466 try {
467 SwingUtilities.invokeAndWait( new Runnable() {
468 public void run() {
469 MutableTreeNode root = resolveDirectory( (MutableTreeNode)getRoot(), base, src);
470
471 URINode uri = null;
472 for ( int i = 0; i < root.getChildCount(); i++) {
473 URINode child = (URINode)root.getChildAt( i);
474
475 if ( child.getURI().equals( src)) {
476 uri = child;
477 }
478 }
479
480 if ( uri == null) {
481
482 uri = new URINode( src);
483 insertNode( root, uri);
484 }
485
486 insertNode( uri, node);
487 }
488 });
489 } catch (InterruptedException e) {
490 Logger.getLogger(this.getClass()).error( "Unexpected Error", e);
491 } catch (InvocationTargetException e) {
492 Logger.getLogger(this.getClass()).error( "Unexpected Error", e);
493 }
494 }
495
496 private void insertNode( MutableTreeNode parent, ResultNode node) {
497 final int index = parent.getChildCount();
498 parent.insert( node, index);
499
500 int[] newIndexs = new int[1];
501 newIndexs[0] = index;
502 nodesWereInserted( parent, newIndexs);
503 }
504
505
506
507
508
509
510
511
512
513
514
515 public MutableTreeNode resolveDirectory( MutableTreeNode node, URI base, URI src) {
516 if ( base != null) {
517 URI relative = base.relativize( src);
518 String rel =relative.toString();
519
520 if ( rel.contains( "/")) {
521 URI dir = base.resolve( rel.substring( 0, rel.indexOf( '/')+1));
522
523 URINode uri = null;
524 for ( int i = 0; i < node.getChildCount(); i++) {
525 URINode child = (URINode)node.getChildAt( i);
526
527 if ( child.getURI().toString().equals( dir.toString())) {
528 uri = child;
529 break;
530 }
531 }
532
533 if ( uri != null) {
534 return resolveDirectory( uri, dir, src);
535 }
536
537
538 DirectoryNode dirNode = new DirectoryNode( dir);
539 insertNode( node, dirNode);
540 return resolveDirectory( dirNode, dir, src);
541 }
542 }
543
544 return node;
545 }
546
547 private static String limitString( Node node, int size) {
548 String result = "";
549
550 if (node instanceof Text) {
551 String value = node.getNodeValue();
552 if ( value != null) {
553 result = value;
554
555 if ( value.length() > size) {
556 result = value.substring(0, size-1) + "...";
557 }
558 }
559 }
560
561 return result;
562 }
563
564 private static String limitString( String value, int size) {
565 String result = "";
566 if ( value != null) {
567 result = value;
568
569 if ( value.length() > size) {
570 result = value.substring(0, size-1) + "...";
571 }
572 }
573
574 return result;
575 }
576
577 private static String getContext(Node node, String content) {
578 if (node instanceof Element) {
579 return getContext( (Element)node, content);
580 }
581
582 return content;
583 }
584
585 private static String getContext(Element element, String content) {
586 StringBuffer buffer = new StringBuffer("<");
587 buffer.append(element.getNodeName());
588
589 NamedNodeMap map = element.getAttributes();
590 for (int i = 0; i < map.getLength(); i++) {
591 Node node = map.item(i);
592 if (node instanceof Attr) {
593 buffer.append("\n\t");
594 buffer.append(writeAttribute((Attr)node));
595 }
596 }
597
598
599
600
601
602
603
604 buffer.append(">");
605 if ( content != null && content.length() > 0) {
606 buffer.append("\n\t");
607 buffer.append( content);
608 }
609 buffer.append("\n</");
610 buffer.append(element.getNodeName());
611 buffer.append(">");
612
613 return buffer.toString();
614 }
615
616 private static String writeAttribute(Attr attribute) {
617 StringBuffer buffer = new StringBuffer();
618
619
620
621
622
623
624
625 buffer.append(attribute.getNodeName());
626 buffer.append("=\"");
627 buffer.append(attribute.getNodeValue());
628 buffer.append("\"");
629
630 return buffer.toString();
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652 private static String writePI(ProcessingInstruction pi) {
653 StringBuffer buffer = new StringBuffer("<?");
654
655 buffer.append(pi.getTarget());
656 buffer.append(" ");
657 buffer.append(pi.getData());
658 buffer.append("?>");
659
660 return buffer.toString();
661 }
662
663 private static String writeComment(String comment) {
664 StringBuffer buffer = new StringBuffer("<!-- ");
665
666 buffer.append(comment);
667 buffer.append(" -->");
668
669 return buffer.toString();
670 }
671
672 private static String getPath(Node node) {
673 StringBuffer buffer = new StringBuffer();
674
675 if ( node != null && node instanceof Element) {
676 buffer.append(getPath(node.getParentNode()));
677 buffer.append("/");
678 buffer.append(node.getNodeName());
679 }
680
681 return buffer.toString();
682 }
683 }