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