From c61580d5c20b1af1c8c7e30f8811aae322c30de2 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Fri, 8 Sep 2006 01:59:23 +0000 Subject: [PATCH] Added built-in ID attribute support to base classes. --- .../AbstractAttributeExtensibleXMLObject.cpp | 17 +++++- xmltooling/AbstractAttributeExtensibleXMLObject.h | 22 +++++-- xmltooling/AbstractXMLObject.h | 4 ++ xmltooling/AttributeExtensibleXMLObject.h | 68 ++++++++++++++++++++-- xmltooling/XMLObject.h | 7 +++ xmltooling/XMLToolingConfig.cpp | 5 ++ xmltooling/base.h | 12 ++++ xmltooling/signature/impl/KeyInfoImpl.cpp | 2 +- xmltoolingtest/XMLObjectBaseTestCase.h | 1 + 9 files changed, 127 insertions(+), 11 deletions(-) diff --git a/xmltooling/AbstractAttributeExtensibleXMLObject.cpp b/xmltooling/AbstractAttributeExtensibleXMLObject.cpp index 781b722..7b7fd32 100644 --- a/xmltooling/AbstractAttributeExtensibleXMLObject.cpp +++ b/xmltooling/AbstractAttributeExtensibleXMLObject.cpp @@ -29,6 +29,8 @@ using namespace xmltooling; using namespace std; +set AttributeExtensibleXMLObject::m_idAttributeSet; + AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject() { for (map::iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) @@ -38,12 +40,16 @@ AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject() AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src) : AbstractXMLObject(src) { + m_idAttribute = m_attributeMap.end(); for (map::const_iterator i=src.m_attributeMap.begin(); i!=src.m_attributeMap.end(); i++) { m_attributeMap[i->first] = XMLString::replicate(i->second); } + if (src.m_idAttribute != src.m_attributeMap.end()) { + m_idAttribute = m_attributeMap.find(src.m_idAttribute->first); + } } -void AbstractAttributeExtensibleXMLObject::setAttribute(QName& qualifiedName, const XMLCh* value) +void AbstractAttributeExtensibleXMLObject::setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID) { map::iterator i=m_attributeMap.find(qualifiedName); if (i!=m_attributeMap.end()) { @@ -53,11 +59,20 @@ void AbstractAttributeExtensibleXMLObject::setAttribute(QName& qualifiedName, co i->second=XMLString::replicate(value); } else { + if (m_idAttribute==i) + m_idAttribute=m_attributeMap.end(); m_attributeMap.erase(i); } + + if (ID) { + m_idAttribute=i; + } } else if (value) { releaseThisandParentDOM(); m_attributeMap[qualifiedName]=XMLString::replicate(value); + if (ID) { + m_idAttribute = m_attributeMap.find(qualifiedName); + } } } diff --git a/xmltooling/AbstractAttributeExtensibleXMLObject.h b/xmltooling/AbstractAttributeExtensibleXMLObject.h index ca2b390..e2e65ea 100644 --- a/xmltooling/AbstractAttributeExtensibleXMLObject.h +++ b/xmltooling/AbstractAttributeExtensibleXMLObject.h @@ -38,26 +38,40 @@ namespace xmltooling { * AbstractXMLObject mixin that implements AttributeExtensibleXMLObject. * Inherit from this class to add support for attribute wildcarding. */ - class XMLTOOL_API AbstractAttributeExtensibleXMLObject : public virtual AttributeExtensibleXMLObject, public virtual AbstractXMLObject + class XMLTOOL_API AbstractAttributeExtensibleXMLObject + : public virtual AttributeExtensibleXMLObject, public virtual AbstractXMLObject { public: virtual ~AbstractAttributeExtensibleXMLObject(); - virtual const XMLCh* getAttribute(QName& qualifiedName) const { + const XMLCh* getAttribute(const QName& qualifiedName) const { std::map::const_iterator i=m_attributeMap.find(qualifiedName); return (i==m_attributeMap.end()) ? NULL : i->second; } - virtual void setAttribute(QName& qualifiedName, const XMLCh* value); + void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false); + + const std::map& getExtensionAttributes() const { + return m_attributeMap; + } + + const XMLCh* getXMLID() const { + return (m_idAttribute == m_attributeMap.end()) ? NULL : m_idAttribute->second; + } protected: - AbstractAttributeExtensibleXMLObject() {} + AbstractAttributeExtensibleXMLObject() { + m_idAttribute = m_attributeMap.end(); + } /** Copy constructor. */ AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src); /** Map of arbitrary attributes. */ std::map m_attributeMap; + + /** Points to the last attribute designated as an XML ID. */ + std::map::const_iterator m_idAttribute; }; }; diff --git a/xmltooling/AbstractXMLObject.h b/xmltooling/AbstractXMLObject.h index e159df1..dee54be 100644 --- a/xmltooling/AbstractXMLObject.h +++ b/xmltooling/AbstractXMLObject.h @@ -69,6 +69,10 @@ namespace xmltooling { const QName* getSchemaType() const { return m_typeQname; } + + const XMLCh* getXMLID() const { + return NULL; + } bool hasParent() const { return m_parent != NULL; diff --git a/xmltooling/AttributeExtensibleXMLObject.h b/xmltooling/AttributeExtensibleXMLObject.h index 2d1472f..8ba087b 100644 --- a/xmltooling/AttributeExtensibleXMLObject.h +++ b/xmltooling/AttributeExtensibleXMLObject.h @@ -27,6 +27,11 @@ using namespace xercesc; +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + namespace xmltooling { /** @@ -34,27 +39,80 @@ namespace xmltooling { */ class XMLTOOL_API AttributeExtensibleXMLObject : public virtual XMLObject { - public: + protected: AttributeExtensibleXMLObject() {} + + public: virtual ~AttributeExtensibleXMLObject() {} /** - * Gets the value of an XML attribute of the object + * Gets the value of an XML attribute of the object. * * @param qualifiedName qualified name of the attribute * @return the attribute value, or NULL */ - virtual const XMLCh* getAttribute(QName& qualifiedName) const=0; + virtual const XMLCh* getAttribute(const QName& qualifiedName) const=0; /** - * Sets (or clears) an XML attribute of the object + * Sets (or clears) an XML attribute of the object. * * @param qualifiedName qualified name of the attribute * @param value value to set, or NULL to clear + * @param ID true iff the attribute is an XML ID */ - virtual void setAttribute(QName& qualifiedName, const XMLCh* value)=0; + virtual void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false)=0; + + /** + * Gets an immutable map of the extended XML attributes of the object. + * + * This set is not guaranteed to (and generally will not) include + * attributes defined directly on the object's "type". + */ + virtual const std::map& getExtensionAttributes() const=0; + + /** + * Gets an immutable list of all the ID attributes currently registered. + * + * @return list of all the ID attributes currently registered + */ + static const std::set& getRegisteredIDAttributes() { + return m_idAttributeSet; + } + + /** + * Registers a new attribute as being of XML ID type. + * + * @param name the qualified attribute name + */ + static void registerIDAttribute(const QName& name) { + m_idAttributeSet.insert(name); + } + + /** + * Deregisters an ID attribute. + * + * @param name the qualified attribute name + */ + static void deregisterIDAttribute(const QName& name) { + m_idAttributeSet.erase(name); + } + + /** + * Deregisters all ID attributes. + */ + static void deregisterIDAttributes() { + m_idAttributeSet.clear(); + } + + private: + /** Set of attributes to treat as XML IDs. */ + static std::set m_idAttributeSet; }; }; +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + #endif /* __xmltooling_attrextxmlobj_h__ */ diff --git a/xmltooling/XMLObject.h b/xmltooling/XMLObject.h index ed750ce..21715e9 100644 --- a/xmltooling/XMLObject.h +++ b/xmltooling/XMLObject.h @@ -104,6 +104,13 @@ namespace xmltooling { virtual const QName* getSchemaType() const=0; /** + * Gets the value of the ID attribute set on this object, if any. + * + * @return an ID value or NULL + */ + virtual const XMLCh* getXMLID() const=0; + + /** * Checks to see if this object has a parent. * * @return true if the object has a parent, false if not diff --git a/xmltooling/XMLToolingConfig.cpp b/xmltooling/XMLToolingConfig.cpp index 9477479..e248f6a 100644 --- a/xmltooling/XMLToolingConfig.cpp +++ b/xmltooling/XMLToolingConfig.cpp @@ -184,6 +184,10 @@ bool XMLToolingInternalConfig::init() registerCredentialResolvers(); registerTrustEngines(); #endif + + // Register xml:id as an ID attribute. + static const XMLCh xmlid[] = UNICODE_LITERAL_2(i,d); + AttributeExtensibleXMLObject::registerIDAttribute(QName(XMLConstants::XML_NS, xmlid)); } catch (const xercesc::XMLException&) { log.fatal("caught exception while initializing Xerces"); @@ -200,6 +204,7 @@ void XMLToolingInternalConfig::term() KeyInfoSchemaValidators.destroyValidators(); EncryptionSchemaValidators.destroyValidators(); XMLToolingException::deregisterFactories(); + AttributeExtensibleXMLObject::deregisterIDAttributes(); #ifndef XMLTOOLING_NO_XMLSEC TrustEngineManager.deregisterFactories(); diff --git a/xmltooling/base.h b/xmltooling/base.h index fe281c5..228640d 100644 --- a/xmltooling/base.h +++ b/xmltooling/base.h @@ -455,6 +455,18 @@ IMPL_XMLOBJECT_ATTRIB(proper,XMLCh) /** + * Implements get/set methods and a private member for a string XML attribute, + * plus a getXMLID override. + * + * @param proper the proper name of the attribute + */ +#define IMPL_ID_ATTRIB(proper) \ + IMPL_XMLOBJECT_ATTRIB(proper,XMLCh) \ + const XMLCh* getXMLID() const { \ + return m_##proper; \ + } + +/** * Implements get/set methods and a private member for a DateTime XML attribute. * * @param proper the proper name of the attribute diff --git a/xmltooling/signature/impl/KeyInfoImpl.cpp b/xmltooling/signature/impl/KeyInfoImpl.cpp index 9a92069..922d583 100644 --- a/xmltooling/signature/impl/KeyInfoImpl.cpp +++ b/xmltooling/signature/impl/KeyInfoImpl.cpp @@ -694,7 +694,7 @@ namespace xmlsignature { } IMPL_XMLOBJECT_CLONE(KeyInfo); - IMPL_STRING_ATTRIB(Id); + IMPL_ID_ATTRIB(Id); IMPL_TYPED_CHILDREN(KeyName,m_children.end()); IMPL_TYPED_CHILDREN(KeyValue,m_children.end()); IMPL_TYPED_CHILDREN(RetrievalMethod,m_children.end()); diff --git a/xmltoolingtest/XMLObjectBaseTestCase.h b/xmltoolingtest/XMLObjectBaseTestCase.h index d2d56c0..a90b1fc 100644 --- a/xmltoolingtest/XMLObjectBaseTestCase.h +++ b/xmltoolingtest/XMLObjectBaseTestCase.h @@ -96,6 +96,7 @@ public: return new SimpleXMLObject(*this); } + const XMLCh* getXMLID() const { return getId(); } const XMLCh* getId() const { return m_id; } void setId(const XMLCh* id) { m_id=prepareForAssignment(m_id,id); } -- 2.1.4