Abstract unmarshaller minus signatures.
authorcantor <cantor@de75baf8-a10c-0410-a50a-987c0e22f00f>
Tue, 21 Feb 2006 19:45:58 +0000 (19:45 +0000)
committercantor <cantor@de75baf8-a10c-0410-a50a-987c0e22f00f>
Tue, 21 Feb 2006 19:45:58 +0000 (19:45 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/trunk@21 de75baf8-a10c-0410-a50a-987c0e22f00f

xmltooling/io/AbstractXMLObjectUnmarshaller.cpp [new file with mode: 0644]
xmltooling/io/AbstractXMLObjectUnmarshaller.h
xmltooling/io/Marshaller.cpp [new file with mode: 0644]
xmltooling/io/Marshaller.h
xmltooling/io/Unmarshaller.cpp [new file with mode: 0644]
xmltooling/io/Unmarshaller.h

diff --git a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp
new file mode 100644 (file)
index 0000000..9aefabc
--- /dev/null
@@ -0,0 +1,221 @@
+/*\r
+*  Copyright 2001-2006 Internet2\r
+ * \r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * AbstractXMLObjectUnmarshaller.cpp\r
+ * \r
+ * A thread-safe abstract unmarshaller.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "DOMCachingXMLObject.h"\r
+#include "exceptions.h"\r
+#include "XMLObjectBuilder.h"\r
+#include "io/AbstractXMLObjectUnmarshaller.h"\r
+#include "util/NDC.h"\r
+#include "util/XMLConstants.h"\r
+#include "util/XMLHelper.h"\r
+\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <log4cpp/Category.hh>\r
+\r
+using namespace xmltooling;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+#define XT_log (*static_cast<Category*>(m_log))\r
+\r
+AbstractXMLObjectUnmarshaller::AbstractXMLObjectUnmarshaller(const XMLCh* targetNamespaceURI, const XMLCh* targetLocalName)\r
+        : m_targetQName(targetNamespaceURI, targetLocalName),\r
+        m_log(&Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller")) {\r
+    if (!targetLocalName || !*targetLocalName)\r
+        throw UnmarshallingException("targetLocalName cannot be null or empty");\r
+}\r
+\r
+XMLObject* AbstractXMLObjectUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) const\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("unmarshall");\r
+#endif\r
+\r
+    if (XT_log.isDebugEnabled()) {\r
+        auto_ptr_char dname(element->getLocalName());\r
+        XT_log.debug("unmarshalling DOM element %s", dname.get());\r
+    }\r
+\r
+#ifdef _DEBUG\r
+    checkElementIsTarget(element);\r
+#endif\r
+\r
+    XMLObject* xmlObject = buildXMLObject(element);\r
+\r
+    if (element->hasAttributes()) {\r
+        unmarshallAttributes(element, xmlObject);\r
+    }\r
+\r
+    if (element->getTextContent()) {\r
+        processElementContent(xmlObject, element->getTextContent());\r
+    }\r
+\r
+    unmarshallChildElements(element, xmlObject);\r
+\r
+    /* TODO: Signing\r
+    if (xmlObject instanceof SignableXMLObject) {\r
+        verifySignature(domElement, xmlObject);\r
+    }\r
+    */\r
+\r
+    DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(xmlObject);\r
+    if (dc)\r
+        dc->setDOM(element,bindDocument);\r
+        \r
+    return xmlObject;\r
+}\r
+\r
+void AbstractXMLObjectUnmarshaller::checkElementIsTarget(const DOMElement* domElement) const\r
+{\r
+    auto_ptr<QName> elementName(XMLHelper::getNodeQName(domElement));\r
+\r
+    XT_log.debug("checking that root element meets target criteria");\r
+\r
+    auto_ptr<QName> type(XMLHelper::getXSIType(domElement));\r
+\r
+    if (type.get() && m_targetQName==*(type.get())) {\r
+        XT_log.debug("schema type of element matches target");\r
+        return;\r
+    }\r
+    else {\r
+        if (m_targetQName==*(elementName.get())) {\r
+            XT_log.debug("element name matches target");\r
+            return;\r
+        }\r
+        else {\r
+            XT_log.errorStream() << "unmarshaller for (" << m_targetQName.toString()\r
+                << ") passed (" << elementName->toString() << ")" << CategoryStream::ENDLINE;\r
+            throw UnmarshallingException("Incorrect element type passed to unmarshaller.");\r
+        }\r
+    }\r
+}\r
+\r
+XMLObject* AbstractXMLObjectUnmarshaller::buildXMLObject(const DOMElement* domElement) const\r
+{\r
+    const XMLObjectBuilder* xmlObjectBuilder = XMLObjectBuilder::getBuilder(domElement);\r
+    if (xmlObjectBuilder)\r
+        return xmlObjectBuilder->buildObject();\r
+    throw UnmarshallingException("Failed to locate XMLObjectBuilder for element.");\r
+}\r
+\r
+void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domElement, XMLObject* xmlObject) const\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("unmarshallAttributes");\r
+#endif\r
+    static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull};\r
+\r
+    if (XT_log.isDebugEnabled()) {\r
+        auto_ptr_char dname(domElement->getLocalName());\r
+        XT_log.debug("unmarshalling attributes for DOM element %s", dname.get());\r
+    }\r
+\r
+    DOMNamedNodeMap* attributes = domElement->getAttributes();\r
+    if (!attributes) {\r
+        XT_log.debug("no attributes to unmarshall");\r
+        return;\r
+    }\r
+\r
+    DOMNode* childNode;\r
+    DOMAttr* attribute;\r
+    for (XMLSize_t i=0; i<attributes->getLength(); i++) {\r
+        childNode = attributes->item(i);\r
+\r
+        // The child node should always be an attribute, but just in case\r
+        if (childNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) {\r
+            XT_log.debug("encountered child node of type %d in attribute list, ignoring it", childNode->getNodeType());\r
+            continue;\r
+        }\r
+\r
+        attribute = static_cast<DOMAttr*>(childNode);\r
+        \r
+        const XMLCh* nsuri=attribute->getNamespaceURI();\r
+        if (!XMLString::compareString(nsuri,XMLConstants::XMLNS_NS)) {\r
+            XT_log.debug("found namespace declaration, adding it to the list of namespaces on the XMLObject");\r
+            xmlObject->addNamespace(Namespace(attribute->getValue(), attribute->getLocalName()));\r
+            continue;\r
+        }\r
+        else if (!XMLString::compareString(nsuri,XMLConstants::XSI_NS) &&\r
+                    !XMLString::compareString(attribute->getLocalName(),type)) {\r
+            XT_log.debug("found xsi:type declaration, setting the schema type of the XMLObject");\r
+            auto_ptr<QName> xsitype(XMLHelper::getAttributeValueAsQName(attribute));\r
+            xmlObject->setSchemaType(xsitype.get());\r
+            continue;\r
+        }\r
+\r
+        XT_log.debug("processing generic attribute");\r
+        processAttribute(xmlObject, attribute);\r
+    }\r
+}\r
+\r
+void AbstractXMLObjectUnmarshaller::unmarshallChildElements(const DOMElement* domElement, XMLObject* xmlObject) const\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("unmarshallChildElements");\r
+#endif\r
+\r
+    if (XT_log.isDebugEnabled()) {\r
+        auto_ptr_char dname(domElement->getLocalName());\r
+        XT_log.debug("unmarshalling child elements of DOM element %s", dname.get());\r
+    }\r
+\r
+    DOMNodeList* childNodes = domElement->getChildNodes();\r
+    DOMNode* childNode;\r
+    const Unmarshaller* unmarshaller;\r
+    if (!childNodes || childNodes->getLength()==0) {\r
+        XT_log.debug("element had no children");\r
+        return;\r
+    }\r
+\r
+    XMLToolingConfig& config=XMLToolingConfig::getConfig();\r
+    for (XMLSize_t i = 0; i < childNodes->getLength(); i++) {\r
+        childNode = childNodes->item(i);\r
+        if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {\r
+            unmarshaller = Unmarshaller::getUnmarshaller(static_cast<DOMElement*>(childNode));\r
+            if (!unmarshaller) {\r
+                if (config.ignoreUnknownElements) {\r
+                    unmarshaller=Unmarshaller::getDefaultUnmarshaller();\r
+                    if (!unmarshaller) {\r
+                        auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
+                        XT_log.error("no default unmarshaller installed, detected unknown child element %s", cname->toString().c_str());\r
+                        throw UnmarshallingException("Unmarshaller detected unknown child element, but no default unmarshaller was found.");\r
+                    }\r
+                    else {\r
+                        XT_log.debug("using default unmarshaller");\r
+                    }\r
+                }\r
+                else {\r
+                    auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
+                    XT_log.error("detected unknown child element %s", cname->toString().c_str());\r
+                    throw UnknownElementException("Unmarshaller detected unknown child element.");\r
+                }\r
+            }\r
+\r
+            if (XT_log.isDebugEnabled()) {\r
+                auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
+                XT_log.debug("unmarshalling child element %s", cname->toString().c_str());\r
+            }\r
+            processChildElement(xmlObject, unmarshaller->unmarshall(static_cast<DOMElement*>(childNode)));\r
+        }\r
+    }\r
+}\r
index 0bc665a..fb45191 100644 (file)
 #if !defined(__xmltooling_xmlunmarshaller_h__)\r
 #define __xmltooling_xmlunmarshaller_h__\r
 \r
