X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2FAbstractDOMCachingXMLObject.cpp;h=fb4c0f508ae262674658da7fedf1ce649ee5aee0;hb=c5183613326e3d36a544b2941654d0667a29b836;hp=0b9f064e9fad96be4e0e7734f5042e714a072360;hpb=5800e81da1d8ab1356666d8a32e83ffd48a7b884;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/AbstractDOMCachingXMLObject.cpp b/xmltooling/AbstractDOMCachingXMLObject.cpp index 0b9f064..fb4c0f5 100644 --- a/xmltooling/AbstractDOMCachingXMLObject.cpp +++ b/xmltooling/AbstractDOMCachingXMLObject.cpp @@ -21,8 +21,10 @@ */ #include "internal.h" -#include "exceptions.h" #include "AbstractDOMCachingXMLObject.h" +#include "exceptions.h" +#include "XMLObjectBuilder.h" +#include "util/XMLHelper.h" #include #include @@ -38,63 +40,106 @@ AbstractDOMCachingXMLObject::~AbstractDOMCachingXMLObject() m_document->release(); } -void AbstractDOMCachingXMLObject::releaseDOM() +void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument) const { - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); - if (log.isDebugEnabled()) - log.debug("Releasing cached DOM reprsentation for %s", getElementQName().toString().c_str()); - - // We don't get rid of the document we're holding, if any. - // The marshalling process deals with that. - setDOM(NULL); + m_dom=dom; + if (dom) { + if (bindDocument) { + setDocument(dom->getOwnerDocument()); + } + } } -void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease) +void AbstractDOMCachingXMLObject::releaseDOM() const { - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); - if (log.isDebugEnabled()) { - log.debug( - "Releasing cached DOM representation for parent of %s with propagation set to %s", - getElementQName().toString().c_str(), propagateRelease ? "true" : "false" - ); + if (m_dom) { + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); + if (log.isDebugEnabled()) { + string qname=getElementQName().toString(); + log.debug("releasing cached DOM representation for (%s)", qname.empty() ? "unknown" : qname.c_str()); + } + setDOM(NULL); } +} +void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease) const +{ DOMCachingXMLObject* domCachingParent = dynamic_cast(getParent()); if (domCachingParent) { - domCachingParent->releaseDOM(); - if (propagateRelease) - domCachingParent->releaseParentDOM(propagateRelease); + if (domCachingParent->getDOM()) { + Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( + "releasing cached DOM representation for parent object with propagation set to %s", + propagateRelease ? "true" : "false" + ); + domCachingParent->releaseDOM(); + if (propagateRelease) + domCachingParent->releaseParentDOM(propagateRelease); + } } } class _release : public binary_function { public: void operator()(XMLObject* obj, bool propagate) const { - DOMCachingXMLObject* domCachingParent = dynamic_cast(obj); - if (domCachingParent) { - domCachingParent->releaseDOM(); + DOMCachingXMLObject* domCaching = dynamic_cast(obj); + if (domCaching) { + domCaching->releaseDOM(); if (propagate) - domCachingParent->releaseChildrenDOM(propagate); + domCaching->releaseChildrenDOM(propagate); } } }; -void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease) +void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease) const { - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); - if (log.isDebugEnabled()) { - log.debug( - "Releasing cached DOM representation for children of %s with propagation set to %s", - getElementQName().toString().c_str(), propagateRelease ? "true" : "false" + if (hasChildren()) { + Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( + "releasing cached DOM representation for children with propagation set to %s", + propagateRelease ? "true" : "false" ); + for_each(m_children.begin(),m_children.end(),bind2nd(_release(),propagateRelease)); + } +} + +DOMElement* AbstractDOMCachingXMLObject::cloneDOM(DOMDocument* doc) const +{ + if (getDOM()) { + if (!doc) + doc=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); + return static_cast(doc->importNode(getDOM(),true)); + } + return NULL; +} + +XMLObject* AbstractDOMCachingXMLObject::clone() const +{ + // See if we can clone via the DOM. + DOMElement* domCopy=cloneDOM(); + if (domCopy) { + // Seemed to work, so now we unmarshall the DOM to produce the clone. + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(domCopy); + if (!b) { + auto_ptr q(XMLHelper::getNodeQName(domCopy)); + Category::getInstance(XMLTOOLING_LOGCAT".DOM").error( + "DOM clone failed, unable to locate builder for element (%s)", q->toString().c_str() + ); + domCopy->getOwnerDocument()->release(); + throw UnmarshallingException("Unable to locate builder for cloned element."); + } + try { + auto_ptr objCopy(b->buildObject(domCopy)); + objCopy->unmarshall(domCopy, true); // bind document + return objCopy.release(); + } + catch (...) { + domCopy->getOwnerDocument()->release(); + throw; + } } - - vector children; - if (getOrderedChildren(children)) - for_each(children.begin(),children.end(),bind2nd(_release(),propagateRelease)); + return NULL; } -XMLObject* AbstractDOMCachingXMLObject::prepareForAssignment(const XMLObject* oldValue, XMLObject* newValue) { +XMLObject* AbstractDOMCachingXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue) { if (newValue && newValue->hasParent()) throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject");