1 package com.bonevich.erj.xml;
2
3 import org.tigris.gef.base.Diagram;
4 import org.tigris.gef.presentation.*;
5
6 import javax.xml.parsers.SAXParserFactory;
7 import javax.xml.parsers.SAXParser;
8 import org.xml.sax.Attributes;
9 import org.xml.sax.InputSource;
10 import org.xml.sax.helpers.DefaultHandler;
11
12 import java.io.*;
13 import java.util.HashMap;
14 import java.util.StringTokenizer;
15 import java.awt.Color;
16 import java.net.URL;
17
18 public class SVGReader extends DefaultHandler
19 {
20 ////////////////////////////////////////////////////////////////
21 // Static variables
22 private static SVGReader _instance = new SVGReader();
23 private static String[] _entityPaths = { "/com/bonevich/erj/xml/dtd/" };
24
25 ////////////////////////////////////////////////////////////////
26 // Instance variables
27 protected Diagram _diagram = null;
28 protected HashMap _figRegistry = null;
29 protected HashMap _ownerRegistry = new HashMap();
30 protected int _nestedGroups = 0;
31
32 ////////////////////////////////////////////////////////////////
33 // XML element handler states
34 private int _elementState = 0;
35 private static final int DEFAULT_STATE = 0;
36 private static final int TEXT_STATE = 1;
37 private static final int LINE_STATE = 2;
38 private static final int POLY_STATE = 3;
39 private static final int NODE_STATE = 4;
40 private static final int EDGE_STATE = 5;
41 private static final int PRIVATE_STATE = 6;
42
43 private static final int PRIVATE_NODE_STATE = 64;
44 private static final int PRIVATE_EDGE_STATE = 65;
45 private static final int TEXT_NODE_STATE = 14;
46 private static final int TEXT_EDGE_STATE = 15;
47
48 private int _x1Int = 0;
49 private int _y1Int = 0;
50 private StringBuffer _textBuf = null;
51 private FigLine _currentLine = null;
52 private FigText _currentText = null;
53 private FigPoly _currentPoly = null;
54 private FigNode _currentNode = null;
55 private FigEdge _currentEdge = null;
56
57 ////////////////////////////////////////////////////////////////
58 // Constructors
59 /***
60 * We are a Singleton Pattern, so the default constructor is
61 * not publicly available.
62 */
63 protected SVGReader() { }
64
65 /***
66 * Singleton instance accessor.
67 */
68 public static SVGReader getInstance()
69 {
70 return _instance;
71 }
72
73 /***
74 * Initialize the mapping of Fig owner Ids to Fig owner instances.
75 */
76 public void setOwnerRegistry(HashMap owners)
77 {
78 _ownerRegistry = owners;
79 }
80
81
82 ////////////////////////////////////////////////////////////////
83 // Main parsing access operations
84
85 /***
86 * Read a diagram given an InputStream on the SVG source.
87 * Note: does not close the stream after reading.
88 */
89 public synchronized Diagram readDiagram(InputStream is)
90 throws IOException
91 {
92 return readDiagram(new InputSource(is));
93 }
94
95 /***
96 * Read a diagram given an SVG InputSource.
97 */
98 public synchronized Diagram readDiagram(InputSource source)
99 throws IOException
100 {
101 try
102 {
103 System.out.println("======================================================");
104 System.out.println("== READING DIAGRAM: " + source.getSystemId());
105 System.out.println();
106
107 initDiagram("com.bonevich.erj.diagram.ERDiagram");
108 _figRegistry = new HashMap();
109
110 SAXParserFactory factory = SAXParserFactory.newInstance();
111 factory.setNamespaceAware(false);
112 factory.setValidating(false);
113 SAXParser pc = factory.newSAXParser();
114 pc.parse(source, this);
115 return _diagram;
116 }
117 catch (Exception e)
118 {
119 e.printStackTrace();
120 throw new IOException("Failed to load project diagram: " + e);
121 }
122 }
123
124 /***
125 * Read a diagram given an URL to an SVG source.
126 */
127 public synchronized Diagram readDiagram(URL url)
128 throws IOException
129 {
130 InputStream is = url.openStream();
131 InputSource source = new InputSource(is);
132 source.setSystemId(url.toString());
133
134 readDiagram(source);
135
136 source = null;
137 is.close();
138 return _diagram;
139 }
140
141 /***
142 * Instantiate and initialize a diagram given a descriptor.
143 * The descriptor is of the form "{{diagramClassName}}[|{{ownerInstanceId}}]"
144 */
145 protected void initDiagram(String descriptor)
146 {
147 String className = descriptor;
148 String initStr = null;
149 int pipe = descriptor.indexOf(PIPE_STR);
150 if (pipe != -1)
151 {
152 className = descriptor.substring(0, pipe);
153 initStr = descriptor.substring(pipe + 1);
154 }
155
156 String newClassName = translateClassName(className);
157 try
158 {
159 Class cls = Class.forName(newClassName);
160 _diagram = (Diagram) cls.newInstance();
161
162 if (initStr != null && !initStr.equals(EMPTY_STR))
163 {
164 _diagram.initialize(findOwner(initStr));
165 }
166 }
167 catch (Exception ex)
168 {
169 System.out.println("Could not set diagram type to " + newClassName);
170 ex.printStackTrace();
171 }
172 }
173
174
175 //////////////////////////////////////////////////////////
176 // SAX2 ContentHandler implementation
177
178 public void startElement(String namespace,
179 String localName,
180 String qualifiedName,
181 Attributes attrs)
182 {
183 switch(_elementState)
184 {
185 case DEFAULT_STATE:
186 if (qualifiedName.equals(ELEMENT_GROUP_STR))
187 {
188 _nestedGroups++;
189 _diagram.add(handleGroup(attrs));
190 }
191 else if (qualifiedName.equals(ELEMENT_SVG_STR))
192 {
193 handleSVG(attrs);
194 }
195 else if (_nestedGroups == 0)
196 {
197 if (qualifiedName.equals(ELEMENT_PATH_STR))
198 {
199 _diagram.add(handlePolyLine(attrs));
200 }
201 else if (qualifiedName.equals(ELEMENT_ELLIPSE_STR))
202 {
203 _diagram.add(handleEllipse(attrs));
204 }
205 else if (qualifiedName.equals(ELEMENT_RECT_STR))
206 {
207 _diagram.add(handleRect(attrs));
208 }
209 else if (qualifiedName.equals(ELEMENT_TEXT_STR))
210 {
211 _elementState = TEXT_STATE;
212 _diagram.add(handleText(attrs));
213 }
214 else if (qualifiedName.equals(ELEMENT_LINE_STR))
215 {
216 _diagram.add(handleLine(attrs));
217 }
218 else
219 {
220 System.out.println("Unknown top-level tag: " + qualifiedName);
221 }
222 }
223 else if (_nestedGroups > 0)
224 {
225 //System.out.println("Skipping nested " + qualifiedName);
226 }
227 break;
228
229 case LINE_STATE:
230 lineStateStartElement(qualifiedName, attrs);
231 break;
232
233 case POLY_STATE:
234 polyStateStartElement(qualifiedName, attrs);
235 break;
236
237 case NODE_STATE:
238 nodeStateStartElement(qualifiedName, attrs);
239 break;
240
241 case EDGE_STATE:
242 edgeStateStartElement(qualifiedName, attrs);
243 break;
244 }
245 }
246
247 public void characters(char[] ch, int start, int length)
248 {
249 if(_textBuf != null &&
250 (_elementState == TEXT_STATE || _elementState == PRIVATE_STATE ||
251 _elementState == TEXT_NODE_STATE || _elementState == TEXT_EDGE_STATE ||
252 _elementState == PRIVATE_NODE_STATE || _elementState == PRIVATE_EDGE_STATE)
253 )
254 {
255 _textBuf.append(ch, start, length);
256 }
257 }
258
259 public void endElement(String namespace, String localName, String qualifiedName)
260 {
261 //System.err.println("(endElement) namespace = " + namespace + " and qualifiedName = " + qualifiedName);
262 switch(_elementState)
263 {
264 case 0:
265 if (qualifiedName.equals(ELEMENT_GROUP_STR))
266 {
267 _nestedGroups--;
268 }
269 break;
270
271 case POLY_STATE:
272 if(qualifiedName.equals(ELEMENT_PATH_STR))
273 {
274 _elementState = DEFAULT_STATE;
275 _currentPoly = null;
276 }
277 break;
278
279 case LINE_STATE:
280 if(qualifiedName.equals(ELEMENT_LINE_STR))
281 {
282 _elementState = DEFAULT_STATE;
283 _currentLine = null;
284 }
285 break;
286
287 case TEXT_STATE:
288 if(qualifiedName.equals(ELEMENT_TEXT_STR))
289 {
290 _currentText.setText(_textBuf.toString());
291 _elementState = DEFAULT_STATE;
292 _currentText = null;
293 _textBuf = null;
294 }
295 break;
296
297 case TEXT_NODE_STATE:
298 if(qualifiedName.equals(ELEMENT_TEXT_STR))
299 {
300 _currentText.setText(_textBuf.toString());
301 _elementState = NODE_STATE;
302 _currentText = null;
303 _textBuf = null;
304 }
305 break;
306
307 case TEXT_EDGE_STATE:
308 if(qualifiedName.equals(ELEMENT_TEXT_STR))
309 {
310 _currentText.setText(_textBuf.toString());
311 _elementState = EDGE_STATE;
312 _currentText = null;
313 _textBuf = null;
314 }
315 break;
316
317 case NODE_STATE:
318 _elementState = DEFAULT_STATE;
319 _currentNode = null;
320 _textBuf = null;
321 break;
322
323 // case EDGE_STATE:
324 // _elementState = DEFAULT_STATE;
325 // _currentEdge = null;
326 // _textBuf = null;
327 // break;
328
329 case PRIVATE_STATE:
330 privateStateEndElement(qualifiedName);
331 _textBuf = null;
332 _elementState = DEFAULT_STATE;
333 break;
334
335 case PRIVATE_NODE_STATE:
336 privateStateEndElement(qualifiedName);
337 _textBuf = null;
338 _elementState = NODE_STATE;
339 break;
340
341 case PRIVATE_EDGE_STATE:
342 privateStateEndElement(qualifiedName);
343 _textBuf = null;
344 _elementState = EDGE_STATE;
345 break;
346 }
347 }
348
349 //////////////////////////////////////////////////////////
350 // SAX2 EntityResolver implementation
351
352 public InputSource resolveEntity(String publicId, String systemId)
353 {
354 InputSource source = null;
355 try
356 {
357 URL url = new URL(systemId);
358 try
359 {
360 source = new InputSource(url.openStream());
361 source.setSystemId(systemId);
362 if (publicId != null)
363 {
364 source.setPublicId(publicId);
365 }
366 }
367 catch (IOException e)
368 {
369 if (systemId.endsWith(".dtd"))
370 {
371 int i = systemId.lastIndexOf('/');
372 i++; // go past '/' if there, otherwise advance to 0
373 InputStream is = null;
374 for (int pathIndex = 0; pathIndex < _entityPaths.length && is == null; pathIndex++)
375 {
376 String DTD_DIR = _entityPaths[pathIndex];
377 is = getClass().getResourceAsStream(DTD_DIR + systemId.substring(i));
378 if(is == null)
379 {
380 try
381 {
382 is = new FileInputStream(DTD_DIR.substring(1) + systemId.substring(i));
383 }
384 catch(Exception ex) {}
385 }
386 }
387 if(is != null)
388 {
389 source = new InputSource(is);
390 source.setSystemId(systemId);
391 if(publicId != null)
392 {
393 source.setPublicId(publicId);
394 }
395 }
396 }
397 }
398 }
399 catch(Exception e)
400 {
401 e.printStackTrace();
402 }
403
404 //
405 // returning an "empty" source is better than failing
406 //
407 if (source == null)
408 {
409 source = new InputSource();
410 source.setSystemId(systemId);
411 }
412 return source;
413 }
414
415
416 ////////////////////////////////////////////////////////////////
417 // Internal parsing methods
418
419 protected void handleSVG(Attributes attrs)
420 {
421 String name = attrs.getValue(FIG_NAME_ATTR_STR);
422 String clsName = attrs.getValue(FIG_CLASS_ATTR_STR);
423 try
424 {
425 if (clsName != null && !clsName.equals(EMPTY_STR))
426 {
427 initDiagram(clsName);
428 }
429 if (name != null && !name.equals(EMPTY_STR))
430 {
431 _diagram.setName(name);
432 }
433 }
434 catch (Exception e)
435 {
436 e.printStackTrace();
437 System.out.println("Exception in handleSVG");
438 }
439 }
440
441 protected FigCircle handleEllipse(Attributes attrs)
442 {
443 FigCircle f = new FigCircle(0, 0, 50, 50);
444 setAttrs(f, attrs);
445
446 String cx = attrs.getValue(FIG_CENTER_X_ATTR_STR);
447 String cy = attrs.getValue(FIG_CENTER_Y_ATTR_STR);
448 String rx = attrs.getValue(FIG_RADIUS_X_ATTR_STR);
449 String ry = attrs.getValue(FIG_RADIUS_Y_ATTR_STR);
450
451 int cxInt = (cx == null || cx.equals(EMPTY_STR)) ? 0 : Integer.parseInt(cx);
452 int cyInt = (cy == null || cy.equals(EMPTY_STR)) ? 0 : Integer.parseInt(cy);
453 int rxInt = (rx == null || rx.equals(EMPTY_STR)) ? 10 : Integer.parseInt(rx);
454 int ryInt = (ry == null || ry.equals(EMPTY_STR)) ? 10 : Integer.parseInt(ry);
455
456 f.setX( cxInt - rxInt );
457 f.setY( cyInt - ryInt );
458 f.setWidth(rxInt * 2);
459 f.setHeight(ryInt * 2);
460
461 return f;
462 }
463
464 /***
465 * Returns Fig rather than FigGroups because this is
466 * also used for FigEdges.
467 */
468 protected Fig handleGroup(Attributes attrs)
469 {
470 Fig f = null;
471
472 String clsNameBounds = attrs.getValue(FIG_CLASS_ATTR_STR);
473 StringTokenizer st = new StringTokenizer(clsNameBounds, GROUP_TOKENIZER_STR);
474 String xStr = null, yStr = null, wStr = null, hStr = null;
475
476 String clsName = st.nextToken();
477 if (st.hasMoreElements())
478 {
479 xStr = st.nextToken();
480 yStr = st.nextToken();
481 wStr = st.nextToken();
482 hStr = st.nextToken();
483 }
484
485 try {
486 Class nodeClass = Class.forName(translateClassName(clsName));
487 f = (Fig) nodeClass.newInstance();
488 if (xStr != null && !xStr.equals(EMPTY_STR))
489 {
490 int x = Integer.parseInt(xStr);
491 int y = Integer.parseInt(yStr);
492 int w = Integer.parseInt(wStr);
493 int h = Integer.parseInt(hStr);
494 f.setBounds(x, y, w, h);
495 }
496
497 if (f instanceof FigNode)
498 {
499 FigNode fn = (FigNode) f;
500 _currentNode = fn;
501 _elementState = NODE_STATE;
502 _textBuf = new StringBuffer();
503 }
504 else if (f instanceof FigEdge)
505 {
506 _currentEdge = (FigEdge) f;
507 _elementState = EDGE_STATE;
508 }
509 }
510 catch (Exception e)
511 {
512 System.out.println("Exception in handleGroup");
513 e.printStackTrace();
514 }
515 catch (NoSuchMethodError e)
516 {
517 System.out.println("No default constructor for class " + clsName);
518 e.printStackTrace();
519 }
520
521 setAttrs(f, attrs);
522 return f;
523 }
524
525 protected Fig handlePolyLine(Attributes attrs)
526 {
527 String clsName = translateClassName(attrs.getValue(FIG_PATH_DESC_ATTR_STR));
528 if (clsName != null && clsName.indexOf(FIG_LINE_STR) != -1)
529 {
530 return handleLine(attrs);
531 }
532 else
533 {
534 return handlePath(attrs);
535 }
536 }
537
538 protected FigLine handleLine(Attributes attrs)
539 {
540 _currentLine = new FigLine(0, 0, 100, 100);
541 setAttrs(_currentLine, attrs);
542
543 String x1 = attrs.getValue(FIG_X1_ATTR_STR);
544 String y1 = attrs.getValue(FIG_Y1_ATTR_STR);
545 _x1Int = (x1 == null || x1.equals(EMPTY_STR)) ? 0 : Integer.parseInt(x1);
546 _y1Int = (y1 == null || y1.equals(EMPTY_STR)) ? 0 : Integer.parseInt(y1);
547 _currentLine.setX1(_x1Int);
548 _currentLine.setY1(_y1Int);
549
550 String x2 = attrs.getValue(FIG_X2_ATTR_STR);
551 String y2 = attrs.getValue(FIG_Y2_ATTR_STR);
552 int x2Int = (x2 == null || x2.equals(EMPTY_STR)) ? _x1Int : Integer.parseInt(x2);
553 int y2Int = (y2 == null || y2.equals(EMPTY_STR)) ? _y1Int : Integer.parseInt(y2);
554 _currentLine.setX2(x2Int);
555 _currentLine.setY2(y2Int);
556
557 _elementState = LINE_STATE;
558 return _currentLine;
559 }
560
561 protected FigPoly handlePath(Attributes attrs)
562 {
563 String type = attrs.getValue(FIG_CLASS_ATTR_STR);
564
565 FigPoly f = null;
566 try
567 {
568 Class pathClass = Class.forName(translateClassName(type));
569 f = (FigPoly) pathClass.newInstance();
570
571 // Set the default attributes
572 setAttrs(f, attrs);
573
574 _currentPoly = f;
575 _elementState = POLY_STATE;
576
577 // Set the path data
578 String path = attrs.getValue(FIG_PATH_DATA_ATTR_STR);
579 int x = -1;
580 int y = -1;
581
582 StringReader reader = new StringReader(path);
583 StreamTokenizer tokenizer = new StreamTokenizer(reader);
584
585 int tok = tokenizer.nextToken();
586 while (tok != StreamTokenizer.TT_EOF)
587 {
588 if (tok == StreamTokenizer.TT_NUMBER)
589 {
590 if (x == -1)
591 {
592 x = (int)tokenizer.nval;
593 }
594 else
595 {
596 y = (int)tokenizer.nval;
597 }
598
599 // Add the point
600 if (x != -1 && y != -1)
601 {
602 f.addPoint(x,y);
603 x = -1;
604 y = -1;
605 }
606 }
607
608 tok = tokenizer.nextToken();
609 }
610 }
611 catch (Exception e)
612 {
613 e.printStackTrace();
614 }
615
616 return f;
617 }
618
619 protected FigRect handleRect(Attributes attrs)
620 {
621 FigRect f;
622 String cornerRadius = attrs.getValue(FIG_RADIUS_X_ATTR_STR);
623 if (cornerRadius == null || cornerRadius.equals(EMPTY_STR))
624 {
625 f = new FigRect(0, 0, 80, 80);
626 }
627 else
628 {
629 f = new FigRRect(0, 0, 80, 80);
630 int rInt = Integer.parseInt(cornerRadius);
631 ((FigRRect) f).setCornerRadius(rInt);
632 }
633 setAttrs(f, attrs);
634 return f;
635 }
636
637 protected FigText handleText(Attributes attrs)
638 {
639 FigText f = new FigText(100, 100, 90, 45);
640 setAttrs(f, attrs);
641
642 _elementState = TEXT_STATE;
643 _textBuf = new StringBuffer();
644 _currentText = f;
645
646 String style = attrs.getValue(FIG_STYLE_ATTR_STR);
647 if (style != null)
648 {
649 String font = parseStyle(STYLE_FONT_STR, style);
650 if (font != null)
651 {
652 f.setFontFamily(font);
653 }
654 String size = parseStyle(STYLE_FONT_SIZE_STR, style);
655 if (size != null)
656 {
657 int s = Integer.parseInt( size );
658 f.setFontSize( s );
659 }
660 }
661 return f;
662 }
663
664
665 ////////////////////////////////////////////////////////////////
666 // Internal methods
667
668 private void nodeStateStartElement(String tagName, Attributes attrs)
669 {
670 if (tagName.equals(FIG_DESC_ATTR_STR))
671 {
672 }
673 else if (tagName.equals(FIG_TITLE_ATTR_STR))
674 {
675 }
676 else if (tagName.equals(FIG_SWITCH_ATTR_STR))
677 {
678 _textBuf = new StringBuffer();
679 _elementState = PRIVATE_NODE_STATE;
680 }
681 else if (tagName.equals(FIG_TEXT_ATTR_STR))
682 {
683 _textBuf = new StringBuffer();
684 _elementState = TEXT_NODE_STATE;
685 Fig p = handleText(attrs);
686 }
687 }
688
689 private void edgeStateStartElement(String tagName, Attributes attrs)
690 {
691 if (tagName.equals(FIG_DESC_ATTR_STR))
692 {
693 }
694 else if (tagName.equals(FIG_TITLE_ATTR_STR))
695 {
696 }
697 else if (tagName.equals(FIG_PATH_ATTR_STR))
698 {
699 Fig p = handlePath(attrs);
700 _currentEdge.setFig(p);
701 ((FigPoly) p)._isComplete = true;
702 _currentEdge.calcBounds();
703 if (_currentEdge instanceof FigEdgePoly)
704 {
705 ((FigEdgePoly) _currentEdge).setInitiallyLaidOut(true);
706 }
707 }
708 else if (tagName.equals(FIG_SWITCH_ATTR_STR))
709 {
710 _elementState = PRIVATE_EDGE_STATE;
711 _textBuf = new StringBuffer();
712 }
713 else if (tagName.equals(FIG_TEXT_ATTR_STR))
714 {
715 _elementState = TEXT_EDGE_STATE;
716 _textBuf = new StringBuffer();
717 Fig p = handleText(attrs);
718 }
719 }
720
721 protected void lineStateStartElement(String tagName, Attributes attrs)
722 {
723 dumpAttributes(attrs);
724 if (_currentLine != null)
725 {
726 if (tagName.equals(FIG_DESC_ATTR_STR))
727 {
728 }
729 else if (tagName.equals(FIG_TITLE_ATTR_STR))
730 {
731 }
732 else if (tagName.equals(FIG_MOVETO_ATTR_STR))
733 {
734 String x1 = attrs.getValue(FIG_X_ATTR_STR);
735 String y1 = attrs.getValue(FIG_Y_ATTR_STR);
736 _x1Int = (x1 == null || x1.equals(EMPTY_STR)) ? 0 : Integer.parseInt(x1);
737 _y1Int = (y1 == null || y1.equals(EMPTY_STR)) ? 0 : Integer.parseInt(y1);
738 _currentLine.setX1(_x1Int);
739 _currentLine.setY1(_y1Int);
740 }
741 else if (tagName.equals(FIG_LINETO_ATTR_STR))
742 {
743 String x2 = attrs.getValue(FIG_X_ATTR_STR);
744 String y2 = attrs.getValue(FIG_Y_ATTR_STR);
745 int x2Int = (x2 == null || x2.equals(EMPTY_STR)) ? _x1Int : Integer.parseInt(x2);
746 int y2Int = (y2 == null || y2.equals(EMPTY_STR)) ? _y1Int : Integer.parseInt(y2);
747 _currentLine.setX2(x2Int);
748 _currentLine.setY2(y2Int);
749 }
750 }
751 }
752
753 private void polyStateStartElement(String tagName, Attributes attrs)
754 {
755 if (_currentPoly != null)
756 {
757 if (tagName.equals(FIG_DESC_ATTR_STR))
758 {
759 }
760 else if (tagName.equals(FIG_TITLE_ATTR_STR))
761 {
762 }
763 else if (tagName.equals(FIG_MOVETO_ATTR_STR))
764 {
765 String x1 = attrs.getValue(FIG_X_ATTR_STR);
766 String y1 = attrs.getValue(FIG_Y_ATTR_STR);
767 _x1Int = (x1 == null || x1.equals(EMPTY_STR)) ? 0 : Integer.parseInt(x1);
768 _y1Int = (y1 == null || y1.equals(EMPTY_STR)) ? 0 : Integer.parseInt(y1);
769 _currentPoly.addPoint(_x1Int, _y1Int);
770 }
771 else if (tagName.equals(FIG_LINETO_ATTR_STR))
772 {
773 String x2 = attrs.getValue(FIG_X_ATTR_STR);
774 String y2 = attrs.getValue(FIG_Y_ATTR_STR);
775 int x2Int = (x2 == null || x2.equals(EMPTY_STR)) ? _x1Int : Integer.parseInt(x2);
776 int y2Int = (y2 == null || y2.equals(EMPTY_STR)) ? _y1Int : Integer.parseInt(y2);
777 _currentPoly.addPoint(x2Int, y2Int);
778 }
779 }
780 }
781
782 private void privateStateEndElement(String tagName)
783 {
784 String body = _textBuf.toString();
785
786 if (_currentNode != null)
787 {
788 if ( _currentEdge != null )
789 {
790 _currentEdge = null;
791 }
792
793 _currentNode.setPrivateData(body);
794
795 Fig encloser = null;
796 StringTokenizer st2 = new StringTokenizer(body, PRIVATE_DATA_TOKENIZER_STR);
797 while (st2.hasMoreElements())
798 {
799 String t = st2.nextToken();
800 String v = EMPTY_STR;
801 if (st2.hasMoreElements())
802 {
803 v = st2.nextToken();
804 }
805
806 if (t.equals(PRIVATE_DATA_ENC_FIG_STR))
807 {
808 encloser = findFig(v);
809 }
810 else if (t.equals(PRIVATE_DATA_TEXT_STR))
811 {
812 //do nothing
813 }
814 }
815 _currentNode.setEnclosingFig(encloser);
816 }
817
818 if (_currentEdge != null)
819 {
820 _currentEdge.setPrivateData(body);
821
822 Fig spf = null;
823 Fig dpf = null;
824 FigNode sfn = null;
825 FigNode dfn = null;
826
827 StringTokenizer st2 = new StringTokenizer(body, PRIVATE_DATA_TOKENIZER_STR);
828 while (st2.hasMoreElements())
829 {
830 String t = st2.nextToken();
831 String v = st2.nextToken();
832 if (t.equals(PRIVATE_DATA_SRCPORT_STR))
833 {
834 spf = findFig(v);
835 }
836 if (t.equals(PRIVATE_DATA_DESTPORT_STR))
837 {
838 dpf = findFig(v);
839 }
840 if (t.equals(PRIVATE_DATA_SRCNODE_STR))
841 {
842 sfn = (FigNode) findFig(v);
843 }
844 if (t.equals(PRIVATE_DATA_DESTNODE_STR))
845 {
846 dfn = (FigNode) findFig(v);
847 }
848 }
849
850 _currentEdge.setSourcePortFig(spf);
851 _currentEdge.setDestPortFig(dpf);
852 _currentEdge.setSourceFigNode(sfn);
853 _currentEdge.setDestFigNode(dfn);
854 }
855 }
856
857
858 //////////////////////////////////////////////////////////
859 // Utility operations
860
861 protected void setAttrs(Fig f, Attributes attrs)
862 {
863 //dumpAttributes(attrs);
864
865 String name = attrs.getValue(FIG_NAME_ATTR_STR);
866 if (name != null && !name.equals(EMPTY_STR))
867 {
868 _figRegistry.put(name, f);
869 }
870
871 String x = attrs.getValue(FIG_X_ATTR_STR);
872 if (x != null && !x.equals(EMPTY_STR))
873 {
874 String y = attrs.getValue(FIG_Y_ATTR_STR);
875 String w = attrs.getValue(FIG_WIDTH_ATTR_STR);
876 String h = attrs.getValue(FIG_HEIGHT_ATTR_STR);
877 int xInt = Integer.parseInt(x);
878 int yInt = (y == null || y.equals(EMPTY_STR)) ? 0 : Integer.parseInt(y);
879 int wInt = (w == null || w.equals(EMPTY_STR)) ? 20 : Integer.parseInt(w);
880 int hInt = (h == null || h.equals(EMPTY_STR)) ? 20 : Integer.parseInt(h);
881 f.setBounds(xInt, yInt, wInt, hInt);
882 }
883
884 // Parse Style
885 String style = attrs.getValue(FIG_STYLE_ATTR_STR);
886 if (style != null)
887 {
888 String fillcolor = parseStyle(STYLE_FILL_STR, style);
889 if (fillcolor != null && !fillcolor.equals(EMPTY_STR))
890 {
891 f.setFillColor( parseColor(fillcolor, Color.blue ) );
892 }
893
894 if (!(f instanceof FigNode))
895 {
896 String linewidth = parseStyle(STYLE_STROKE_WIDTH_STR, style);
897 if (linewidth != null && !linewidth.equals(EMPTY_STR))
898 {
899 f.setLineWidth(Integer.parseInt(linewidth));
900 }
901 String strokecolor = parseStyle(STYLE_STROKE_STR, style);
902 if (strokecolor != null && !strokecolor.equals(EMPTY_STR))
903 {
904 f.setLineColor( parseColor(strokecolor, Color.blue ) );
905 }
906
907 String dasharray = parseStyle(STYLE_STROKE_DASH_ARRAY_STR, style);
908 if (dasharray != null && !dasharray.equals(EMPTY_STR) && !dasharray.equals(SET_VALUE_STR))
909 {
910 f.setDashed(true);
911 }
912 }
913 }
914
915 String dynobjs = attrs.getValue(FIG_DYNOBJ_ATTR_STR);
916 if (dynobjs != null && dynobjs.length() != 0 && f instanceof FigGroup)
917 {
918 FigGroup fg = (FigGroup) f;
919 fg.parseDynObjects(dynobjs);
920 }
921
922 setOwnerAttr(f, attrs);
923 }
924
925 protected void setOwnerAttr(Fig f, Attributes attrs)
926 {
927 try
928 {
929 String owner = attrs.getValue(FIG_OWNER_HREF_ATTR_STR);
930 if (owner != null && !owner.equals(EMPTY_STR))
931 {
932 f.setOwner(findOwner(owner));
933 }
934 }
935 catch (Exception e)
936 {
937 e.printStackTrace();
938 System.out.println("Could not set owner");
939 }
940 }
941
942 protected Fig findFig(String uri)
943 {
944 Fig f = null;
945 if (uri.indexOf(DOT_STR) == -1)
946 {
947 f = (Fig) _figRegistry.get(uri);
948 }
949 else
950 {
951 StringTokenizer st = new StringTokenizer(uri, DOT_STR);
952 String figNum = st.nextToken();
953 f = (Fig) _figRegistry.get(figNum);
954 if (f instanceof FigEdge)
955 {
956 return ((FigEdge) f).getFig();
957 }
958
959 while (st.hasMoreElements())
960 {
961 if (f instanceof FigGroup)
962 {
963 String subIndex = st.nextToken();
964 int i = Integer.parseInt(subIndex);
965 f = (Fig)((FigGroup) f).getFigs().elementAt(i);
966 }
967 }
968 }
969 return f;
970 }
971
972 protected Object findOwner(String uri)
973 {
974 Object own = _ownerRegistry.get(uri);
975 return own;
976 }
977
978 /***
979 * Translate a given class name into another???
980 */
981 protected String translateClassName(String oldName)
982 {
983 return oldName;
984 }
985
986 protected Color parseColor(String name, Color defaultColor)
987 {
988 try
989 {
990 int start = name.indexOf(RGB_STR, 0);
991 if (start != -1)
992 {
993 start = name.indexOf(OPAREN_STR, start);
994 int end = name.indexOf(COMMA_STR, start);
995 if (start != -1)
996 {
997 start++;
998 int red = Integer.parseInt(name.substring( start, end ).trim());
999 start = end + 1;
1000 end = name.indexOf(COMMA_STR, start);
1001 int green = Integer.parseInt(name.substring( start, end ).trim());
1002 start = end + 1;
1003 end = name.indexOf(CPAREN_STR, start);
1004 int blue = Integer.parseInt(name.substring( start, end ).trim());
1005 return new Color(red, green, blue);
1006 }
1007 return defaultColor;
1008 }
1009 }
1010 catch (Exception ex)
1011 {
1012 System.out.println("Invalid rgb() sequence: " + name);
1013 return defaultColor;
1014 }
1015
1016 return colorByName(name, defaultColor);
1017 }
1018
1019 protected Color colorByName(String name, Color defaultColor)
1020 {
1021 if (name.equalsIgnoreCase(NONE_STR)) return null;
1022 if (name.equalsIgnoreCase(WHITE_STR)) return Color.white;
1023 if (name.equalsIgnoreCase(LIGHTGRAY_STR)) return Color.lightGray;
1024 if (name.equalsIgnoreCase(GRAY_STR)) return Color.gray;
1025 if (name.equalsIgnoreCase(DARKGRAY_STR)) return Color.darkGray;
1026 if (name.equalsIgnoreCase(BLACK_STR)) return Color.black;
1027 if (name.equalsIgnoreCase(RED_STR)) return Color.red;
1028 if (name.equalsIgnoreCase(PINK_STR)) return Color.pink;
1029 if (name.equalsIgnoreCase(ORANGE_STR)) return Color.orange;
1030 if (name.equalsIgnoreCase(YELLOW_STR)) return Color.yellow;
1031 if (name.equalsIgnoreCase(GREEN_STR)) return Color.green;
1032 if (name.equalsIgnoreCase(MAGENTA_STR)) return Color.magenta;
1033 if (name.equalsIgnoreCase(CYAN_STR)) return Color.cyan;
1034 if (name.equalsIgnoreCase(BLUE_STR)) return Color.blue;
1035 try
1036 {
1037 return Color.decode(name);
1038 }
1039 catch (Exception e)
1040 {
1041 System.out.println("Invalid color code string: " + name);
1042 }
1043 return defaultColor;
1044 }
1045
1046 /***
1047 * This method parses the 'style' attribute for a particular field
1048 * @return java.lang.String
1049 * @param field java.lang.String
1050 * @param style java.lang.String
1051 */
1052 protected String parseStyle(String field, String style)
1053 {
1054 field += COLON_STR;
1055 int start = style.indexOf(field, 0);
1056 if ( start != -1 )
1057 {
1058 int end = style.indexOf(SEMICOLON_STR, start);
1059 if ( end != -1 )
1060 {
1061 return style.substring( start + field.length(), end ).trim();
1062 }
1063 else
1064 {
1065 return style.substring( start + field.length(), style.length() - 1 ).trim();
1066 }
1067 }
1068 return null;
1069 }
1070
1071 private void dumpAttributes(Attributes attrs)
1072 {
1073 int num = attrs.getLength();
1074 for (int i = 0; i < num; i++)
1075 {
1076 System.err.println("attr: lname = " + attrs.getLocalName(i) +
1077 "; qname = " + attrs.getQName(i) +
1078 "; type = " + attrs.getType(i) +
1079 "; uri = " + attrs.getURI(i) +
1080 "; value = " + attrs.getValue(i)
1081 );
1082 }
1083 }
1084
1085 //////////////////////////////////////////////////////////
1086 // Useful Parsing Constants
1087 private static final String EMPTY_STR = "";
1088 private static final String PIPE_STR = "|";
1089 private static final String DOT_STR = ".";
1090 private static final String COLON_STR = ":";
1091 private static final String SEMICOLON_STR = ";";
1092 private static final String COMMA_STR = ",";
1093 private static final String OPAREN_STR = "(";
1094 private static final String CPAREN_STR = ")";
1095 private static final String RGB_STR = "rgb";
1096 private static final String GROUP_TOKENIZER_STR = ",;[] ";
1097 private static final String PRIVATE_DATA_TOKENIZER_STR = "=\"' \t\n";
1098 private static final String PRIVATE_DATA_ENC_FIG_STR = "enclosingFig";
1099 private static final String PRIVATE_DATA_TEXT_STR = "text";
1100 private static final String PRIVATE_DATA_SRCPORT_STR = "sourcePortFig";
1101 private static final String PRIVATE_DATA_DESTPORT_STR = "destPortFig";
1102 private static final String PRIVATE_DATA_SRCNODE_STR = "sourceFigNode";
1103 private static final String PRIVATE_DATA_DESTNODE_STR = "destFigNode";
1104
1105 private static final String ELEMENT_SVG_STR = "svg";
1106 private static final String ELEMENT_PATH_STR = "path";
1107 private static final String ELEMENT_ELLIPSE_STR = "ellipse";
1108 private static final String ELEMENT_RECT_STR = "rect";
1109 private static final String ELEMENT_TEXT_STR = "text";
1110 private static final String ELEMENT_LINE_STR = "line";
1111 private static final String ELEMENT_GROUP_STR = "g";
1112
1113 private static final String FIG_NAME_ATTR_STR = "id";
1114 private static final String FIG_CLASS_ATTR_STR = "class";
1115 private static final String FIG_DESC_ATTR_STR = "desc";
1116 private static final String FIG_TITLE_ATTR_STR = "title";
1117 private static final String FIG_SWITCH_ATTR_STR = "switch";
1118 private static final String FIG_TEXT_ATTR_STR = "text";
1119 private static final String FIG_PATH_ATTR_STR = "path";
1120 private static final String FIG_MOVETO_ATTR_STR = "moveto";
1121 private static final String FIG_LINETO_ATTR_STR = "lineto";
1122 private static final String FIG_OWNER_HREF_ATTR_STR = "gef:href";
1123 private static final String FIG_X_ATTR_STR = "x";
1124 private static final String FIG_Y_ATTR_STR = "y";
1125 private static final String FIG_X1_ATTR_STR = "x1";
1126 private static final String FIG_Y1_ATTR_STR = "y1";
1127 private static final String FIG_X2_ATTR_STR = "x2";
1128 private static final String FIG_Y2_ATTR_STR = "y2";
1129 private static final String FIG_WIDTH_ATTR_STR = "width";
1130 private static final String FIG_HEIGHT_ATTR_STR = "height";
1131 private static final String FIG_STYLE_ATTR_STR = "style";
1132 private static final String FIG_DYNOBJ_ATTR_STR = "dynobjects";
1133 private static final String FIG_CENTER_X_ATTR_STR = "cx";
1134 private static final String FIG_CENTER_Y_ATTR_STR = "cy";
1135 private static final String FIG_RADIUS_X_ATTR_STR = "rx";
1136 private static final String FIG_RADIUS_Y_ATTR_STR = "ry";
1137 private static final String FIG_PATH_DATA_ATTR_STR = "d";
1138 private static final String FIG_PATH_DESC_ATTR_STR = "description";
1139
1140 private static final String STYLE_FILL_STR = "fill";
1141 private static final String STYLE_FONT_STR = "font";
1142 private static final String STYLE_FONT_SIZE_STR = "font-size";
1143 private static final String STYLE_STROKE_STR = "stroke";
1144 private static final String STYLE_STROKE_WIDTH_STR = "stroke-width";
1145 private static final String STYLE_STROKE_DASH_ARRAY_STR = "stroke-dash-array";
1146 private static final String SET_VALUE_STR = "1";
1147 private static final String FIG_LINE_STR = "FigLine";
1148
1149 private static final String NONE_STR = "none";
1150 private static final String WHITE_STR = "white";
1151 private static final String LIGHTGRAY_STR = "lightGray";
1152 private static final String GRAY_STR = "gray";
1153 private static final String DARKGRAY_STR = "darkGray";
1154 private static final String BLACK_STR = "black";
1155 private static final String RED_STR = "red";
1156 private static final String PINK_STR = "pink";
1157 private static final String ORANGE_STR = "orange";
1158 private static final String YELLOW_STR = "yellow";
1159 private static final String GREEN_STR = "green";
1160 private static final String MAGENTA_STR = "magenta";
1161 private static final String CYAN_STR = "cyan";
1162 private static final String BLUE_STR = "blue";
1163
1164 } /* end class SVGReader */
This page was automatically generated by Maven