Set fourth file version digit to signify rebuild.
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractAttributeExtensibleXMLObject.cpp
index 7362956..166e96c 100644 (file)
-/*\r
- *  Copyright 2001-2006 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * AbstractAttributeExtensibleXMLObject.cpp\r
- * \r
- * Extension of AbstractDOMCachingXMLObject that implements an AttributeExtensibleXMLObject. \r
- */\r
-\r
-#include "internal.h"\r
-#include "AbstractAttributeExtensibleXMLObject.h"\r
-\r
-#include <algorithm>\r
-#include <functional>\r
-\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-class _release : public unary_function<XMLCh*,void> {\r
-public:\r
-    void operator()(pair<QName,XMLCh*> p) const {\r
-        XMLString::release(&(p.second));\r
-    }\r
-};\r
-\r
-AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject()\r
-{\r
-    for_each(m_attributeMap.begin(),m_attributeMap.end(),_release());\r
-}\r
-\r
-void AbstractAttributeExtensibleXMLObject::setAttribute(QName& qualifiedName, const XMLCh* value)\r
-{\r
-    map<QName,XMLCh*>::iterator i=m_attributeMap.find(qualifiedName);\r
-    if (i!=m_attributeMap.end()) {\r
-        releaseThisandParentDOM();\r
-        XMLString::release(&(i->second));\r
-        if (value) {\r
-            i->second=XMLString::replicate(value);\r
-        }\r
-        else {\r
-            m_attributeMap.erase(i);\r
-        }\r
-    }\r
-    else if (value) {\r
-        releaseThisandParentDOM();\r
-        m_attributeMap[qualifiedName]=XMLString::replicate(value);\r
-    }\r
-}\r
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ */
+
+/**
+ * AbstractAttributeExtensibleXMLObject.cpp
+ * 
+ * Extension of AbstractDOMCachingXMLObject that implements an AttributeExtensibleXMLObject. 
+ */
+
+#include "internal.h"
+#include "AbstractAttributeExtensibleXMLObject.h"
+#include "ElementExtensibleXMLObject.h"
+#include "ElementProxy.h"
+
+#include <algorithm>
+#include <functional>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace xmltooling;
+using namespace xercesc;
+using namespace boost::lambda;
+using namespace boost;
+using namespace std;
+
+
+ElementExtensibleXMLObject::ElementExtensibleXMLObject()
+{
+}
+
+ElementExtensibleXMLObject::~ElementExtensibleXMLObject()
+{
+}
+
+ElementProxy::ElementProxy()
+{
+}
+
+ElementProxy::~ElementProxy()
+{
+}
+
+set<xmltooling::QName> AttributeExtensibleXMLObject::m_idAttributeSet;
+
+AttributeExtensibleXMLObject::AttributeExtensibleXMLObject()
+{
+}
+
+AttributeExtensibleXMLObject::~AttributeExtensibleXMLObject()
+{
+}
+
+const set<xmltooling::QName>& AttributeExtensibleXMLObject::getRegisteredIDAttributes()
+{
+    return m_idAttributeSet;
+}
+
+bool AttributeExtensibleXMLObject::isRegisteredIDAttribute(const xmltooling::QName& name)
+{
+    return m_idAttributeSet.find(name)!=m_idAttributeSet.end();
+}
+
+void AttributeExtensibleXMLObject::registerIDAttribute(const xmltooling::QName& name)
+{
+    m_idAttributeSet.insert(name);
+}
+
+void AttributeExtensibleXMLObject::deregisterIDAttribute(const xmltooling::QName& name)
+{
+    m_idAttributeSet.erase(name);
+}
+
+void AttributeExtensibleXMLObject::deregisterIDAttributes()
+{
+    m_idAttributeSet.clear();
+}
+
+AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject()
+{
+    m_idAttribute = m_attributeMap.end();
+}
+
+AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src)
+    : AbstractXMLObject(src)
+{
+    m_idAttribute = m_attributeMap.end();
+    for (map<xmltooling::QName,XMLCh*>::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);
+    }
+}
+
+AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject()
+{
+#ifdef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
+    static void (*release)(XMLCh**) = &XMLString::release;
+#else
+    static void (*release)(XMLCh**,MemoryManager*) = &XMLString::release;
+#endif
+    for_each(
+        m_attributeMap.begin(), m_attributeMap.end(),
+        lambda::bind(
+            release,
+            &lambda::bind(&map<xmltooling::QName,XMLCh*>::value_type::second, boost::ref(_1))
+#ifndef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
+            ,XMLPlatformUtils::fgMemoryManager
+#endif
+            )
+        );
+}
+
+const XMLCh* AbstractAttributeExtensibleXMLObject::getAttribute(const xmltooling::QName& qualifiedName) const
+{
+    map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.find(qualifiedName);
+    return (i != m_attributeMap.end()) ? i->second : nullptr;
+}
+
+const XMLCh* AbstractAttributeExtensibleXMLObject::getLang() const
+{
+    static const XMLCh _lang[] = UNICODE_LITERAL_4(l,a,n,g);
+    static xmltooling::QName qname(xmlconstants::XML_NS, _lang);
+    return getAttribute(qname);
+}
+
+void AbstractAttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const XMLCh* value, bool ID)
+{
+    map<xmltooling::QName,XMLCh*>::iterator i=m_attributeMap.find(qualifiedName);
+    if (i != m_attributeMap.end()) {
+        releaseThisandParentDOM();
+        XMLString::release(&(i->second));
+        if (value && *value) {
+            i->second = XMLString::replicate(value);
+            if (ID)
+                m_idAttribute = i;
+        }
+        else {
+            if (m_idAttribute == i)
+                m_idAttribute = m_attributeMap.end();
+            m_attributeMap.erase(i);
+        }
+    }
+    else if (value && *value) {
+        releaseThisandParentDOM();
+        m_attributeMap[qualifiedName] = XMLString::replicate(value);
+        if (ID)
+            m_idAttribute = m_attributeMap.find(qualifiedName);
+        Namespace newNamespace(qualifiedName.getNamespaceURI(), qualifiedName.getPrefix(), false, Namespace::VisiblyUsed);
+        addNamespace(newNamespace);
+    }
+}
+
+void AttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const xmltooling::QName& value)
+{
+    if (!value.hasLocalPart())
+        return;
+
+    if (value.hasPrefix()) {
+        xstring buf(value.getPrefix());
+        buf = buf + chColon + value.getLocalPart();
+        setAttribute(qualifiedName, buf.c_str());
+    }
+    else {
+        setAttribute(qualifiedName, value.getLocalPart());
+    }
+
+    Namespace newNamespace(value.getNamespaceURI(), value.getPrefix(), false, Namespace::NonVisiblyUsed);
+    addNamespace(newNamespace);
+}
+
+const map<xmltooling::QName,XMLCh*>& AbstractAttributeExtensibleXMLObject::getExtensionAttributes() const
+{
+    return m_attributeMap;
+}
+const XMLCh* AbstractAttributeExtensibleXMLObject::getXMLID() const
+{
+    return (m_idAttribute != m_attributeMap.end()) ? m_idAttribute->second : nullptr;
+}
+
+void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute)
+{
+    xmltooling::QName q(attribute->getNamespaceURI(), attribute->getLocalName(), attribute->getPrefix());
+    bool ID = attribute->isId() || isRegisteredIDAttribute(q);
+    setAttribute(q,attribute->getNodeValue(),ID);
+    if (ID) {
+#ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
+        attribute->getOwnerElement()->setIdAttributeNode(attribute, true);
+#else
+        attribute->getOwnerElement()->setIdAttributeNode(attribute);
+#endif
+    }
+}
+
+void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const
+{
+    for (map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.begin(); i != m_attributeMap.end(); ++i) {
+        DOMAttr* attr = domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(), i->first.getLocalPart());
+        if (i->first.hasPrefix())
+            attr->setPrefix(i->first.getPrefix());
+        attr->setNodeValue(i->second);
+        domElement->setAttributeNodeNS(attr);
+        if (m_idAttribute == i) {
+#ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
+            domElement->setIdAttributeNode(attr, true);
+#else
+            domElement->setIdAttributeNode(attr);
+#endif
+        }
+    }
+}