package org.exolab.castor.xml.parsing; import org.exolab.castor.types.AnyNode; import org.exolab.castor.xml.util.SAX2ANY; import org.xml.sax.AttributeList; import org.xml.sax.Attributes; import org.xml.sax.SAXException; public class AnyNodeUnmarshalHandler { private NamespaceHandling _namespaceHandling; /** * A SAX2ANY unmarshaller in case we are dealing with {@literal <any>}. */ private SAX2ANY _anyUnmarshaller = null; /** * The any branch depth. */ private int _depth = 0; /** * Keeps track of the current element information as passed by the parser. */ private ElementInfo _elemInfo = null; public AnyNodeUnmarshalHandler(NamespaceHandling namespaceHandling) { _namespaceHandling = namespaceHandling; } /** * Delegates startElement to SAX2ANY. Sets any branch depth counter to 1. * * @param name * Name of the element if we use SAX 2 * @param namespace * Namespace of the element * @param wsPreserve * preserve whitespaces ? * @return Object anyUnmarshaller get StartingNode * @throws SAXException */ public Object commonStartElement(String name, String namespace, boolean wsPreserve) throws SAXException { // 1- creates a new SAX2ANY handler _anyUnmarshaller = new SAX2ANY(_namespaceHandling.getNamespaceContext(), wsPreserve); // 2- delegates the element handling if (_elemInfo._attributeList != null) { // -- SAX 1 startElement(_elemInfo._qName, _elemInfo._attributeList); } else { // -- SAX 2 startElement(namespace, name, _elemInfo._qName, _elemInfo._attributes); } // first element so depth can only be one at this point _depth = 1; return _anyUnmarshaller.getStartingNode(); } /** * delegates ignorableWhitespace call to SAX2ANY. * * @param ch * Characters * @param start * Offset * @param length * Length * @throws SAXException */ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { _anyUnmarshaller.ignorableWhitespace(ch, start, length); } /** * Delegates SAX1 startElement to SAX2ANY. Increases any branch depth * counter. * * @param name Name of the element. * @param attList Attribute list. * @throws SAXException */ public void startElement(String name, AttributeList attList) throws SAXException { _depth++; _anyUnmarshaller.startElement(name, attList); return; } /** * Delegates SAX2 startElement to SAX2ANY. Increases any branch depth * counter. * * @param namespaceURI * @param localName * @param qName * @param atts * @throws SAXException */ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { _depth++; _anyUnmarshaller.startElement(namespaceURI, localName, qName, atts); return; } /** * Delegates endElement to SAX2ANY. * * @param name * @throws SAXException */ public void endElement(String name) throws SAXException { _anyUnmarshaller.endElement(name); _depth--; } /** * delegates characters to SAX2ANY. * * @param ch * @param start * @param length * @throws SAXException */ public void characters(char[] ch, int start, int length) throws SAXException { _anyUnmarshaller.characters(ch, start, length); } /** * delegates startPrefixMapping to SAX2ANY. * * @param prefix * @param uri * @throws SAXException */ public void startPrefixMapping(String prefix, String uri) throws SAXException { _anyUnmarshaller.startPrefixMapping(prefix, uri); } /** * delegates endPrefixMapping to SAX2ANY. * * @param prefix * @throws SAXException */ public void endPrefixMapping(String prefix) throws SAXException { _anyUnmarshaller.endPrefixMapping(prefix); } /** * Checks if there is a SAX2ANY object * * @return True if there is a SAX2ANY. */ public boolean hasAnyUnmarshaller() { return _anyUnmarshaller != null; } /** * Checks if any branch depth counter is zero. * * @return true if 0 */ public boolean isStartingNode() { return _depth == 0; } /** * Returns SAX2ANY startingNode. * * @return */ public AnyNode getStartingNode() { AnyNode startingNode = _anyUnmarshaller.getStartingNode(); _anyUnmarshaller = null; return startingNode; } /** * Preserves passed name and attributes. * * @param name * Name * @param atts * Attributes */ public void preservePassedArguments(String name, Attributes atts) { _elemInfo = setElementInfo(_elemInfo, name, atts); } /** * Preserves passed name and attributes. * * @param name * Name * @param attList * AttributeList */ public void preservePassedArguments(String name, AttributeList attList) { _elemInfo = setElementInfo(_elemInfo, name, attList); } /** * Sets name and attList on element * * @param element * ElementInfo, can be null * @param name * Name * @param attList * Attributes * @return element on which name and attList are set */ private ElementInfo setElementInfo(ElementInfo element, String name, AttributeList attList) { if (element == null) { return new ElementInfo(name, attList); } element.clear(); element._qName = name; element._attributeList = attList; return element; } /** * Sets name and attributes on element * * @param element * ElementInfo, can be null * @param name * Name * @param attributes * Attributes * @return element on which name and attributes are set */ private ElementInfo setElementInfo(ElementInfo element, String name, Attributes attributes) { if (element == null) { return new ElementInfo(name, attributes); } element.clear(); element._qName = name; element._attributes = attributes; return element; } /** * A utility class for keeping track of the qName and how the SAX parser * passed attributes. */ class ElementInfo { String _qName = null; Attributes _attributes = null; AttributeList _attributeList = null; ElementInfo() { super(); } ElementInfo(String qName, Attributes atts) { super(); _qName = qName; _attributes = atts; } ElementInfo(String qName, AttributeList atts) { super(); _qName = qName; _attributeList = atts; } void clear() { _qName = null; _attributes = null; _attributeList = null; } } // -- ElementInfo }