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