Set fourth file version digit to signify rebuild.
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractAttributeExtensibleXMLObject.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * AbstractAttributeExtensibleXMLObject.cpp
23  * 
24  * Extension of AbstractDOMCachingXMLObject that implements an AttributeExtensibleXMLObject. 
25  */
26
27 #include "internal.h"
28 #include "AbstractAttributeExtensibleXMLObject.h"
29 #include "ElementExtensibleXMLObject.h"
30 #include "ElementProxy.h"
31
32 #include <algorithm>
33 #include <functional>
34 #include <boost/lambda/bind.hpp>
35 #include <boost/lambda/lambda.hpp>
36 #include <xercesc/util/XMLUniDefs.hpp>
37
38 using namespace xmltooling;
39 using namespace xercesc;
40 using namespace boost::lambda;
41 using namespace boost;
42 using namespace std;
43
44
45 ElementExtensibleXMLObject::ElementExtensibleXMLObject()
46 {
47 }
48
49 ElementExtensibleXMLObject::~ElementExtensibleXMLObject()
50 {
51 }
52
53 ElementProxy::ElementProxy()
54 {
55 }
56
57 ElementProxy::~ElementProxy()
58 {
59 }
60
61 set<xmltooling::QName> AttributeExtensibleXMLObject::m_idAttributeSet;
62
63 AttributeExtensibleXMLObject::AttributeExtensibleXMLObject()
64 {
65 }
66
67 AttributeExtensibleXMLObject::~AttributeExtensibleXMLObject()
68 {
69 }
70
71 const set<xmltooling::QName>& AttributeExtensibleXMLObject::getRegisteredIDAttributes()
72 {
73     return m_idAttributeSet;
74 }
75
76 bool AttributeExtensibleXMLObject::isRegisteredIDAttribute(const xmltooling::QName& name)
77 {
78     return m_idAttributeSet.find(name)!=m_idAttributeSet.end();
79 }
80
81 void AttributeExtensibleXMLObject::registerIDAttribute(const xmltooling::QName& name)
82 {
83     m_idAttributeSet.insert(name);
84 }
85
86 void AttributeExtensibleXMLObject::deregisterIDAttribute(const xmltooling::QName& name)
87 {
88     m_idAttributeSet.erase(name);
89 }
90
91 void AttributeExtensibleXMLObject::deregisterIDAttributes()
92 {
93     m_idAttributeSet.clear();
94 }
95
96 AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject()
97 {
98     m_idAttribute = m_attributeMap.end();
99 }
100
101 AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src)
102     : AbstractXMLObject(src)
103 {
104     m_idAttribute = m_attributeMap.end();
105     for (map<xmltooling::QName,XMLCh*>::const_iterator i = src.m_attributeMap.begin(); i != src.m_attributeMap.end(); ++i) {
106         m_attributeMap[i->first] = XMLString::replicate(i->second);
107     }
108     if (src.m_idAttribute != src.m_attributeMap.end()) {
109         m_idAttribute = m_attributeMap.find(src.m_idAttribute->first);
110     }
111 }
112
113 AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject()
114 {
115 #ifdef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
116     static void (*release)(XMLCh**) = &XMLString::release;
117 #else
118     static void (*release)(XMLCh**,MemoryManager*) = &XMLString::release;
119 #endif
120     for_each(
121         m_attributeMap.begin(), m_attributeMap.end(),
122         lambda::bind(
123             release,
124             &lambda::bind(&map<xmltooling::QName,XMLCh*>::value_type::second, boost::ref(_1))
125 #ifndef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
126             ,XMLPlatformUtils::fgMemoryManager
127 #endif
128             )
129         );
130 }
131
132 const XMLCh* AbstractAttributeExtensibleXMLObject::getAttribute(const xmltooling::QName& qualifiedName) const
133 {
134     map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.find(qualifiedName);
135     return (i != m_attributeMap.end()) ? i->second : nullptr;
136 }
137
138 const XMLCh* AbstractAttributeExtensibleXMLObject::getLang() const
139 {
140     static const XMLCh _lang[] = UNICODE_LITERAL_4(l,a,n,g);
141     static xmltooling::QName qname(xmlconstants::XML_NS, _lang);
142     return getAttribute(qname);
143 }
144
145 void AbstractAttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const XMLCh* value, bool ID)
146 {
147     map<xmltooling::QName,XMLCh*>::iterator i=m_attributeMap.find(qualifiedName);
148     if (i != m_attributeMap.end()) {
149         releaseThisandParentDOM();
150         XMLString::release(&(i->second));
151         if (value && *value) {
152             i->second = XMLString::replicate(value);
153             if (ID)
154                 m_idAttribute = i;
155         }
156         else {
157             if (m_idAttribute == i)
158                 m_idAttribute = m_attributeMap.end();
159             m_attributeMap.erase(i);
160         }
161     }
162     else if (value && *value) {
163         releaseThisandParentDOM();
164         m_attributeMap[qualifiedName] = XMLString::replicate(value);
165         if (ID)
166             m_idAttribute = m_attributeMap.find(qualifiedName);
167         Namespace newNamespace(qualifiedName.getNamespaceURI(), qualifiedName.getPrefix(), false, Namespace::VisiblyUsed);
168         addNamespace(newNamespace);
169     }
170 }
171
172 void AttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const xmltooling::QName& value)
173 {
174     if (!value.hasLocalPart())
175         return;
176
177     if (value.hasPrefix()) {
178         xstring buf(value.getPrefix());
179         buf = buf + chColon + value.getLocalPart();
180         setAttribute(qualifiedName, buf.c_str());
181     }
182     else {
183         setAttribute(qualifiedName, value.getLocalPart());
184     }
185
186     Namespace newNamespace(value.getNamespaceURI(), value.getPrefix(), false, Namespace::NonVisiblyUsed);
187     addNamespace(newNamespace);
188 }
189
190 const map<xmltooling::QName,XMLCh*>& AbstractAttributeExtensibleXMLObject::getExtensionAttributes() const
191 {
192     return m_attributeMap;
193 }
194 const XMLCh* AbstractAttributeExtensibleXMLObject::getXMLID() const
195 {
196     return (m_idAttribute != m_attributeMap.end()) ? m_idAttribute->second : nullptr;
197 }
198
199 void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute)
200 {
201     xmltooling::QName q(attribute->getNamespaceURI(), attribute->getLocalName(), attribute->getPrefix());
202     bool ID = attribute->isId() || isRegisteredIDAttribute(q);
203     setAttribute(q,attribute->getNodeValue(),ID);
204     if (ID) {
205 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
206         attribute->getOwnerElement()->setIdAttributeNode(attribute, true);
207 #else
208         attribute->getOwnerElement()->setIdAttributeNode(attribute);
209 #endif
210     }
211 }
212
213 void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const
214 {
215     for (map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.begin(); i != m_attributeMap.end(); ++i) {
216         DOMAttr* attr = domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(), i->first.getLocalPart());
217         if (i->first.hasPrefix())
218             attr->setPrefix(i->first.getPrefix());
219         attr->setNodeValue(i->second);
220         domElement->setAttributeNodeNS(attr);
221         if (m_idAttribute == i) {
222 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
223             domElement->setIdAttributeNode(attr, true);
224 #else
225             domElement->setIdAttributeNode(attr);
226 #endif
227         }
228     }
229 }