-#include <xmltooling/DOMCachingXMLObject.h>\r
-#include <xmltooling/exceptions.h>\r
-#include <xmltooling/XMLObjectBuilder.h>\r
+#include <xmltooling/XMLObject.h>\r
 #include <xmltooling/io/Unmarshaller.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
 \r
 namespace xmltooling {\r
 \r
@@ -55,11 +51,7 @@ namespace xmltooling {
          * @param targetLocalName the local name of either the schema type QName or element QName of the elements this\r
          *            unmarshaller operates on\r
          */\r
-        AbstractXMLObjectUnmarshaller(const XMLCh* targetNamespaceURI, const XMLCh* targetLocalName)\r
-                : m_targetQName(targetNamespaceURI, targetLocalName) {\r
-            if (!targetLocalName || !*targetLocalName)\r
-                throw UnmarshallerException("targetLocalName cannot be null or empty");\r
-        }\r
+        AbstractXMLObjectUnmarshaller(const XMLCh* targetNamespaceURI, const XMLCh* targetLocalName);\r
 \r
         /**\r
          * Checks that the given DOM Element's XSI type or namespace qualified element name matches the target QName of this\r
@@ -69,7 +61,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if the DOM Element does not match the target of this unmarshaller\r
          */\r
-        void checkElementIsTarget(DOMElement* domElement) const;\r
+        void checkElementIsTarget(const DOMElement* domElement) const;\r
         \r
         /**\r
          * Constructs the XMLObject that the given DOM Element will be unmarshalled into. If the DOM element has an XML\r
@@ -84,7 +76,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if there is now XMLObjectBuilder registered for the given DOM Element\r
          */\r
-        virtual XMLObject* buildXMLObject(DOMElement* domElement) const;\r
+        virtual XMLObject* buildXMLObject(const DOMElement* domElement) const;\r
         \r
         /**\r
          * Unmarshalls the attributes from the given DOM Element into the given XMLObject. If the attribute is an XML\r
@@ -97,7 +89,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute\r
          */\r
-        virtual void unmarshallAttributes(DOMElement* domElement, XMLObject* xmlObject) const;\r
+        virtual void unmarshallAttributes(const DOMElement* domElement, XMLObject* xmlObject) const;\r
 \r
         /**\r
          * Unmarshalls a given Element's children. For each child an unmarshaller is retrieved using\r
@@ -109,19 +101,7 @@ namespace xmltooling {
          * \r
          * @throws UnmarshallingException thrown if an error occurs unmarshalling the child elements\r
          */\r
-        virtual void unmarshallChildElements(DOMElement* domElement, XMLObject* xmlObject) const;\r
-\r
-        /**\r
-         * Gets the Unmarshaller for the given Element. If the child element has an explicit XML Schema type,\r
-         * that is used to get the unmarshaller. If there is no unmarshaller registered for the schema type,\r
-         * or the element does not have an explicit schema type, the element's QName is used.\r
-         * \r
-         * @param domElement the DOM Element to get the Unmarshaller for\r
-         * @return the Unmarshaller for the given DOM Element\r
-         * \r
-         * @throws UnmarshallingException thrown if no unmarshaller is available for the given DOM Element\r
-         */\r
-        const Unmarshaller* getUnmarshaller(DOMElement* domElement) const;\r
+        virtual void unmarshallChildElements(const DOMElement* domElement, XMLObject* xmlObject) const;\r
 \r
         /**\r
          * Called after a child element has been unmarshalled so that it can be added to the parent XMLObject.\r
@@ -137,12 +117,11 @@ namespace xmltooling {
          * Called after an attribute has been unmarshalled so that it can be added to the XMLObject.\r
          * \r
          * @param xmlObject the XMLObject\r
-         * @param name the attribute's name\r
-         * @param value the attribute's value\r
+         * @param attribute the attribute being unmarshalled\r
          * \r
          * @throws UnmarshallingException thrown if there is a problem adding the attribute to the XMLObject\r
          */\r
-        virtual void processAttribute(XMLObject* xmlObject, const XMLCh* name, const XMLCh* value) const=0;\r
+        virtual void processAttribute(XMLObject* xmlObject, const DOMAttr* attribute) const=0;\r
     \r
         /**\r
          * Called if the element being unmarshalled contained textual content so that it can be added to the XMLObject.\r
@@ -152,6 +131,7 @@ namespace xmltooling {
          */\r
         virtual void processElementContent(XMLObject* xmlObject, const XMLCh* elementContent) const=0;\r
 \r
+        void* m_log;\r
     private:\r
         QName m_targetQName;\r
     };\r
diff --git a/xmltooling/io/Marshaller.cpp b/xmltooling/io/Marshaller.cpp
new file mode 100644 (file)
index 0000000..fe7424e
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * Marshaller.cpp\r
+ * \r
+ * Transforms XMLObjects into DOM trees \r
+ */\r
+\r
+#include "internal.h"\r
+#include "Marshaller.h"\r
+#include "util/NDC.h"\r
+#include "util/XMLHelper.h"\r
+\r
+#include <log4cpp/Category.hh>\r
+\r
+using namespace xmltooling;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+map<QName,Marshaller*> Marshaller::m_map;\r
+\r
+Marshaller* Marshaller::m_default=NULL;\r
+\r
+const Marshaller* Marshaller::getMarshaller(const DOMElement* domElement)\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("getMarshaller");\r
+#endif\r
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller");\r
\r
+    auto_ptr<QName> schemaType(XMLHelper::getXSIType(domElement));\r
+    const Marshaller* m = getMarshaller(*(schemaType.get()));\r
+    if (m) {\r
+        if (log.isDebugEnabled()) {\r
+            log.debug("Located Marshaller for schema type: %s", schemaType->toString().c_str());\r
+        }\r
+        return m;\r
+    }\r
+    \r
+    auto_ptr<QName> elementName(XMLHelper::getNodeQName(domElement));\r
+    m = getMarshaller(*(elementName.get()));\r
+    if (m) {\r
+        if (log.isDebugEnabled()) {\r
+            log.debug("Located Marshaller for element name: %s", elementName->toString().c_str());\r
+        }\r
+        return m;\r
+    }\r
+\r
+    log.error("No Marshaller was registered for element: %s", elementName->toString().c_str());\r
+    return NULL;\r
+}\r
+\r
+void Marshaller::destroyMarshallers()\r
+{\r
+    for_each(m_map.begin(),m_map.end(),cleanup_pair<QName,Marshaller>());\r
+    m_map.clear();\r
+    deregisterDefaultMarshaller();\r
+}\r
index bc0be37..fffc484 100644 (file)
 /**\r
  * @file Marshaller.h\r
  * \r
- * Transforms XMLObjects into DOM trees.\r
+ * Transforms XMLObjects into DOM trees\r
  */\r
 \r
 #if !defined(__xmltooling_marshaller_h__)\r
 #define __xmltooling_marshaller_h__\r
 \r
