b5403b521d8feed037b22bdb5c3117730dcc0c31
[debian/openrocket] / src / net / sf / openrocket / file / simplesax / DelegatorHandler.java
1 package net.sf.openrocket.file.simplesax;
2
3 import java.util.HashMap;
4 import java.util.Stack;
5
6 import net.sf.openrocket.aerodynamics.Warning;
7 import net.sf.openrocket.aerodynamics.WarningSet;
8
9 import org.xml.sax.Attributes;
10 import org.xml.sax.SAXException;
11 import org.xml.sax.helpers.DefaultHandler;
12
13 /**
14  * The actual handler class.  Contains the necessary methods for parsing the SAX source.
15  * Delegates the actual content parsing to {@link ElementHandler} objects.
16  */
17 class DelegatorHandler extends DefaultHandler {
18         private final WarningSet warnings;
19
20         private final Stack<ElementHandler> handlerStack = new Stack<ElementHandler>();
21         private final Stack<StringBuilder> elementData = new Stack<StringBuilder>();
22         private final Stack<HashMap<String, String>> elementAttributes = 
23                 new Stack<HashMap<String, String>>();
24
25
26         // Ignore all elements as long as ignore > 0
27         private int ignore = 0;
28
29
30         public DelegatorHandler(ElementHandler initialHandler, WarningSet warnings) {
31                 this.warnings = warnings;
32                 handlerStack.add(initialHandler);
33                 elementData.add(new StringBuilder()); // Just in case
34         }
35
36
37         /////////  SAX handlers
38
39         @Override
40         public void startElement(String uri, String localName, String name,
41                         Attributes attributes) throws SAXException {
42
43                 // Check for ignore
44                 if (ignore > 0) {
45                         ignore++;
46                         return;
47                 }
48
49                 // Check for unknown namespace
50                 if (!uri.equals("")) {
51                         warnings.add(Warning.fromString("Unknown namespace element '" + uri
52                                         + "' encountered, ignoring."));
53                         ignore++;
54                         return;
55                 }
56
57                 // Add layer to data stacks
58                 elementData.push(new StringBuilder());
59                 elementAttributes.push(copyAttributes(attributes));
60
61                 // Call the handler
62                 ElementHandler h = handlerStack.peek();
63                 h = h.openElement(localName, elementAttributes.peek(), warnings);
64                 if (h != null) {
65                         handlerStack.push(h);
66                 } else {
67                         // Start ignoring elements
68                         ignore++;
69                 }
70         }
71
72
73         /**
74          * Stores encountered characters in the elementData stack.
75          */
76         @Override
77         public void characters(char[] chars, int start, int length) throws SAXException {
78                 // Check for ignore
79                 if (ignore > 0)
80                         return;
81
82                 StringBuilder sb = elementData.peek();
83                 sb.append(chars, start, length);
84         }
85
86
87         /**
88          * Removes the last layer from the stack.
89          */
90         @Override
91         public void endElement(String uri, String localName, String name) throws SAXException {
92
93                 // Check for ignore
94                 if (ignore > 0) {
95                         ignore--;
96                         return;
97                 }
98
99                 // Remove data from stack
100                 String data = elementData.pop().toString(); // throws on error
101                 HashMap<String, String> attr = elementAttributes.pop();
102
103                 // Remove last handler and call the next one
104                 ElementHandler h;
105                 
106                 h = handlerStack.pop();
107                 h.endHandler(localName, attr, data, warnings);
108                 
109                 h = handlerStack.peek();
110                 h.closeElement(localName, attr, data, warnings);
111         }
112
113
114         private static HashMap<String, String> copyAttributes(Attributes atts) {
115                 HashMap<String, String> ret = new HashMap<String, String>();
116                 for (int i = 0; i < atts.getLength(); i++) {
117                         ret.put(atts.getLocalName(i), atts.getValue(i));
118                 }
119                 return ret;
120         }
121 }
122