Add additional macros for longer string literals
[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 void AbstractAttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const XMLCh* value, bool ID)
139 {
140     map<xmltooling::QName,XMLCh*>::iterator i=m_attributeMap.find(qualifiedName);
141     if (i != m_attributeMap.end()) {
142         releaseThisandParentDOM();
143         XMLString::release(&(i->second));
144         if (value && *value) {
145             i->second = XMLString::replicate(value);
146             if (ID)
147                 m_idAttribute = i;
148         }
149         else {
150             if (m_idAttribute == i)
151                 m_idAttribute = m_attributeMap.end();
152             m_attributeMap.erase(i);
153         }
154     }
155     else if (value && *value) {
156         releaseThisandParentDOM();
157         m_attributeMap[qualifiedName] = XMLString::replicate(value);
158         if (ID)
159             m_idAttribute = m_attributeMap.find(qualifiedName);
160         Namespace newNamespace(qualifiedName.getNamespaceURI(), qualifiedName.getPrefix(), false, Namespace::VisiblyUsed);
161         addNamespace(newNamespace);
162     }
163 }
164
165 void AttributeExtensibleXMLObject::setAttribute(const xmltooling::QName& qualifiedName, const xmltooling::QName& value)
166 {
167     if (!value.hasLocalPart())
168         return;
169
170     if (value.hasPrefix()) {
171         xstring buf(value.getPrefix());
172         buf = buf + chColon + value.getLocalPart();
173         setAttribute(qualifiedName, buf.c_str());
174     }
175     else {
176         setAttribute(qualifiedName, value.getLocalPart());
177     }
178
179     Namespace newNamespace(value.getNamespaceURI(), value.getPrefix(), false, Namespace::NonVisiblyUsed);
180     addNamespace(newNamespace);
181 }
182
183 const map<xmltooling::QName,XMLCh*>& AbstractAttributeExtensibleXMLObject::getExtensionAttributes() const
184 {
185     return m_attributeMap;
186 }
187 const XMLCh* AbstractAttributeExtensibleXMLObject::getXMLID() const
188 {
189     return (m_idAttribute != m_attributeMap.end()) ? m_idAttribute->second : nullptr;
190 }
191
192 void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute)
193 {
194     xmltooling::QName q(attribute->getNamespaceURI(), attribute->getLocalName(), attribute->getPrefix());
195     bool ID = attribute->isId() || isRegisteredIDAttribute(q);
196     setAttribute(q,attribute->getNodeValue(),ID);
197     if (ID) {
198 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
199         attribute->getOwnerElement()->setIdAttributeNode(attribute, true);
200 #else
201         attribute->getOwnerElement()->setIdAttributeNode(attribute);
202 #endif
203     }
204 }
205
206 void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const
207 {
208     for (map<xmltooling::QName,XMLCh*>::const_iterator i = m_attributeMap.begin(); i != m_attributeMap.end(); ++i) {
209         DOMAttr* attr = domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(), i->first.getLocalPart());
210         if (i->first.hasPrefix())
211             attr->setPrefix(i->first.getPrefix());
212         attr->setNodeValue(i->second);
213         domElement->setAttributeNodeNS(attr);
214         if (m_idAttribute == i) {
215 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
216             domElement->setIdAttributeNode(attr, true);
217 #else
218             domElement->setIdAttributeNode(attr);
219 #endif
220         }
221     }
222 }