Refactored simple content and child-handling into mixin classes.
[shibboleth/xmltooling.git] / xmltooling / AbstractXMLObject.h
index b4f7788..5ead42f 100644 (file)
 \r
 #include <xmltooling/XMLObject.h>\r
 \r
-#pragma warning( push )\r
-#pragma warning( disable : 4250 4251 )\r
+#if defined (_MSC_VER)\r
+    #pragma warning( push )\r
+    #pragma warning( disable : 4250 4251 )\r
+#endif\r
 \r
 namespace xmltooling {\r
 \r
     /**\r
      * An abstract implementation of XMLObject.\r
+     * This is the primary concrete base class, and supplies basic namespace,\r
+     * type, and parent handling. Most implementation classes should not\r
+     * directly inherit from this class, but rather from the various mixins\r
+     * that supply the rest of the XMLObject interface, as required.\r
      */\r
     class XMLTOOL_API AbstractXMLObject : public virtual XMLObject\r
     {\r
@@ -40,100 +46,105 @@ namespace xmltooling {
             delete m_typeQname;\r
         }\r
 \r
-        /**\r
-         * @see XMLObject::getElementQName()\r
-         */\r
         const QName& getElementQName() const {\r
             return m_elementQname;\r
         }\r
 \r
-        /**\r
-         * @see XMLObject::setElementNamespacePrefix()\r
-         */\r
-        void setElementNamespacePrefix(const XMLCh* prefix) {\r
-            m_elementQname.setPrefix(prefix);\r
-        }\r
-\r
-        /**\r
-         * @see XMLObject::getNamespaces()\r
-         */\r
         const std::set<Namespace>& getNamespaces() const {\r
             return m_namespaces;\r
         }\r
     \r
-        /**\r
-         * @see XMLObject::addNamespace()\r
-         */\r
-        void addNamespace(const Namespace& ns) {\r
-            m_namespaces.insert(ns);\r
+        void addNamespace(const Namespace& ns) const {\r
+            if (ns.alwaysDeclare() || m_namespaces.find(ns)==m_namespaces.end()) {\r
+                m_namespaces.insert(ns);\r
+            }\r
         }\r
     \r
-        /**\r
-         * @see XMLObject::removeNamespace()\r
-         */\r
         void removeNamespace(const Namespace& ns) {\r
             m_namespaces.erase(ns);\r
         }\r
         \r
-        /**\r
-         * @see XMLObject::getSchemaType()\r
-         */\r
         const QName* getSchemaType() const {\r
             return m_typeQname;\r
         }\r
     \r
-        /**\r
-         * @see XMLObject::setSchemaType()\r
-         */\r
-        void setSchemaType(const QName* type) {\r
-            delete m_typeQname;\r
-            m_typeQname = NULL;\r
-            if (type) {\r
-                m_typeQname = new QName(*type);\r
-                addNamespace(Namespace(type->getNamespaceURI(), type->getPrefix()));\r
-            }\r
-        }\r
-    \r
-        /**\r
-         * @see XMLObject::hasParent()\r
-         */\r
         bool hasParent() const {\r
             return m_parent != NULL;\r
         }\r
      \r
-        /**\r
-         * @see XMLObject::getParent()\r
-         */\r
         XMLObject* getParent() const {\r
             return m_parent;\r
         }\r
     \r
-        /**\r
-         * @see XMLObject::setParent()\r
-         */\r
         void setParent(XMLObject* parent) {\r
             m_parent = parent;\r
         }\r
-    \r
+\r
      protected:\r
         /**\r
          * Constructor\r
          * \r
-         * @param namespaceURI the namespace the element is in\r
-         * @param elementLocalName the local name of the XML element this Object represents\r
+         * @param nsURI         the namespace of the element\r
+         * @param localName     the local name of the XML element this Object represents\r
+         * @param prefix        the namespace prefix to use\r
+         * @param schemaType    the xsi:type to use\r
          */\r
-        explicit AbstractXMLObject(const XMLCh* namespaceURI, const XMLCh* elementLocalName)\r
-            : m_elementQname(namespaceURI,elementLocalName), m_typeQname(NULL), m_parent(NULL) {}\r
+        AbstractXMLObject(\r
+            const XMLCh* nsURI=NULL, const XMLCh* localName=NULL, const XMLCh* prefix=NULL, const QName* schemaType=NULL\r
+            );\r
+\r
+        /** Copy constructor. */\r
+        AbstractXMLObject(const AbstractXMLObject& src);\r
         \r
+        /**\r
+         * A helper function for derived classes.\r
+         * This 'normalizes' newString, and then if it is different from oldString,\r
+         * it invalidates the DOM, frees the old string, and return the new.\r
+         * If not different, it frees the new string and just returns the old value.\r
+         * \r
+         * @param oldValue - the current value\r
+         * @param newValue - the new value\r
+         * \r
+         * @return the value that should be assigned\r
+         */\r
+        XMLCh* prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue);\r
+\r
+        /**\r
+         * A helper function for derived classes, for assignment of (singleton) XML objects.\r
+         * \r
+         * It is indifferent to whether either the old or the new version of the value is null. \r
+         * This method will do a safe compare of the objects and will also invalidate the DOM if appropriate.\r
+         * Note that since the new value (even if NULL) is always returned, it may be more efficient\r
+         * to discard the return value and just assign independently if a dynamic cast would be involved.\r
+         * \r
+         * @param oldValue - current value\r
+         * @param newValue - proposed new value\r
+         * @return the new value \r
+         * \r
+         * @throws XMLObjectException if the new child already has a parent.\r
+         */\r
+        XMLObject* prepareForAssignment(XMLObject* oldValue, XMLObject* newValue);\r
+\r
+        /**\r
+         * Set of namespaces associated with the object.\r
+         */\r
+        mutable std::set<Namespace> m_namespaces;\r
+\r
+        /**\r
+         * Logging object.\r
+         */\r
+        void* m_log;\r
+\r
     private:\r
         XMLObject* m_parent;\r
         QName m_elementQname;\r
         QName* m_typeQname;\r
-        std::set<Namespace> m_namespaces;\r
     };\r
 \r
 };\r
 \r
-#pragma warning( pop )\r
+#if defined (_MSC_VER)\r
+    #pragma warning( pop )\r
+#endif\r
 \r
 #endif /* __xmltooling_abstractxmlobj_h__ */\r