updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / file / simplesax / DelegatorHandler.java
diff --git a/src/net/sf/openrocket/file/simplesax/DelegatorHandler.java b/src/net/sf/openrocket/file/simplesax/DelegatorHandler.java
new file mode 100644 (file)
index 0000000..b5403b5
--- /dev/null
@@ -0,0 +1,122 @@
+package net.sf.openrocket.file.simplesax;
+
+import java.util.HashMap;
+import java.util.Stack;
+
+import net.sf.openrocket.aerodynamics.Warning;
+import net.sf.openrocket.aerodynamics.WarningSet;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * The actual handler class.  Contains the necessary methods for parsing the SAX source.
+ * Delegates the actual content parsing to {@link ElementHandler} objects.
+ */
+class DelegatorHandler extends DefaultHandler {
+       private final WarningSet warnings;
+
+       private final Stack<ElementHandler> handlerStack = new Stack<ElementHandler>();
+       private final Stack<StringBuilder> elementData = new Stack<StringBuilder>();
+       private final Stack<HashMap<String, String>> elementAttributes = 
+               new Stack<HashMap<String, String>>();
+
+
+       // Ignore all elements as long as ignore > 0
+       private int ignore = 0;
+
+
+       public DelegatorHandler(ElementHandler initialHandler, WarningSet warnings) {
+               this.warnings = warnings;
+               handlerStack.add(initialHandler);
+               elementData.add(new StringBuilder()); // Just in case
+       }
+
+
+       /////////  SAX handlers
+
+       @Override
+       public void startElement(String uri, String localName, String name,
+                       Attributes attributes) throws SAXException {
+
+               // Check for ignore
+               if (ignore > 0) {
+                       ignore++;
+                       return;
+               }
+
+               // Check for unknown namespace
+               if (!uri.equals("")) {
+                       warnings.add(Warning.fromString("Unknown namespace element '" + uri
+                                       + "' encountered, ignoring."));
+                       ignore++;
+                       return;
+               }
+
+               // Add layer to data stacks
+               elementData.push(new StringBuilder());
+               elementAttributes.push(copyAttributes(attributes));
+
+               // Call the handler
+               ElementHandler h = handlerStack.peek();
+               h = h.openElement(localName, elementAttributes.peek(), warnings);
+               if (h != null) {
+                       handlerStack.push(h);
+               } else {
+                       // Start ignoring elements
+                       ignore++;
+               }
+       }
+
+
+       /**
+        * Stores encountered characters in the elementData stack.
+        */
+       @Override
+       public void characters(char[] chars, int start, int length) throws SAXException {
+               // Check for ignore
+               if (ignore > 0)
+                       return;
+
+               StringBuilder sb = elementData.peek();
+               sb.append(chars, start, length);
+       }
+
+
+       /**
+        * Removes the last layer from the stack.
+        */
+       @Override
+       public void endElement(String uri, String localName, String name) throws SAXException {
+
+               // Check for ignore
+               if (ignore > 0) {
+                       ignore--;
+                       return;
+               }
+
+               // Remove data from stack
+               String data = elementData.pop().toString(); // throws on error
+               HashMap<String, String> attr = elementAttributes.pop();
+
+               // Remove last handler and call the next one
+               ElementHandler h;
+               
+               h = handlerStack.pop();
+               h.endHandler(localName, attr, data, warnings);
+               
+               h = handlerStack.peek();
+               h.closeElement(localName, attr, data, warnings);
+       }
+
+
+       private static HashMap<String, String> copyAttributes(Attributes atts) {
+               HashMap<String, String> ret = new HashMap<String, String>();
+               for (int i = 0; i < atts.getLength(); i++) {
+                       ret.put(atts.getLocalName(i), atts.getValue(i));
+               }
+               return ret;
+       }
+}
+