Prelims for symbol hiding, doesn't work yet
[shibboleth/cpp-xmltooling.git] / xmltooling / base.h
1 /*
2  *  Copyright 2001-2006 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 base.h
19  * 
20  * Base header file definitions
21  * Must be included prior to including any other header
22  */
23
24 #ifndef __xmltooling_base_h__
25 #define __xmltooling_base_h__
26
27 #if defined (_MSC_VER) || defined(__BORLANDC__)
28   #include <xmltooling/config_pub_win32.h>
29 #else
30   #include <xmltooling/config_pub.h>
31 #endif
32
33 // Windows and GCC4 Symbol Visibility Macros
34 #ifdef WIN32
35   #define XMLTOOL_IMPORT __declspec(dllimport)
36   #define XMLTOOL_EXPORT __declspec(dllexport)
37   #define XMLTOOL_DLLLOCAL
38   #define XMLTOOL_DLLPUBLIC
39 #else
40   #define XMLTOOL_IMPORT
41   #ifdef GCC_HASCLASSVISIBILITY
42     #define XMLTOOL_EXPORT __attribute__ ((visibility("default")))
43     #define XMLTOOL_DLLLOCAL __attribute__ ((visibility("hidden")))
44     #define XMLTOOL_DLLPUBLIC __attribute__ ((visibility("default")))
45   #else
46     #define XMLTOOL_EXPORT
47     #define XMLTOOL_DLLLOCAL
48     #define XMLTOOL_DLLPUBLIC
49   #endif
50 #endif
51
52 // Define XMLTOOL_API for DLL builds
53 #ifdef XMLTOOLING_EXPORTS
54   #define XMLTOOL_API XMLTOOL_EXPORT
55 #else
56   #define XMLTOOL_API XMLTOOL_IMPORT
57 #endif
58
59 // Throwable classes must always be visible on GCC in all binaries
60 #ifdef WIN32
61   #define XMLTOOL_EXCEPTIONAPI(api) api
62 #elif defined(GCC_HASCLASSVISIBILITY)
63   #define XMLTOOL_EXCEPTIONAPI(api) XMLTOOL_EXPORT
64 #else
65   #define XMLTOOL_EXCEPTIONAPI(api)
66 #endif
67
68 #ifdef _MSC_VER
69     #define XMLTOOLING_DOXYGEN(desc) /##** desc */
70 #else
71     #define XMLTOOLING_DOXYGEN(desc)
72 #endif
73
74 /**
75  * Blocks copy c'tor and assignment operator for a class.
76  */
77 #define MAKE_NONCOPYABLE(type) \
78     private: \
79         type(const type&); \
80         type& operator=(const type&);
81
82 #ifndef DOXYGEN_SKIP
83 #ifndef NULL
84 #define NULL    0
85 #endif
86 #define UNICODE_LITERAL_1(a) {chLatin_##a, chNull}
87 #define UNICODE_LITERAL_2(a,b) {chLatin_##a, chLatin_##b, chNull}
88 #define UNICODE_LITERAL_3(a,b,c) {chLatin_##a, chLatin_##b, chLatin_##c, chNull}
89 #define UNICODE_LITERAL_4(a,b,c,d) {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chNull}
90 #define UNICODE_LITERAL_5(a,b,c,d,e) {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chNull}
91 #define UNICODE_LITERAL_6(a,b,c,d,e,f) {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chNull}
92 #define UNICODE_LITERAL_7(a,b,c,d,e,f,g) \
93     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chNull}
94 #define UNICODE_LITERAL_8(a,b,c,d,e,f,g,h) \
95     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chNull}
96 #define UNICODE_LITERAL_9(a,b,c,d,e,f,g,h,i) \
97     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, chNull}
98 #define UNICODE_LITERAL_10(a,b,c,d,e,f,g,h,i,j) \
99     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
100         chLatin_##j, chNull}
101 #define UNICODE_LITERAL_11(a,b,c,d,e,f,g,h,i,j,k) \
102     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
103         chLatin_##j, chLatin_##k, chNull}
104 #define UNICODE_LITERAL_12(a,b,c,d,e,f,g,h,i,j,k,l) \
105     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
106         chLatin_##j, chLatin_##k, chLatin_##l, chNull}
107 #define UNICODE_LITERAL_13(a,b,c,d,e,f,g,h,i,j,k,l,m) \
108     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
109         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chNull}
110 #define UNICODE_LITERAL_14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
111     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
112         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chNull}
113 #define UNICODE_LITERAL_15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
114     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
115         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chNull}
116 #define UNICODE_LITERAL_16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
117     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
118         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chNull}
119 #define UNICODE_LITERAL_17(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) \
120     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
121         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chNull}
122 #define UNICODE_LITERAL_18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) \
123     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
124         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, chNull}
125 #define UNICODE_LITERAL_19(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) \
126     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
127         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
128         chLatin_##s, chNull}
129 #define UNICODE_LITERAL_20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) \
130     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
131         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
132         chLatin_##s, chLatin_##t, chNull}
133 #define UNICODE_LITERAL_21(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u) \
134     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
135         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
136         chLatin_##s, chLatin_##t, chLatin_##u, chNull}
137 #define UNICODE_LITERAL_22(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v) \
138     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
139         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
140         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chNull}
141 #define UNICODE_LITERAL_23(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w) \
142     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
143         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
144         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chNull}
145 #define UNICODE_LITERAL_24(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x) \
146     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
147         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
148         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chNull}
149 #define UNICODE_LITERAL_25(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y) \
150     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
151         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
152         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chNull}
153 #define UNICODE_LITERAL_26(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) \
154     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
155         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
156         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, chNull}
157 #endif /* DOXYGEN_SKIP */
158
159 /**
160  * Begins the declaration of an XMLObject specialization.
161  * Basic boilerplate includes a protected constructor, empty virtual destructor,
162  * and Unicode constants for the default associated element's name and prefix.
163  * 
164  * @param linkage   linkage specifier for the class
165  * @param cname     the name of the class to declare
166  * @param base      the base class to derive from using public virtual inheritance
167  * @param desc      documentation comment for class
168  */
169 #define BEGIN_XMLOBJECT(linkage,cname,base,desc) \
170     XMLTOOLING_DOXYGEN(desc) \
171     class linkage cname : public virtual base, public virtual xmltooling::ValidatingXMLObject { \
172     protected: \
173         cname() {} \
174     public: \
175         virtual ~cname() {} \
176         XMLTOOLING_DOXYGEN(Type-specific clone method.) \
177         virtual cname* clone##cname() const=0; \
178         XMLTOOLING_DOXYGEN(Element local name) \
179         static const XMLCh LOCAL_NAME[]
180
181 /**
182  * Ends the declaration of an XMLObject specialization.
183  */
184 #define END_XMLOBJECT }
185
186 /**
187  * Declares abstract get/set methods for a named XML attribute.
188  * 
189  * @param proper    the proper name of the attribute
190  * @param upcased   the upcased name of the attribute
191  */
192 #define DECL_XMLOBJECT_ATTRIB(proper,upcased) \
193     public: \
194         XMLTOOLING_DOXYGEN(proper attribute name) \
195         static const XMLCh upcased##_ATTRIB_NAME[]; \
196         XMLTOOLING_DOXYGEN(Returns the proper attribute.) \
197         virtual const XMLCh* get##proper() const=0; \
198         XMLTOOLING_DOXYGEN(Sets the proper attribute.) \
199         virtual void set##proper(const XMLCh* proper)=0
200
201 /**
202  * Implements get/set methods and a private member for a named XML attribute.
203  * 
204  * @param proper    the proper name of the attribute
205  */
206 #define IMPL_XMLOBJECT_ATTRIB(proper) \
207     private: \
208         XMLCh* m_##proper; \
209     public: \
210         const XMLCh* get##proper() const { \
211             return m_##proper; \
212         } \
213         void set##proper(const XMLCh* proper) { \
214             m_##proper = prepareForAssignment(m_##proper,proper); \
215         }
216
217 /**
218  * Declares abstract get/set methods for a typed XML child object.
219  * 
220  * @param proper    the proper name of the child type
221  */
222 #define DECL_XMLOBJECT_CHILD(proper) \
223     public: \
224         XMLTOOLING_DOXYGEN(Returns the proper child.) \
225         virtual proper* get##proper() const=0; \
226         XMLTOOLING_DOXYGEN(Sets the proper child.) \
227         virtual void set##proper(proper* child)=0
228
229 /**
230  * Implements get/set methods and a private list iterator member for a typed XML child object.
231  * 
232  * @param proper    the proper name of the child type
233  */
234 #define IMPL_XMLOBJECT_CHILD(proper) \
235     private: \
236         proper* m_##proper; \
237         std::list<XMLObject*>::iterator m_pos_##proper; \
238     public: \
239         proper* get##proper() const { \
240             return m_##proper; \
241         } \
242         void set##proper(proper* child) { \
243             prepareForAssignment(m_##proper,child); \
244             *m_pos_##proper = m_##proper = child; \
245         }
246
247 /**
248  * Declares abstract get/set methods for a typed XML child collection.
249  * 
250  * @param proper    the proper name of the child type
251  */
252 #define DECL_XMLOBJECT_CHILDREN(proper) \
253     public: \
254         XMLTOOLING_DOXYGEN(Returns modifiable proper collection.) \
255         virtual VectorOf(proper) get##proper##s()=0; \
256         XMLTOOLING_DOXYGEN(Returns reference to immutable proper collection.) \
257         virtual const std::vector<proper*>& get##proper##s() const=0
258
259 /**
260  * Implements get method and a private vector member for a typed XML child collection.
261  * 
262  * @param proper    the proper name of the child type
263  * @param fence     insertion fence for new objects of the child collection in backing list
264  */
265 #define IMPL_XMLOBJECT_CHILDREN(proper,fence) \
266     private: \
267         std::vector<proper*> m_##proper##s; \
268     public: \
269         VectorOf(proper) get##proper##s() { \
270             return VectorOf(proper)(this, m_##proper##s, &m_children, fence); \
271         } \
272         const std::vector<proper*>& get##proper##s() const { \
273             return m_##proper##s; \
274         } 
275
276 /**
277  * Implements marshalling for an attribute
278  * 
279  * @param proper        the proper name of the attribute
280  * @param ucase         the upcased name of the attribute
281  * @param namespaceURI  the XML namespace of the attribute
282  */
283 #define MARSHALL_XMLOBJECT_ATTRIB(proper,ucase,namespaceURI) \
284     if(get##proper()) { \
285         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, get##proper()); \
286     }
287
288 /**
289  * Implements marshalling for an ID attribute
290  * 
291  * @param proper        the proper name of the attribute
292  * @param ucase         the upcased name of the attribute
293  * @param namespaceURI  the XML namespace of the attribute
294  */
295 #define MARSHALL_XMLOBJECT_ID_ATTRIB(proper,ucase,namespaceURI) \
296     if(get##proper()) { \
297         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, get##proper()); \
298         domElement->setIdAttributeNS(namespaceURI, ucase##_ATTRIB_NAME); \
299     }
300
301 /**
302  * Implements unmarshalling process branch for an attribute
303  * 
304  * @param proper        the proper name of the attribute
305  * @param ucase         the upcased name of the attribute
306  * @param namespaceURI  the XML namespace of the attribute
307  */
308 #define PROC_XMLOBJECT_ATTRIB(proper,ucase,namespaceURI) \
309     if (xmltooling::XMLHelper::isNodeNamed(attribute, namespaceURI, ucase##_ATTRIB_NAME)) { \
310         set##proper(attribute->getValue()); \
311         return; \
312     }
313
314 /**
315  * Implements unmarshalling process branch for an ID attribute
316  * 
317  * @param proper        the proper name of the attribute
318  * @param ucase         the upcased name of the attribute
319  * @param namespaceURI  the XML namespace of the attribute
320  */
321 #define PROC_XMLOBJECT_ID_ATTRIB(proper,ucase,namespaceURI) \
322     if (xmltooling::XMLHelper::isNodeNamed(attribute, namespaceURI, ucase##_ATTRIB_NAME)) { \
323         set##proper(attribute->getValue()); \
324         static_cast<DOMElement*>(attribute->getParentNode())->setIdAttributeNode(attribute); \
325         return; \
326     }
327
328 /**
329  * Implements unmarshalling process branch for typed child collection element
330  * 
331  * @param proper        the proper name of the child type
332  * @param namespaceURI  the XML namespace of the child element
333  */
334 #define PROC_XMLOBJECT_CHILDREN(proper,namespaceURI) \
335     if (xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,proper::LOCAL_NAME)) { \
336         proper* typesafe=dynamic_cast<proper*>(childXMLObject); \
337         if (typesafe) { \
338             get##proper##s().push_back(typesafe); \
339             return; \
340         } \
341     }
342
343 /**
344  * Implements unmarshalling process branch for typed child singleton element
345  * 
346  * @param proper        the proper name of the child type
347  * @param namespaceURI  the XML namespace of the child element
348  */
349 #define PROC_XMLOBJECT_CHILD(proper,namespaceURI) \
350     if (xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,proper::LOCAL_NAME)) { \
351         proper* typesafe=dynamic_cast<proper*>(childXMLObject); \
352         if (typesafe) { \
353             set##proper(typesafe); \
354             return; \
355         } \
356     }
357
358 /**
359  * Declares aliased get/set methods for named XML element content.
360  * 
361  * @param proper    the proper name to label the element's content
362  */
363 #define DECL_XMLOBJECT_CONTENT(proper) \
364     XMLTOOLING_DOXYGEN(Returns proper.) \
365     const XMLCh* get##proper() const { \
366         return getTextContent(); \
367     } \
368     XMLTOOLING_DOXYGEN(Sets or clears proper.) \
369     void set##proper(const XMLCh* proper) { \
370         setTextContent(proper); \
371     }
372
373 /**
374  * Implements marshalling/unmarshalling for element content.
375  */
376 #define IMPL_XMLOBJECT_CONTENT \
377     protected: \
378         void marshallElementContent(DOMElement* domElement) const { \
379             if(getTextContent()) { \
380                 domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent())); \
381             } \
382         } \
383         void processElementContent(const XMLCh* elementContent) { \
384             setTextContent(elementContent); \
385         }
386
387
388 /**
389  * Implements cloning methods for an XMLObject specialization implementation class.
390  * 
391  * @param cname    the name of the XMLObject specialization
392  */
393 #define IMPL_XMLOBJECT_CLONE(cname) \
394     cname* clone##cname() const { \
395         return clone(); \
396     } \
397     cname* clone() const { \
398         std::auto_ptr<xmltooling::XMLObject> domClone(xmltooling::AbstractDOMCachingXMLObject::clone()); \
399         cname##Impl* ret=dynamic_cast<cname##Impl*>(domClone.get()); \
400         if (ret) { \
401             domClone.release(); \
402             return ret; \
403         } \
404         return new cname##Impl(*this); \
405     }
406
407 /**
408  * Declares an XMLObject specialization with a simple content model and type,
409  * handling it as string data.
410  * 
411  * @param linkage   linkage specifier for the class
412  * @param cname     the name of the XMLObject specialization
413  * @param proper    the proper name to label the element's content
414  * @param desc      documentation for class
415  */
416 #define DECL_XMLOBJECT_SIMPLE(linkage,cname,proper,desc) \
417     BEGIN_XMLOBJECT(linkage,cname,xmltooling::SimpleElement,desc); \
418         DECL_XMLOBJECT_CONTENT(proper); \
419     END_XMLOBJECT
420
421 /**
422  * Declares and defines an implementation class for an XMLObject with
423  * a simple content model and type, handling it as string data.
424  * 
425  * @param linkage   linkage specifier for the class
426  * @param cname     the name of the XMLObject specialization
427  */
428 #define DECL_XMLOBJECTIMPL_SIMPLE(linkage,cname) \
429     class linkage cname##Impl \
430         : public cname, \
431             public xmltooling::AbstractSimpleElement, \
432             public xmltooling::AbstractChildlessElement, \
433             public xmltooling::AbstractDOMCachingXMLObject, \
434             public xmltooling::AbstractValidatingXMLObject, \
435             public xmltooling::AbstractXMLObjectMarshaller, \
436             public xmltooling::AbstractXMLObjectUnmarshaller \
437     { \
438     public: \
439         virtual ~cname##Impl() {} \
440         cname##Impl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) \
441             : xmltooling::AbstractXMLObject(nsURI, localName, prefix, schemaType) { \
442         } \
443         cname##Impl(const cname##Impl& src) \
444             : xmltooling::AbstractXMLObject(src), \
445                 xmltooling::AbstractSimpleElement(src), \
446                 xmltooling::AbstractDOMCachingXMLObject(src), \
447                 xmltooling::AbstractValidatingXMLObject(src) {} \
448         IMPL_XMLOBJECT_CLONE(cname) \
449         IMPL_XMLOBJECT_CONTENT \
450     }
451     
452 /**
453  * Begins the declaration of an XMLObjectBuilder specialization.
454  * Basic boilerplate includes an empty virtual destructor, and
455  * a default builder that defaults the element name.
456  * 
457  * @param linkage           linkage specifier for the class
458  * @param cname             the name of the XMLObject specialization
459  * @param namespaceURI      the XML namespace of the default associated element
460  * @param namespacePrefix   the XML namespace prefix of the default associated element
461  */
462 #define BEGIN_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix) \
463     XMLTOOLING_DOXYGEN(Builder for cname objects.) \
464     class linkage cname##Builder : public xmltooling::XMLObjectBuilder { \
465     public: \
466         virtual ~cname##Builder() {} \
467         XMLTOOLING_DOXYGEN(Default builder.) \
468         virtual cname* buildObject() const { \
469             return buildObject(namespaceURI,cname::LOCAL_NAME,namespacePrefix); \
470         } \
471         virtual cname* buildObject( \
472             const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const xmltooling::QName* schemaType=NULL \
473             ) const
474
475 /**
476  * Ends the declaration of an XMLObjectBuilder specialization.
477  */
478 #define END_XMLOBJECTBUILDER }
479
480 /**
481  * Declares a generic XMLObjectBuilder specialization.
482  * 
483  * @param linkage           linkage specifier for the class
484  * @param cname             the name of the XMLObject specialization
485  * @param namespaceURI      the XML namespace of the default associated element
486  * @param namespacePrefix   the XML namespace prefix of the default associated element
487  */
488  #define DECL_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix) \
489     BEGIN_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix); \
490     XMLTOOLING_DOXYGEN(Singleton builder.) \
491     static cname* new##cname() { \
492         const cname##Builder* b = dynamic_cast<const cname##Builder*>( \
493             XMLObjectBuilder::getBuilder(xmltooling::QName(namespaceURI,cname::LOCAL_NAME)) \
494             ); \
495         if (b) \
496             return b->buildObject(); \
497         throw xmltooling::XMLObjectException("Unable to obtain typed builder for "#cname"."); \
498     } \
499     END_XMLOBJECTBUILDER
500
501 /**
502  * Implements the standard XMLObjectBuilder specialization function. 
503  * 
504  * @param cname the name of the XMLObject specialization
505  */
506 #define IMPL_XMLOBJECTBUILDER(cname) \
507     cname* cname##Builder::buildObject( \
508         const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType \
509         ) const \
510     { \
511         return new cname##Impl(nsURI,localName,prefix,schemaType); \
512     }
513
514 /**
515  * Begins the declaration of a Schema Validator specialization.
516  * 
517  * @param linkage           linkage specifier for the class
518  * @param cname the base name of the Validator specialization
519  */
520  #define BEGIN_XMLOBJECTVALIDATOR(linkage,cname) \
521     class linkage cname##SchemaValidator : public xmltooling::Validator \
522     { \
523     public: \
524         virtual ~cname##SchemaValidator() {} \
525         virtual cname##SchemaValidator* clone() const { \
526             return new cname##SchemaValidator(); \
527         } \
528         virtual void validate(const xmltooling::XMLObject* xmlObject) const { \
529             const cname* ptr=dynamic_cast<const cname*>(xmlObject); \
530             if (!ptr) \
531                 throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()))
532
533 /**
534  * Ends the declaration of a Validator specialization.
535  */
536 #define END_XMLOBJECTVALIDATOR } }
537
538 /**
539  * Validator code that checks the object type.
540  * 
541  * @param cname     the name of the XMLObject specialization
542  */
543 #define XMLOBJECTVALIDATOR_CHECKTYPE(cname) \
544     const cname* ptr=dynamic_cast<const cname*>(xmlObject); \
545     if (!ptr) \
546         throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()))
547
548 /**
549  * Validator code that checks for a required attribute, content, or singleton.
550  * 
551  * @param cname     the name of the XMLObject specialization
552  * @param proper    the proper name of the attribute, content, or singleton member 
553  */
554 #define XMLOBJECTVALIDATOR_REQUIRE(cname,proper) \
555     if (!ptr->get##proper()) \
556         throw xmltooling::ValidationException(#cname" must have "#proper".")
557
558 /**
559  * Validator code that checks for one of a pair of
560  * required attributes, content, or singletons.
561  * 
562  * @param cname     the name of the XMLObject specialization
563  * @param proper1   the proper name of the first attribute, content, or singleton member 
564  * @param proper2   the proper name of the second attribute, content, or singleton member 
565  */
566 #define XMLOBJECTVALIDATOR_ONEOF(cname,proper1,proper2) \
567     if (!ptr->get##proper1() && !ptr->get##proper2()) \
568         throw xmltooling::ValidationException(#cname" must have "#proper1" or "#proper2".")
569
570 /**
571  * Validator code that checks for one of a set of three
572  * required attributes, content, or singletons.
573  * 
574  * @param cname     the name of the XMLObject specialization
575  * @param proper1   the proper name of the first attribute, content, or singleton member
576  * @param proper2   the proper name of the second attribute, content, or singleton member
577  * @param proper3   the proper name of the third attribute, content, or singleton member
578  */
579 #define XMLOBJECTVALIDATOR_ONEOF3(cname,proper1,proper2,proper3) \
580     if (!ptr->get##proper1() && !ptr->get##proper2() && !ptr->get##proper3()) \
581         throw xmltooling::ValidationException(#cname" must have "#proper1", "#proper2", or "#proper3".")
582
583 /**
584  * Validator code that checks a co-constraint (if one present, the other must be)
585  * between a pair of attributes, content, or singletons.
586  * 
587  * @param cname     the name of the XMLObject specialization
588  * @param proper1   the proper name of the first attribute, content, or singleton member 
589  * @param proper2   the proper name of the second attribute, content, or singleton member 
590  */
591 #define XMLOBJECTVALIDATOR_NONEORBOTH(cname,proper1,proper2) \
592     if ((ptr->get##proper1() && !ptr->get##proper2()) || (!ptr->get##proper1() && ptr->get##proper2())) \
593         throw xmltooling::ValidationException(#cname" cannot have "#proper1" without "#proper2".")
594
595 /**
596  * Validator code that checks for a non-empty collection.
597  * 
598  * @param cname     the name of the XMLObject specialization
599  * @param proper    the proper name of the collection item 
600  */
601 #define XMLOBJECTVALIDATOR_NONEMPTY(cname,proper) \
602     if (ptr->get##proper##s().empty()) \
603         throw xmltooling::ValidationException(#cname" must have at least one "#proper".")
604
605 /**
606  * Declares/defines a Validator specialization that checks object type and
607  * a non-empty simple content model.
608  * 
609  * @param linkage   linkage specifier for the class
610  * @param cname     the name of the XMLObject specialization
611  */
612 #define XMLOBJECTVALIDATOR_SIMPLE(linkage,cname) \
613     BEGIN_XMLOBJECTVALIDATOR(linkage,cname); \
614         XMLOBJECTVALIDATOR_REQUIRE(cname,TextContent); \
615     END_XMLOBJECTVALIDATOR
616
617 #include <utility>
618
619 /**
620  * @namespace xmltooling
621  * Public namespace of XML Tooling library
622  */
623 namespace xmltooling {
624
625     /**
626      * Template function for cloning a sequence of XMLObjects.
627      * Invokes the clone() member on each element of the input sequence and adds the copy to
628      * the output sequence. Order is preserved.
629      * 
630      * @param in    input sequence to clone
631      * @param out   output sequence to copy cloned pointers into
632      */
633     template<class InputSequence,class OutputSequence> void clone(const InputSequence& in, OutputSequence& out) {
634         for (typename InputSequence::const_iterator i=in.begin(); i!=in.end(); i++) {
635             if (*i)
636                 out.push_back((*i)->clone());
637             else
638                 out.push_back(*i);
639         }
640     }
641
642     /**
643      * Functor for cleaning up heap objects in containers.
644      */
645     template<class T> struct cleanup
646     {
647         /**
648          * Function operator to delete an object.
649          * 
650          * @param ptr   object to delete
651          */
652         void operator()(T* ptr) {delete ptr;}
653         
654         /**
655          * Function operator to delete an object stored as const.
656          * 
657          * @param ptr   object to delete after casting away const
658          */
659         void operator()(const T* ptr) {delete const_cast<T*>(ptr);}
660     };
661
662     /**
663      * Functor for cleaning up heap objects in key/value containers.
664      */
665     template<class A,class B> struct cleanup_pair
666     {
667         /**
668          * Function operator to delete an object.
669          * 
670          * @param p   a pair in which the second component is the object to delete
671          */
672         void operator()(const std::pair<A,B*>& p) {delete p.second;}
673     };
674 };
675
676 #endif /* __xmltooling_base_h__ */