Add xsi:nil support to objects.
[shibboleth/xmltooling.git] / xmltooling / base.h
index f8eacaf..b6d3ba3 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file base.h
+ * @file xmltooling/base.h
  * 
  * Base header file definitions
  * Must be included prior to including any other header
   #include <xmltooling/config_pub.h>
 #endif
 
+#ifdef XMLTOOLING_LITE
+# define XMLTOOLING_NO_XMLSEC 1
+#endif
+
 // Windows and GCC4 Symbol Visibility Macros
 #ifdef WIN32
   #define XMLTOOL_IMPORT __declspec(dllimport)
@@ -77,7 +81,7 @@
 #define MAKE_NONCOPYABLE(type) \
     private: \
         type(const type&); \
-        type& operator=(const type&);
+        type& operator=(const type&)
 
 #ifndef DOXYGEN_SKIP
 #ifndef NULL
 #define END_XMLOBJECT }
 
 /**
+ * Declares a static variable holding the XMLObject's element QName.
+ */
+#define DECL_ELEMENT_QNAME \
+    public: \
+        XMLTOOLING_DOXYGEN(Element QName) \
+        static xmltooling::QName ELEMENT_QNAME
+
+/**
+ * Declares a static variable holding the XMLObject's schema type QName.
+ */
+#define DECL_TYPE_QNAME \
+    public: \
+        XMLTOOLING_DOXYGEN(Type QName) \
+        static xmltooling::QName TYPE_QNAME
+
+/**
+ * Implements a static variable holding an XMLObject's element QName.
+ * 
+ * @param cname             the name of the XMLObject specialization
+ * @param namespaceURI      the XML namespace of the default associated element
+ * @param namespacePrefix   the XML namespace prefix of the default associated element
+ */
+#define IMPL_ELEMENT_QNAME(cname,namespaceURI,namespacePrefix) \
+    xmltooling::QName cname::ELEMENT_QNAME(namespaceURI,cname::LOCAL_NAME,namespacePrefix)
+
+/**
+ * Implements a static variable holding an XMLObject's schema type QName.
+ * 
+ * @param cname             the name of the XMLObject specialization
+ * @param namespaceURI      the XML namespace of the default associated element
+ * @param namespacePrefix   the XML namespace prefix of the default associated element
+ */
+#define IMPL_TYPE_QNAME(cname,namespaceURI,namespacePrefix) \
+    xmltooling::QName cname::TYPE_QNAME(namespaceURI,cname::TYPE_NAME,namespacePrefix)
+
+/**
  * Declares abstract set method for a typed XML attribute.
  * The get method is omitted.
  * 
  * @param namespaceURI  the XML namespace of the attribute
  */
 #define MARSHALL_STRING_ATTRIB(proper,ucase,namespaceURI) \
