80b29718ed4512015fa687794bb18199d8fecec3
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractXMLObject.h
1 /*
2 *  Copyright 2001-2007 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  * @file xmltooling/AbstractXMLObject.h
19  * 
20  * An abstract implementation of XMLObject.
21  */
22
23 #ifndef __xmltooling_abstractxmlobj_h__
24 #define __xmltooling_abstractxmlobj_h__
25
26 #include <xmltooling/XMLObject.h>
27 #include <xmltooling/util/DateTime.h>
28
29 #include <log4cpp/Category.hh>
30
31 #if defined (_MSC_VER)
32     #pragma warning( push )
33     #pragma warning( disable : 4250 4251 )
34 #endif
35
36 namespace xmltooling {
37
38     /**
39      * An abstract implementation of XMLObject.
40      * This is the primary concrete base class, and supplies basic namespace,
41      * type, and parent handling. Most implementation classes should not
42      * directly inherit from this class, but rather from the various mixins
43      * that supply the rest of the XMLObject interface, as required.
44      */
45     class XMLTOOL_API AbstractXMLObject : public virtual XMLObject
46     {
47     public:
48         virtual ~AbstractXMLObject() {
49             delete m_typeQname;
50             xercesc::XMLString::release(&m_schemaLocation);
51             xercesc::XMLString::release(&m_noNamespaceSchemaLocation);
52         }
53
54         void detach();
55
56         const QName& getElementQName() const {
57             return m_elementQname;
58         }
59
60         const std::set<Namespace>& getNamespaces() const {
61             return m_namespaces;
62         }
63     
64         void addNamespace(const Namespace& ns) const {
65             std::set<Namespace>::iterator i = m_namespaces.find(ns);
66             if (i == m_namespaces.end())
67                 m_namespaces.insert(ns);
68             else if (ns.alwaysDeclare())
69                 const_cast<Namespace&>(*i).setAlwaysDeclare(true);
70         }
71     
72         void removeNamespace(const Namespace& ns) {
73             m_namespaces.erase(ns);
74         }
75         
76         const QName* getSchemaType() const {
77             return m_typeQname;
78         }
79         
80         const XMLCh* getXMLID() const {
81             return NULL;
82         }
83     
84         bool hasParent() const {
85             return m_parent != NULL;
86         }
87      
88         XMLObject* getParent() const {
89             return m_parent;
90         }
91     
92         void setParent(XMLObject* parent) {
93             m_parent = parent;
94         }
95
96      protected:
97         /**
98          * Constructor
99          * 
100          * @param nsURI         the namespace of the element
101          * @param localName     the local name of the XML element this Object represents
102          * @param prefix        the namespace prefix to use
103          * @param schemaType    the xsi:type to use
104          */
105         AbstractXMLObject(
106             const XMLCh* nsURI=NULL, const XMLCh* localName=NULL, const XMLCh* prefix=NULL, const QName* schemaType=NULL
107             );
108
109         /** Copy constructor. */
110         AbstractXMLObject(const AbstractXMLObject& src);
111         
112         /**
113          * A helper function for derived classes, for assignment of strings.
114          *
115          * This 'normalizes' newString, and then if it is different from oldString,
116          * it invalidates the DOM, frees the old string, and returns the new.
117          * If not different, it frees the new string and just returns the old value.
118          * 
119          * @param oldValue - the current value
120          * @param newValue - the new value
121          * 
122          * @return the value that should be assigned
123          */
124         XMLCh* prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue);
125
126         /**
127          * A helper function for derived classes, for assignment of date/time data.
128          *
129          * It invalidates the DOM, frees the old object, and returns the new.
130          * 
131          * @param oldValue - the current value
132          * @param newValue - the new value
133          * 
134          * @return the value that should be assigned
135          */
136         DateTime* prepareForAssignment(DateTime* oldValue, const DateTime* newValue);
137
138         /**
139          * A helper function for derived classes, for assignment of date/time data.
140          *
141          * It invalidates the DOM, frees the old object, and returns the new.
142          * 
143          * @param oldValue - the current value
144          * @param newValue - the epoch to assign as the new value
145          * 
146          * @return the value that should be assigned
147          */
148         DateTime* prepareForAssignment(DateTime* oldValue, time_t newValue);
149
150         /**
151          * A helper function for derived classes, for assignment of date/time data.
152          *
153          * It invalidates the DOM, frees the old object, and returns the new.
154          * 
155          * @param oldValue - the current value
156          * @param newValue - the new value in string form
157          * 
158          * @return the value that should be assigned
159          */
160         DateTime* prepareForAssignment(DateTime* oldValue, const XMLCh* newValue);
161
162         /**
163          * A helper function for derived classes, for assignment of QName data.
164          *
165          * It invalidates the DOM, frees the old object, and returns the new.
166          * 
167          * @param oldValue - the current value
168          * @param newValue - the new value
169          * 
170          * @return the value that should be assigned
171          */
172         QName* prepareForAssignment(QName* oldValue, const QName* newValue);
173
174         /**
175          * A helper function for derived classes, for assignment of (singleton) XML objects.
176          * 
177          * It is indifferent to whether either the old or the new version of the value is null. 
178          * This method will do a safe compare of the objects and will also invalidate the DOM if appropriate.
179          * Note that since the new value (even if NULL) is always returned, it may be more efficient
180          * to discard the return value and just assign independently if a dynamic cast would be involved.
181          * 
182          * @param oldValue - current value
183          * @param newValue - proposed new value
184          * @return the new value 
185          * 
186          * @throws XMLObjectException if the new child already has a parent.
187          */
188         XMLObject* prepareForAssignment(XMLObject* oldValue, XMLObject* newValue);
189
190         /**
191          * Set of namespaces associated with the object.
192          */
193         mutable std::set<Namespace> m_namespaces;
194
195         /**
196          * Logging object.
197          */
198         log4cpp::Category& m_log;
199
200         /**
201          * Stores off xsi:schemaLocation attribute.
202          */
203         XMLCh* m_schemaLocation;
204
205         /**
206          * Stores off xsi:noNamespaceSchemaLocation attribute.
207          */
208         XMLCh* m_noNamespaceSchemaLocation;
209
210     private:
211         XMLObject* m_parent;
212         QName m_elementQname;
213         QName* m_typeQname;
214     };
215
216 };
217
218 #if defined (_MSC_VER)
219     #pragma warning( pop )
220 #endif
221
222 #endif /* __xmltooling_abstractxmlobj_h__ */