+#include <map>\r
 #include <xercesc/dom/DOM.hpp>\r
 #include <xmltooling/XMLObject.h>\r
 \r
@@ -69,13 +70,30 @@ namespace xmltooling {
             std::map<QName,Marshaller*>::const_iterator i=m_map.find(key);\r
             return (i==m_map.end()) ? NULL : i->second;\r
         }\r
+\r
+        /**\r
+         * Retrieves a Marshaller for a DOM element\r
+         * \r
+         * @param element the element for which to return a marshaller\r
+         * @return the marshaller or NULL\r
+         */\r
+        static const Marshaller* getMarshaller(const DOMElement* key);\r
+\r
+        /**\r
+         * Retrieves default Marshaller for DOM elements\r
+         * \r
+         * @return the default marshaller or NULL\r
+         */\r
+        static const Marshaller* getDefaultMarshaller() {\r
+            return m_default;\r
+        }\r
     \r
         /**\r
          * Gets an immutable list of all the marshallers currently registered.\r
          * \r
          * @return list of all the marshallers currently registered\r
          */\r
-        static const std::map<QName,Marshaller*>& getMarshaller() {\r
+        static const std::map<QName,Marshaller*>& getMarshallers() {\r
             return m_map;\r
         }\r
     \r
@@ -86,9 +104,20 @@ namespace xmltooling {
          * @param marshaller the marshaller\r
          */\r
         static void registerMarshaller(const QName& key, Marshaller* marshaller) {\r
+            deregisterMarshaller(key);\r
             m_map[key]=marshaller;\r
         }\r
-    \r
+\r
+        /**\r
+         * Registers default marshaller\r
+         * \r
+         * @param marshaller the default marshaller\r
+         */\r
+        static void registerDefaultMarshaller(Marshaller* marshaller) {\r
+            deregisterDefaultMarshaller();\r
+            m_default=marshaller;\r
+        }\r
+\r
         /**\r
          * Deregisters a marshaller.\r
          * \r
@@ -98,7 +127,15 @@ namespace xmltooling {
             delete getMarshaller(key);\r
             m_map.erase(key);\r
         }\r
-        \r
+\r
+        /**\r
+         * Deregisters default marshaller.\r
+         */\r
+        static void deregisterDefaultMarshaller() {\r
+            delete m_default;\r
+            m_default=NULL;\r
+        }\r
+\r
         /**\r
          * Unregisters and destroys all registered marshallers. \r
          */\r
@@ -106,6 +143,7 @@ namespace xmltooling {
     \r
     private:\r
         static std::map<QName,Marshaller*> m_map;\r
+        static Marshaller* m_default;\r
     };\r
     \r
 };\r
diff --git a/xmltooling/io/Unmarshaller.cpp b/xmltooling/io/Unmarshaller.cpp
new file mode 100644 (file)
index 0000000..1bc92d3
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * Unmarshaller.cpp\r
+ * \r
+ * Transforms DOM trees into XMLObjects \r
+ */\r
+\r
+#include "internal.h"\r
+#include "Unmarshaller.h"\r
+#include "util/NDC.h"\r
+#include "util/XMLHelper.h"\r
+\r
+#include <log4cpp/Category.hh>\r
+\r
+using namespace xmltooling;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+map<QName,Unmarshaller*> Unmarshaller::m_map;\r
+\r
+Unmarshaller* Unmarshaller::m_default=NULL;\r
+\r
+const Unmarshaller* Unmarshaller::getUnmarshaller(const DOMElement* domElement)\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("getUnmarshaller");\r
+#endif\r
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Unmarshaller");\r
\r
+    auto_ptr<QName> schemaType(XMLHelper::getXSIType(domElement));\r
+    const Unmarshaller* m = getUnmarshaller(*(schemaType.get()));\r
+    if (m) {\r
+        if (log.isDebugEnabled()) {\r
+            log.debug("Located Unmarshaller for schema type: %s", schemaType->toString().c_str());\r
+        }\r
+        return m;\r
+    }\r
+    \r
+    auto_ptr<QName> elementName(XMLHelper::getNodeQName(domElement));\r
+    m = getUnmarshaller(*(elementName.get()));\r
+    if (m) {\r
+        if (log.isDebugEnabled()) {\r
+            log.debug("Located Unmarshaller for element name: %s", elementName->toString().c_str());\r
+        }\r
+        return m;\r
+    }\r
+\r
+    log.error("No Unmarshaller was registered for element: %s", elementName->toString().c_str());\r
+    if (XMLToolingConfig::getConfig().ignoreUnknownElements) {\r
+    }\r
+    \r
+    return NULL;\r
+}\r
+\r
+void Unmarshaller::destroyUnmarshallers()\r
+{\r
+    for_each(m_map.begin(),m_map.end(),cleanup_pair<QName,Unmarshaller>());\r
+    m_map.clear();\r
+    deregisterDefaultUnmarshaller();\r
+}\r
index b6e3446..e65f49f 100644 (file)
@@ -23,6 +23,7 @@
 #if !defined(__xmltooling_unmarshaller_h__)\r
 #define __xmltooling_unmarshaller_h__\r
 \r
