package net.sf.openrocket.file.simplesax;
import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.util.SimpleStack;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* The actual SAX 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 SimpleStack<ElementHandler> handlerStack = new SimpleStack<ElementHandler>();
private final SimpleStack<StringBuilder> elementData = new SimpleStack<StringBuilder>();
private final SimpleStack<HashMap<String, String>> elementAttributes = new SimpleStack<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;
}
}