Multi-line svn commit, see body.
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractXMLObject.cpp
index cc9381a..e019f4e 100644 (file)
 \r
 #include "internal.h"\r
 #include "AbstractXMLObject.h"\r
+#include "exceptions.h"\r
 \r
 #include <algorithm>\r
 #include <log4cpp/Category.hh>\r
 \r
 using namespace xmltooling;\r
 \r
-AbstractXMLObject::~AbstractXMLObject() {\r
-    delete m_typeQname;\r
-    std::for_each(m_children.begin(), m_children.end(), cleanup<XMLObject>());\r
+AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)\r
+    : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), m_schemaLocation(NULL),\r
+        m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL)\r
+{\r
+    addNamespace(Namespace(nsURI, prefix));\r
+    if (schemaType) {\r
+        m_typeQname = new QName(*schemaType);\r
+        addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix()));\r
+    }\r
+}\r
+\r
+AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src)\r
+    : m_namespaces(src.m_namespaces), m_log(src.m_log), m_schemaLocation(XMLString::replicate(src.m_schemaLocation)),\r
+        m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL)\r
+{\r
+    if (src.m_typeQname)\r
+        m_typeQname=new QName(*src.m_typeQname);\r
+}\r
+\r
+XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue)\r
+{\r
+    if (!XMLString::equals(oldValue,newValue)) {\r
+        releaseThisandParentDOM();\r
+        XMLCh* newString = XMLString::replicate(newValue);\r
+        XMLString::release(&oldValue);\r
+        return newString;\r
+    }\r
+    return oldValue;\r
+}\r
+\r
+QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue)\r
+{\r
+    if (!oldValue) {\r
+        if (newValue) {\r
+            releaseThisandParentDOM();\r
+            Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());\r
+            addNamespace(newNamespace);\r
+            return new QName(*newValue);\r
+        }\r
+        return NULL;\r
+    }\r
+\r
+    delete oldValue;\r
+    releaseThisandParentDOM();\r
+    if (newValue) {\r
+        Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());\r
+        addNamespace(newNamespace);\r
+        return new QName(*newValue);\r
+    }\r
+    return NULL;\r
+}\r
+\r
+DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue)\r
+{\r
+    if (!oldValue) {\r
+        if (newValue) {\r
+            releaseThisandParentDOM();\r
+            return new DateTime(*newValue);\r
+        }\r
+        return NULL;\r
+    }\r
+\r
+    delete oldValue;\r
+    releaseThisandParentDOM();\r
+    return newValue ? new DateTime(*newValue) : NULL;\r
+}\r
+\r
+DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue)\r
+{\r
+    delete oldValue;\r
+    releaseThisandParentDOM();\r
+    DateTime* ret = new DateTime(newValue);\r
+    ret->parseDateTime();\r
+    return ret;\r
+}\r
+\r
+DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue)\r
+{\r
+    delete oldValue;\r
+    releaseThisandParentDOM();\r
+    DateTime* ret = new DateTime(newValue);\r
+    ret->parseDateTime();\r
+    return ret;\r
 }\r
 \r
-AbstractXMLObject::AbstractXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix)\r
-    : m_elementQname(namespaceURI,elementLocalName, namespacePrefix), m_typeQname(NULL), m_parent(NULL),\r
-        m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject"))\r
+XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue)\r
 {\r
-    addNamespace(Namespace(namespaceURI, namespacePrefix));\r
+    if (newValue && newValue->hasParent())\r
+        throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject");\r
+\r
+    if (!oldValue) {\r
+        if (newValue) {\r
+            releaseThisandParentDOM();\r
+            newValue->setParent(this);\r
+        }\r
+        return newValue;\r
+    }\r
+\r
+    if (oldValue != newValue) {\r
+        delete oldValue;\r
+        releaseThisandParentDOM();\r
+        if (newValue)\r
+            newValue->setParent(this);\r
+    }\r
+\r
+    return newValue;\r
+}\r
+\r
+void AbstractXMLObject::detach()\r
+{\r
+    if (!getParent())\r
+        return;\r
+    else if (getParent()->hasParent())\r
+        throw XMLObjectException("Cannot detach an object whose parent is itself a child.");\r
+\r
+    // Pull ourselves out of the parent and then blast him.\r
+    getParent()->removeChild(this);\r
+    delete m_parent;\r
+    m_parent = NULL;\r
 }\r