-    if (m_##proper) { \
+    if (m_##proper && *m_##proper) { \
         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, m_##proper); \
     }
 
  * @param namespaceURI  the XML namespace of the attribute
  */
 #define MARSHALL_INTEGER_ATTRIB(proper,ucase,namespaceURI) \
-    if (m_##proper) { \
+    if (m_##proper && *m_##proper) { \
         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, m_##proper); \
     }
 
  * @param namespaceURI  the XML namespace of the attribute
  */
 #define MARSHALL_ID_ATTRIB(proper,ucase,namespaceURI) \
-    if (m_##proper) { \
+    if (m_##proper && *m_##proper) { \
         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, m_##proper); \
         domElement->setIdAttributeNS(namespaceURI, ucase##_ATTRIB_NAME); \
     }
 #define PROC_TYPED_CHILD(proper,namespaceURI,force) \
     if (force || xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,proper::LOCAL_NAME)) { \
         proper* typesafe=dynamic_cast<proper*>(childXMLObject); \
-        if (typesafe) { \
-            set##proper(typesafe); \
+        if (typesafe && !m_##proper) { \
+            typesafe->setParent(this); \
+            *m_pos_##proper = m_##proper = typesafe; \
             return; \
         } \
     }
 #define PROC_TYPED_FOREIGN_CHILD(proper,ns,namespaceURI,force) \
     if (force || xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,ns::proper::LOCAL_NAME)) { \
         ns::proper* typesafe=dynamic_cast<ns::proper*>(childXMLObject); \
-        if (typesafe) { \
-            set##proper(typesafe); \
+        if (typesafe && !m_##proper) { \
+            typesafe->setParent(this); \
+            *m_pos_##proper = m_##proper = typesafe; \
             return; \
         } \
     }
  */
 #define PROC_XMLOBJECT_CHILD(proper,namespaceURI) \
     if (xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,proper::LOCAL_NAME)) { \
-        set##proper(childXMLObject); \
-        return; \
+        if (!m_##proper) { \
+            childXMLObject->setParent(this); \
+            *m_pos_##proper = m_##proper = childXMLObject; \
+            return; \
+        } \
     }
 
 /**
 #define DECL_INTEGER_CONTENT(proper) \
     XMLTOOLING_DOXYGEN(Returns proper in integer form after a NULL indicator.) \
     std::pair<bool,int> get##proper() const { \
-        return std::make_pair((getTextContent()!=NULL), (getTextContent()!=NULL ? xercesc::XMLString::parseInt(getTextContent()) : NULL)); \
+        return std::make_pair((getTextContent()!=NULL), (getTextContent()!=NULL ? xercesc::XMLString::parseInt(getTextContent()) : 0)); \
     } \
     XMLTOOLING_DOXYGEN(Sets proper.) \
     void set##proper(int proper) { \
  */
 #define BEGIN_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix) \
     XMLTOOLING_DOXYGEN(Builder for cname objects.) \
-    class linkage cname##Builder : public xmltooling::XMLObjectBuilder { \
+    class linkage cname##Builder : public xmltooling::ConcreteXMLObjectBuilder { \
     public: \
         virtual ~cname##Builder() {} \
         XMLTOOLING_DOXYGEN(Default builder.) \
  */
 #define BEGIN_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix) \
     XMLTOOLING_DOXYGEN(Builder for cname objects.) \
-    class linkage cname##Builder : public xmltooling::XMLObjectBuilder { \
+    class linkage cname##Builder : public xmltooling::ConcreteXMLObjectBuilder { \
     public: \
         virtual ~cname##Builder() {} \
         XMLTOOLING_DOXYGEN(Default builder.) \
         virtual void validate(const xmltooling::XMLObject* xmlObject) const { \
             const cname* ptr=dynamic_cast<const cname*>(xmlObject); \
             if (!ptr) \
-                throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()))
+                throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name())); \
+            if (ptr->nil() && (ptr->hasChildren() || ptr->getTextContent())) \
+               throw xmltooling::ValidationException("Object has nil property but with children or content.")
 
 /**
  * Begins the declaration of a Schema Validator specialization subclass.
         virtual void validate(const xmltooling::XMLObject* xmlObject) const { \
             const cname* ptr=dynamic_cast<const cname*>(xmlObject); \
             if (!ptr) \
-                throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()))
+                throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()));
 
 /**
  * Ends the declaration of a Validator specialization.
@@ -1509,7 +1556,7 @@ namespace xmltooling {
          * 
          * @param p   a pair in which the second component is the object to delete
          */
-        void operator()(const std::pair<A,B*>& p) {delete p.second;}
+        void operator()(const std::pair<const A,B*>& p) {delete p.second;}
     };
 
     /**
@@ -1522,7 +1569,7 @@ namespace xmltooling {
          * 
          * @param p   a pair in which the second component is the const object to delete
          */
-        void operator()(const std::pair<A,const B*>& p) {delete const_cast<B*>(p.second);}
+        void operator()(const std::pair<const A,const B*>& p) {delete const_cast<B*>(p.second);}
     };
 };