Reducing header overuse, non-inlining selected methods (CPPOST-35).
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractAttributeExtensibleXMLObject.cpp
1 /*
2  *  Copyright 2001-2009 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
31 using namespace xmltooling;
32 using namespace std;
33
34 using xercesc::DOMAttr;
35 using xercesc::DOMElement;
36 using xercesc::XMLString;
37
38 ElementExtensibleXMLObject::ElementExtensibleXMLObject()
39 {
40 }
41
42 ElementExtensibleXMLObject::~ElementExtensibleXMLObject()
43 {
44 }
45
46 ElementProxy::ElementProxy()
47 {
48 }
49
50 ElementProxy::~ElementProxy()
51 {
52 }
53
54 set<QName> AttributeExtensibleXMLObject::m_idAttributeSet;
55
56 AttributeExtensibleXMLObject::AttributeExtensibleXMLObject()
57 {
58 }
59
60 AttributeExtensibleXMLObject::~AttributeExtensibleXMLObject()
61 {
62 }
63
64 const set<QName>& AttributeExtensibleXMLObject::getRegisteredIDAttributes()
65 {
66     return m_idAttributeSet;
67 }
68
69 bool AttributeExtensibleXMLObject::isRegisteredIDAttribute(const QName& name)
70 {
71     return m_idAttributeSet.find(name)!=m_idAttributeSet.end();
72 }
73
74 void AttributeExtensibleXMLObject::registerIDAttribute(const QName& name)
75 {
76     m_idAttributeSet.insert(name);
77 }
78
79 void AttributeExtensibleXMLObject::deregisterIDAttribute(const QName& name)
80 {
81     m_idAttributeSet.erase(name);
82 }
83
84 void AttributeExtensibleXMLObject::deregisterIDAttributes()
85 {
86     m_idAttributeSet.clear();
87 }
88
89 AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject()
90 {
91     m_idAttribute = m_attributeMap.end();
92 }
93
94 AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src)
95     : AbstractXMLObject(src)
96 {
97     m_idAttribute = m_attributeMap.end();
98     for (map<QName,XMLCh*>::const_iterator i=src.m_attributeMap.begin(); i!=src.m_attributeMap.end(); i++) {
99         m_attributeMap[i->first] = XMLString::replicate(i->second);
100     }
101     if (src.m_idAttribute != src.m_attributeMap.end()) {
102         m_idAttribute = m_attributeMap.find(src.m_idAttribute->first);
103     }
104 }
105
106 AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject()
107 {
108     for (map<QName,XMLCh*>::iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++)
109         XMLString::release(&(i->second));
110 }
111
112 const XMLCh* AbstractAttributeExtensibleXMLObject::getAttribute(const QName& qualifiedName) const
113 {
114     map<QName,XMLCh*>::const_iterator i=m_attributeMap.find(qualifiedName);
115     return (i==m_attributeMap.end()) ? NULL : i->second;
116 }
117
118 void AbstractAttributeExtensibleXMLObject::setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID)
119 {
120     map<QName,XMLCh*>::iterator i=m_attributeMap.find(qualifiedName);
121     if (i!=m_attributeMap.end()) {
122         releaseThisandParentDOM();
123         XMLString::release(&(i->second));
124         if (value && *value) {
125             i->second=XMLString::replicate(value);
126             if (ID)
127                 m_idAttribute=i;
128         }
129         else {
130             if (m_idAttribute==i)
131                 m_idAttribute=m_attributeMap.end();
132             m_attributeMap.erase(i);
133         }
134     }
135     else if (value && *value) {
136         releaseThisandParentDOM();
137         m_attributeMap[qualifiedName]=XMLString::replicate(value);
138         if (ID)
139             m_idAttribute = m_attributeMap.find(qualifiedName);
140     }
141 }
142
143 const map<QName,XMLCh*>& AbstractAttributeExtensibleXMLObject::getExtensionAttributes() const
144 {
145     return m_attributeMap;
146 }
147 const XMLCh* AbstractAttributeExtensibleXMLObject::getXMLID() const
148 {
149     return (m_idAttribute == m_attributeMap.end()) ? NULL : m_idAttribute->second;
150 }
151
152 void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute)
153 {
154     QName q(attribute->getNamespaceURI(),attribute->getLocalName(),attribute->getPrefix());
155     bool ID = attribute->isId() || isRegisteredIDAttribute(q);
156     setAttribute(q,attribute->getNodeValue(),ID);
157     if (ID) {
158 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
159         attribute->getOwnerElement()->setIdAttributeNode(attribute, true);
160 #else
161         attribute->getOwnerElement()->setIdAttributeNode(attribute);
162 #endif
163     }
164 }
165
166 void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const
167 {
168     for (map<QName,XMLCh*>::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) {
169         DOMAttr* attr=domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(),i->first.getLocalPart());
170         if (i->first.hasPrefix())
171             attr->setPrefix(i->first.getPrefix());
172         attr->setNodeValue(i->second);
173         domElement->setAttributeNodeNS(attr);
174         if (m_idAttribute==i) {
175 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
176             domElement->setIdAttributeNode(attr, true);
177 #else
178             domElement->setIdAttributeNode(attr);
179 #endif
180         }
181     }
182 }