Handle variant element names, merge in wildcard class, add test cases.
[shibboleth/xmltooling.git] / xmltooling / impl / UnknownElement.cpp
index 745abe9..6759e5f 100644 (file)
@@ -17,7 +17,7 @@
 /**\r
  * UnknownElement.cpp\r
  * \r
- * Basic implementations suitable for use as defaults for unrecognized content\r
+ * Basic implementation suitable for use as default for unrecognized content\r
  */\r
 \r
 #include "internal.h"\r
@@ -70,7 +70,7 @@ void UnknownElementImpl::serialize(string& s) const
         XMLHelper::serialize(getDOM(),s);\r
 }\r
 \r
-DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument* document) const\r
+DOMElement* UnknownElementImpl::marshall(DOMDocument* document, MarshallingContext* ctx) const\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("marshall");\r
@@ -79,30 +79,32 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument
     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller");\r
     log.debug("marshalling unknown content");\r
 \r
-    UnknownElementImpl* unk=dynamic_cast<UnknownElementImpl*>(xmlObject);\r
-    if (!unk)\r
-        throw MarshallingException("Only objects of class UnknownElementImpl can be marshalled.");\r
-    \r
-    DOMElement* cachedDOM=unk->getDOM();\r
+    DOMElement* cachedDOM=getDOM();\r
     if (cachedDOM) {\r
         if (!document || document==cachedDOM->getOwnerDocument()) {\r
             log.debug("XMLObject has a usable cached DOM, reusing it");\r
             if (document)\r
                 setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
-            unk->releaseParentDOM(true);\r
+            releaseParentDOM(true);\r
             return cachedDOM;\r
         }\r
         \r
-        // We have a DOM but it doesn't match the document we were given. This both sucks and blows.\r
-        // Without an adoptNode option to maintain the child pointers, we rely on our custom\r
-        // implementation class to preserve the XML when we release the existing DOM.\r
-        unk->releaseDOM();\r
+        // We have a DOM but it doesn't match the document we were given, so we import\r
+        // it into the new document.\r
+        cachedDOM=static_cast<DOMElement*>(document->importNode(cachedDOM, true));\r
+\r
+        // Recache the DOM.\r
+        setDocumentElement(document, cachedDOM);\r
+        log.debug("caching imported DOM for XMLObject");\r
+        setDOM(cachedDOM, false);\r
+        releaseParentDOM(true);\r
+        return cachedDOM;\r
     }\r
     \r
-    // If we get here, we didn't have a usable DOM (and/or we flushed the one we had).\r
+    // If we get here, we didn't have a usable DOM.\r
     // We need to reparse the XML we saved off into a new DOM.\r
     bool bindDocument=false;\r
-    MemBufInputSource src(reinterpret_cast<const XMLByte*>(unk->m_xml.c_str()),unk->m_xml.length(),"UnknownElementImpl");\r
+    MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"UnknownElementImpl");\r
     Wrapper4InputSource dsrc(&src,false);\r
     log.debug("parsing XML back into DOM tree");\r
     DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc);\r
@@ -123,13 +125,13 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMDocument
     // Recache the DOM and clear the serialized copy.\r
     setDocumentElement(document, cachedDOM);\r
     log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not ");\r
-    unk->setDOM(cachedDOM, bindDocument);\r
-    unk->releaseParentDOM(true);\r
-    unk->m_xml.erase();\r
+    setDOM(cachedDOM, bindDocument);\r
+    releaseParentDOM(true);\r
+    m_xml.erase();\r
     return cachedDOM;\r
 }\r
 \r
-DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement* parentElement) const\r
+DOMElement* UnknownElementImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const\r
 {\r
 #ifdef _DEBUG\r
     xmltooling::NDC ndc("marshall");\r
@@ -138,28 +140,30 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement*
     Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller");\r
     log.debug("marshalling unknown content");\r
 \r
-    UnknownElementImpl* unk=dynamic_cast<UnknownElementImpl*>(xmlObject);\r
-    if (!unk)\r
-        throw MarshallingException("Only objects of class UnknownElementImpl can be marshalled.");\r
-    \r
-    DOMElement* cachedDOM=unk->getDOM();\r
+    DOMElement* cachedDOM=getDOM();\r
     if (cachedDOM) {\r
         if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) {\r
             log.debug("XMLObject has a usable cached DOM, reusing it");\r
             parentElement->appendChild(cachedDOM);\r
-            unk->releaseParentDOM(true);\r
+            releaseParentDOM(true);\r
             return cachedDOM;\r
         }\r
         \r
-        // We have a DOM but it doesn't match the document we were given. This both sucks and blows.\r
-        // Without an adoptNode option to maintain the child pointers, we rely on our custom\r
-        // implementation class to preserve the XML when we release the existing DOM.\r
-        unk->releaseDOM();\r
+        // We have a DOM but it doesn't match the document we were given, so we import\r
+        // it into the new document.\r
+        cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(cachedDOM, true));\r
+\r
+        // Recache the DOM.\r
+        parentElement->appendChild(cachedDOM);\r
+        log.debug("caching imported DOM for XMLObject");\r
+        setDOM(cachedDOM, false);\r
+        releaseParentDOM(true);\r
+        return cachedDOM;\r
     }\r
     \r
     // If we get here, we didn't have a usable DOM (and/or we flushed the one we had).\r
     // We need to reparse the XML we saved off into a new DOM.\r
-    MemBufInputSource src(reinterpret_cast<const XMLByte*>(unk->m_xml.c_str()),unk->m_xml.length(),"UnknownElementImpl");\r
+    MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"UnknownElementImpl");\r
     Wrapper4InputSource dsrc(&src,false);\r
     log.debug("parsing XML back into DOM tree");\r
     DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc);\r
@@ -171,15 +175,14 @@ DOMElement* UnknownElementMarshaller::marshall(XMLObject* xmlObject, DOMElement*
     // Recache the DOM and clear the serialized copy.\r
     parentElement->appendChild(cachedDOM);\r
     log.debug("caching DOM for XMLObject");\r
-    unk->setDOM(cachedDOM, false);\r
-    unk->releaseParentDOM(true);\r
-    unk->m_xml.erase();\r
+    setDOM(cachedDOM, false);\r
+    releaseParentDOM(true);\r
+    m_xml.erase();\r
     return cachedDOM;\r
 }\r
 \r
-XMLObject* UnknownElementUnmarshaller::unmarshall(DOMElement* element, bool bindDocument) const\r
+XMLObject* UnknownElementImpl::unmarshall(DOMElement* element, bool bindDocument)\r
 {\r
-    UnknownElementImpl* ret=new UnknownElementImpl();\r
-    ret->setDOM(element, bindDocument);\r
-    return ret;\r
+    setDOM(element, bindDocument);\r
+    return this;\r
 }\r