Add cache file type to path resolver
[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     static void (*release)(XMLCh**,MemoryManager*) = &XMLString::release;
116     for_each(
117         m_attributeMap.begin(), m_attributeMap.end(),
118         lambda::bind(
119             release,
120             &lambda::bind(&map<xmltooling::QName,XMLCh*>::value_type::second, boost::ref(_1)),
121             XMLPlatformUtils::fgMemoryManager
122             )
123         );
124 }
125
126 const XMLCh* AbstractAttributeExtensibleXMLObject::getAttribute(const xmltooling::QName& qualifiedName) const
127 {
128     map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.find(qualifiedName);
129     return (i != m_attributeMap.end()) ? i->second : nullptr;
130 }
131
132 void AbstractAttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const XMLCh* value, bool ID)
133 {
134     map<xmltooling::QName,XMLCh*>::iterator i=m_attributeMap.find(qualifiedName);
135     if (i != m_attributeMap.end()) {
136         releaseThisandParentDOM();
137         XMLString::release(&(i->second));
138         if (value && *value) {
139             i->second = XMLString::replicate(value);
140             if (ID)
141                 m_idAttribute = i;
142         }
143         else {
144             if (m_idAttribute == i)
145                 m_idAttribute = m_attributeMap.end();
146             m_attributeMap.erase(i);
147         }
148     }
149     else if (value && *value) {
150         releaseThisandParentDOM();
151         m_attributeMap[qualifiedName] = XMLString::replicate(value);
152         if (ID)
153             m_idAttribute = m_attributeMap.find(qualifiedName);
154         Namespace newNamespace(qualifiedName.getNamespaceURI(), qualifiedName.getPrefix(), false, Namespace::VisiblyUsed);
155         addNamespace(newNamespace);
156     }
157 }
158
159 void AttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const xmltooling::QName& value)
160 {
161     if (!value.hasLocalPart())
162         return;
163
164     if (value.hasPrefix()) {
165         xstring buf(value.getPrefix());
166         buf = buf + chColon + value.getLocalPart();
167         setAttribute(qualifiedName, buf.c_str());
168     }
169     else {
170         setAttribute(qualifiedName, value.getLocalPart());
171     }
172
173     Namespace newNamespace(value.getNamespaceURI(), value.getPrefix(), false, Namespace::NonVisiblyUsed);
174     addNamespace(newNamespace);
175 }
176
177 const map<xmltooling::QName,XMLCh*>& AbstractAttributeExtensibleXMLObject::getExtensionAttributes() const
178 {
179     return m_attributeMap;
180 }
181 const XMLCh* AbstractAttributeExtensibleXMLObject::getXMLID() const
182 {
183     return (m_idAttribute != m_attributeMap.end()) ? m_idAttribute->second : nullptr;
184 }
185
186 void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute)
187 {
188     xmltooling::QName q(attribute->getNamespaceURI(), attribute->getLocalName(), attribute->getPrefix());
189     bool ID = attribute->isId() || isRegisteredIDAttribute(q);
190     setAttribute(q,attribute->getNodeValue(),ID);
191     if (ID) {
192 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
193         attribute->getOwnerElement()->setIdAttributeNode(attribute, true);
194 #else
195         attribute->getOwnerElement()->setIdAttributeNode(attribute);
196 #endif
197     }
198 }
199
200 void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const
201 {
202     for (map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.begin(); i != m_attributeMap.end(); ++i) {
203         DOMAttr* attr = domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(), i->first.getLocalPart());
204         if (i->first.hasPrefix())
205             attr->setPrefix(i->first.getPrefix());
206         attr->setNodeValue(i->second);
207         domElement->setAttributeNodeNS(attr);
208         if (m_idAttribute == i) {
209 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
210             domElement->setIdAttributeNode(attr, true);
211 #else
212             domElement->setIdAttributeNode(attr);
213 #endif
214         }
215     }
216 }