+#include <map>\r
 #include <xercesc/dom/DOM.hpp>\r
 #include <xmltooling/XMLObject.h>\r
 \r
@@ -60,7 +61,7 @@ namespace xmltooling {
         virtual XMLObject* unmarshall(DOMElement* element, bool bindDocument=false) const=0;\r
 \r
         /**\r
-         * Retrieves a unmarshaller using the key it was registered with.\r
+         * Retrieves an unmarshaller using the key it was registered with.\r
          * \r
          * @param key the key used to register the unmarshaller\r
          * @return the unmarshaller\r
@@ -71,11 +72,28 @@ namespace xmltooling {
         }\r
     \r
         /**\r
+         * Retrieves an Unmarshaller for a DOM element\r
+         * \r
+         * @param element the element for which to return an unmarshaller\r
+         * @return the unmarshaller or NULL\r
+         */\r
+        static const Unmarshaller* getUnmarshaller(const DOMElement* key);\r
+\r
+        /**\r
+         * Retrieves the default Unmarshaller for an unknown DOM element\r
+         * \r
+         * @return the default unmarshaller or NULL\r
+         */\r
+        static const Unmarshaller* getDefaultUnmarshaller() {\r
+            return m_default;\r
+        }\r
+\r
+        /**\r
          * Gets an immutable list of all the unmarshallers currently registered.\r
          * \r
          * @return list of all the unmarshallers currently registered\r
          */\r
-        static const std::map<QName,Unmarshaller*>& getUnmarshaller() {\r
+        static const std::map<QName,Unmarshaller*>& getUnmarshallers() {\r
             return m_map;\r
         }\r
     \r
@@ -86,8 +104,19 @@ namespace xmltooling {
          * @param unmarshaller the unmarshaller\r
          */\r
         static void registerUnmarshaller(const QName& key, Unmarshaller* unmarshaller) {\r
+            deregisterUnmarshaller(key);\r
             m_map[key]=unmarshaller;\r
         }\r
+\r
+        /**\r
+         * Registers a new default unmarshaller\r
+         * \r
+         * @param unmarshaller the default unmarshaller\r
+         */\r
+        static void registerDefaultUnmarshaller(Unmarshaller* unmarshaller) {\r
+            deregisterDefaultUnmarshaller();\r
+            m_default=unmarshaller;\r
+        }\r
     \r
         /**\r
          * Deregisters a unmarshaller.\r
@@ -98,6 +127,14 @@ namespace xmltooling {
             delete getUnmarshaller(key);\r
             m_map.erase(key);\r
         }\r
+\r
+        /**\r
+         * Deregisters the default unmarshaller.\r
+         */\r
+        static void deregisterDefaultUnmarshaller() {\r
+            delete m_default;\r
+            m_default=NULL;\r
+        }\r
         \r
         /**\r
          * Unregisters and destroys all registered unmarshallers. \r
@@ -106,6 +143,7 @@ namespace xmltooling {
     \r
     private:\r
         static std::map<QName,Unmarshaller*> m_map;\r
+        static Unmarshaller* m_default;\r
     };\r
     \r
 };\r