Tighten up validator namespace checking, rework registration.
[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 #define UNICODE_LITERAL_27(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,aa) \
158     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
159         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
160         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, \
161         chLatin_##aa, chNull}
162 #define UNICODE_LITERAL_28(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,aa,bb) \
163     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
164         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
165         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, \
166         chLatin_##aa, chLatin_##bb, chNull}
167 #define UNICODE_LITERAL_29(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,aa,bb,cc) \
168     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
169         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
170         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, \
171         chLatin_##aa, chLatin_##bb, chLatin_##cc, chNull}
172 #define UNICODE_LITERAL_30(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,aa,bb,cc,dd) \
173     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
174         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
175         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, \
176         chLatin_##aa, chLatin_##bb, chLatin_##cc, chLatin_##dd, chNull}
177 #define UNICODE_LITERAL_31(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,aa,bb,cc,dd,ee) \
178     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
179         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
180         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, \
181         chLatin_##aa, chLatin_##bb, chLatin_##cc, chLatin_##dd, chLatin_##ee, chNull}
182 #define UNICODE_LITERAL_32(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,aa,bb,cc,dd,ee,ff) \
183     {chLatin_##a, chLatin_##b, chLatin_##c, chLatin_##d, chLatin_##e, chLatin_##f, chLatin_##g, chLatin_##h, chLatin_##i, \
184         chLatin_##j, chLatin_##k, chLatin_##l, chLatin_##m, chLatin_##n, chLatin_##o, chLatin_##p, chLatin_##q, chLatin_##r, \
185         chLatin_##s, chLatin_##t, chLatin_##u, chLatin_##v, chLatin_##w, chLatin_##x, chLatin_##y, chLatin_##z, \
186         chLatin_##aa, chLatin_##bb, chLatin_##cc, chLatin_##dd, chLatin_##ee, chLatin_##ff, chNull}
187 #endif /* DOXYGEN_SKIP */
188
189 /**
190  * Begins the declaration of an XMLObject specialization for an abstract element/type.
191  * Basic boilerplate includes a protected constructor, empty virtual destructor,
192  * and Unicode constants for the default associated element's name and prefix.
193  * 
194  * @param linkage   linkage specifier for the class
195  * @param cname     the name of the class to declare
196  * @param base      the base class to derive from using public virtual inheritance
197  * @param desc      documentation comment for class
198  */
199 #define DECL_XMLOBJECT_ABSTRACT(linkage,cname,base,desc) \
200     XMLTOOLING_DOXYGEN(desc) \
201     class linkage cname : public virtual base { \
202     protected: \
203         cname() {} \
204     public: \
205         virtual ~cname() {} \
206         XMLTOOLING_DOXYGEN(Element local name) \
207         static const XMLCh LOCAL_NAME[]; \
208     }
209
210 /**
211  * Begins the declaration of an XMLObject specialization.
212  * Basic boilerplate includes a protected constructor, empty virtual destructor,
213  * and Unicode constants for the default associated element's name and prefix.
214  * 
215  * @param linkage   linkage specifier for the class
216  * @param cname     the name of the class to declare
217  * @param base      the base class to derive from using public virtual inheritance
218  * @param desc      documentation comment for class
219  */
220 #define BEGIN_XMLOBJECT(linkage,cname,base,desc) \
221     XMLTOOLING_DOXYGEN(desc) \
222     class linkage cname : public virtual base, public virtual xmltooling::ValidatingXMLObject { \
223     protected: \
224         cname() {} \
225     public: \
226         virtual ~cname() {} \
227         XMLTOOLING_DOXYGEN(Type-specific clone method.) \
228         virtual cname* clone##cname() const=0; \
229         XMLTOOLING_DOXYGEN(Element local name) \
230         static const XMLCh LOCAL_NAME[]
231
232 /**
233  * Ends the declaration of an XMLObject specialization.
234  */
235 #define END_XMLOBJECT }
236
237 /**
238  * Declares abstract get/set methods for a named XML attribute.
239  * 
240  * @param proper    the proper name of the attribute
241  * @param upcased   the upcased name of the attribute
242  */
243 #define DECL_XMLOBJECT_ATTRIB(proper,upcased) \
244     public: \
245         XMLTOOLING_DOXYGEN(proper attribute name) \
246         static const XMLCh upcased##_ATTRIB_NAME[]; \
247         XMLTOOLING_DOXYGEN(Returns the proper attribute.) \
248         virtual const XMLCh* get##proper() const=0; \
249         XMLTOOLING_DOXYGEN(Sets the proper attribute.) \
250         virtual void set##proper(const XMLCh* proper)=0
251
252 /**
253  * Implements get/set methods and a private member for a named XML attribute.
254  * 
255  * @param proper    the proper name of the attribute
256  */
257 #define IMPL_XMLOBJECT_ATTRIB(proper) \
258     private: \
259         XMLCh* m_##proper; \
260     public: \
261         const XMLCh* get##proper() const { \
262             return m_##proper; \
263         } \
264         void set##proper(const XMLCh* proper) { \
265             m_##proper = prepareForAssignment(m_##proper,proper); \
266         }
267
268 /**
269  * Declares abstract get/set methods for a typed XML child object.
270  * 
271  * @param proper    the proper name of the child type
272  */
273 #define DECL_XMLOBJECT_CHILD(proper) \
274     public: \
275         XMLTOOLING_DOXYGEN(Returns the proper child.) \
276         virtual proper* get##proper() const=0; \
277         XMLTOOLING_DOXYGEN(Sets the proper child.) \
278         virtual void set##proper(proper* child)=0
279
280 /**
281  * Implements get/set methods and a private list iterator member for a typed XML child object.
282  * 
283  * @param proper    the proper name of the child type
284  */
285 #define IMPL_XMLOBJECT_CHILD(proper) \
286     private: \
287         proper* m_##proper; \
288         std::list<XMLObject*>::iterator m_pos_##proper; \
289     public: \
290         proper* get##proper() const { \
291             return m_##proper; \
292         } \
293         void set##proper(proper* child) { \
294             prepareForAssignment(m_##proper,child); \
295             *m_pos_##proper = m_##proper = child; \
296         }
297
298 /**
299  * Declares abstract get/set methods for a typed XML child collection.
300  * 
301  * @param proper    the proper name of the child type
302  */
303 #define DECL_XMLOBJECT_CHILDREN(proper) \
304     public: \
305         XMLTOOLING_DOXYGEN(Returns modifiable proper collection.) \
306         virtual VectorOf(proper) get##proper##s()=0; \
307         XMLTOOLING_DOXYGEN(Returns reference to immutable proper collection.) \
308         virtual const std::vector<proper*>& get##proper##s() const=0
309
310 /**
311  * Implements get method and a private vector member for a typed XML child collection.
312  * 
313  * @param proper    the proper name of the child type
314  * @param fence     insertion fence for new objects of the child collection in backing list
315  */
316 #define IMPL_XMLOBJECT_CHILDREN(proper,fence) \
317     private: \
318         std::vector<proper*> m_##proper##s; \
319     public: \
320         VectorOf(proper) get##proper##s() { \
321             return VectorOf(proper)(this, m_##proper##s, &m_children, fence); \
322         } \
323         const std::vector<proper*>& get##proper##s() const { \
324             return m_##proper##s; \
325         } 
326
327 /**
328  * Implements marshalling for an attribute
329  * 
330  * @param proper        the proper name of the attribute
331  * @param ucase         the upcased name of the attribute
332  * @param namespaceURI  the XML namespace of the attribute
333  */
334 #define MARSHALL_XMLOBJECT_ATTRIB(proper,ucase,namespaceURI) \
335     if(get##proper()) { \
336         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, get##proper()); \
337     }
338
339 /**
340  * Implements marshalling for an ID attribute
341  * 
342  * @param proper        the proper name of the attribute
343  * @param ucase         the upcased name of the attribute
344  * @param namespaceURI  the XML namespace of the attribute
345  */
346 #define MARSHALL_XMLOBJECT_ID_ATTRIB(proper,ucase,namespaceURI) \
347     if(get##proper()) { \
348         domElement->setAttributeNS(namespaceURI, ucase##_ATTRIB_NAME, get##proper()); \
349         domElement->setIdAttributeNS(namespaceURI, ucase##_ATTRIB_NAME); \
350     }
351
352 /**
353  * Implements unmarshalling process branch for an attribute
354  * 
355  * @param proper        the proper name of the attribute
356  * @param ucase         the upcased name of the attribute
357  * @param namespaceURI  the XML namespace of the attribute
358  */
359 #define PROC_XMLOBJECT_ATTRIB(proper,ucase,namespaceURI) \
360     if (xmltooling::XMLHelper::isNodeNamed(attribute, namespaceURI, ucase##_ATTRIB_NAME)) { \
361         set##proper(attribute->getValue()); \
362         return; \
363     }
364
365 /**
366  * Implements unmarshalling process branch for an ID attribute
367  * 
368  * @param proper        the proper name of the attribute
369  * @param ucase         the upcased name of the attribute
370  * @param namespaceURI  the XML namespace of the attribute
371  */
372 #define PROC_XMLOBJECT_ID_ATTRIB(proper,ucase,namespaceURI) \
373     if (xmltooling::XMLHelper::isNodeNamed(attribute, namespaceURI, ucase##_ATTRIB_NAME)) { \
374         set##proper(attribute->getValue()); \
375         static_cast<DOMElement*>(attribute->getParentNode())->setIdAttributeNode(attribute); \
376         return; \
377     }
378
379 /**
380  * Implements unmarshalling process branch for typed child collection element
381  * 
382  * @param proper        the proper name of the child type
383  * @param namespaceURI  the XML namespace of the child element
384  */
385 #define PROC_XMLOBJECT_CHILDREN(proper,namespaceURI) \
386     if (xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,proper::LOCAL_NAME)) { \
387         proper* typesafe=dynamic_cast<proper*>(childXMLObject); \
388         if (typesafe) { \
389             get##proper##s().push_back(typesafe); \
390             return; \
391         } \
392     }
393
394 /**
395  * Implements unmarshalling process branch for typed child singleton element
396  * 
397  * @param proper        the proper name of the child type
398  * @param namespaceURI  the XML namespace of the child element
399  */
400 #define PROC_XMLOBJECT_CHILD(proper,namespaceURI) \
401     if (xmltooling::XMLHelper::isNodeNamed(root,namespaceURI,proper::LOCAL_NAME)) { \
402         proper* typesafe=dynamic_cast<proper*>(childXMLObject); \
403         if (typesafe) { \
404             set##proper(typesafe); \
405             return; \
406         } \
407     }
408
409 /**
410  * Declares aliased get/set methods for named XML element content.
411  * 
412  * @param proper    the proper name to label the element's content
413  */
414 #define DECL_XMLOBJECT_CONTENT(proper) \
415     XMLTOOLING_DOXYGEN(Returns proper.) \
416     const XMLCh* get##proper() const { \
417         return getTextContent(); \
418     } \
419     XMLTOOLING_DOXYGEN(Sets or clears proper.) \
420     void set##proper(const XMLCh* proper) { \
421         setTextContent(proper); \
422     }
423
424 /**
425  * Implements marshalling/unmarshalling for element content.
426  */
427 #define IMPL_XMLOBJECT_CONTENT \
428     protected: \
429         void marshallElementContent(DOMElement* domElement) const { \
430             if(getTextContent()) { \
431                 domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent())); \
432             } \
433         } \
434         void processElementContent(const XMLCh* elementContent) { \
435             setTextContent(elementContent); \
436         }
437
438
439 /**
440  * Implements cloning methods for an XMLObject specialization implementation class.
441  * 
442  * @param cname    the name of the XMLObject specialization
443  */
444 #define IMPL_XMLOBJECT_CLONE(cname) \
445     cname* clone##cname() const { \
446         return clone(); \
447     } \
448     cname* clone() const { \
449         std::auto_ptr<xmltooling::XMLObject> domClone(xmltooling::AbstractDOMCachingXMLObject::clone()); \
450         cname##Impl* ret=dynamic_cast<cname##Impl*>(domClone.get()); \
451         if (ret) { \
452             domClone.release(); \
453             return ret; \
454         } \
455         return new cname##Impl(*this); \
456     }
457
458 /**
459  * Declares an XMLObject specialization with a simple content model and type,
460  * handling it as string data.
461  * 
462  * @param linkage   linkage specifier for the class
463  * @param cname     the name of the XMLObject specialization
464  * @param proper    the proper name to label the element's content
465  * @param desc      documentation for class
466  */
467 #define DECL_XMLOBJECT_SIMPLE(linkage,cname,proper,desc) \
468     BEGIN_XMLOBJECT(linkage,cname,xmltooling::SimpleElement,desc); \
469         DECL_XMLOBJECT_CONTENT(proper); \
470     END_XMLOBJECT
471
472 /**
473  * Declares and defines an implementation class for an XMLObject with
474  * a simple content model and type, handling it as string data.
475  * 
476  * @param linkage   linkage specifier for the class
477  * @param cname     the name of the XMLObject specialization
478  */
479 #define DECL_XMLOBJECTIMPL_SIMPLE(linkage,cname) \
480     class linkage cname##Impl \
481         : public cname, \
482             public xmltooling::AbstractSimpleElement, \
483             public xmltooling::AbstractChildlessElement, \
484             public xmltooling::AbstractDOMCachingXMLObject, \
485             public xmltooling::AbstractValidatingXMLObject, \
486             public xmltooling::AbstractXMLObjectMarshaller, \
487             public xmltooling::AbstractXMLObjectUnmarshaller \
488     { \
489     public: \
490         virtual ~cname##Impl() {} \
491         cname##Impl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) \
492             : xmltooling::AbstractXMLObject(nsURI, localName, prefix, schemaType) { \
493         } \
494         cname##Impl(const cname##Impl& src) \
495             : xmltooling::AbstractXMLObject(src), \
496                 xmltooling::AbstractSimpleElement(src), \
497                 xmltooling::AbstractDOMCachingXMLObject(src), \
498                 xmltooling::AbstractValidatingXMLObject(src) {} \
499         IMPL_XMLOBJECT_CLONE(cname) \
500         IMPL_XMLOBJECT_CONTENT \
501     }
502     
503 /**
504  * Begins the declaration of an XMLObjectBuilder specialization.
505  * Basic boilerplate includes an empty virtual destructor, and
506  * a default builder that defaults the element name.
507  * 
508  * @param linkage           linkage specifier for the class
509  * @param cname             the name of the XMLObject specialization
510  * @param namespaceURI      the XML namespace of the default associated element
511  * @param namespacePrefix   the XML namespace prefix of the default associated element
512  */
513 #define BEGIN_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix) \
514     XMLTOOLING_DOXYGEN(Builder for cname objects.) \
515     class linkage cname##Builder : public xmltooling::XMLObjectBuilder { \
516     public: \
517         virtual ~cname##Builder() {} \
518         XMLTOOLING_DOXYGEN(Default builder.) \
519         virtual cname* buildObject() const { \
520             return buildObject(namespaceURI,cname::LOCAL_NAME,namespacePrefix); \
521         } \
522         virtual cname* buildObject( \
523             const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const xmltooling::QName* schemaType=NULL \
524             ) const
525
526 /**
527  * Ends the declaration of an XMLObjectBuilder specialization.
528  */
529 #define END_XMLOBJECTBUILDER }
530
531 /**
532  * Declares a generic XMLObjectBuilder specialization.
533  * 
534  * @param linkage           linkage specifier for the class
535  * @param cname             the name of the XMLObject specialization
536  * @param namespaceURI      the XML namespace of the default associated element
537  * @param namespacePrefix   the XML namespace prefix of the default associated element
538  */
539  #define DECL_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix) \
540     BEGIN_XMLOBJECTBUILDER(linkage,cname,namespaceURI,namespacePrefix); \
541     XMLTOOLING_DOXYGEN(Singleton builder.) \
542     static cname* new##cname() { \
543         const cname##Builder* b = dynamic_cast<const cname##Builder*>( \
544             XMLObjectBuilder::getBuilder(xmltooling::QName(namespaceURI,cname::LOCAL_NAME)) \
545             ); \
546         if (b) \
547             return b->buildObject(); \
548         throw xmltooling::XMLObjectException("Unable to obtain typed builder for "#cname"."); \
549     } \
550     END_XMLOBJECTBUILDER
551
552 /**
553  * Implements the standard XMLObjectBuilder specialization function. 
554  * 
555  * @param cname the name of the XMLObject specialization
556  */
557 #define IMPL_XMLOBJECTBUILDER(cname) \
558     cname* cname##Builder::buildObject( \
559         const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType \
560         ) const \
561     { \
562         return new cname##Impl(nsURI,localName,prefix,schemaType); \
563     }
564
565 /**
566  * Begins the declaration of a Schema Validator specialization.
567  * 
568  * @param linkage           linkage specifier for the class
569  * @param cname the base name of the Validator specialization
570  */
571  #define BEGIN_XMLOBJECTVALIDATOR(linkage,cname) \
572     class linkage cname##SchemaValidator : public xmltooling::Validator \
573     { \
574     public: \
575         virtual ~cname##SchemaValidator() {} \
576         virtual cname##SchemaValidator* clone() const { \
577             return new cname##SchemaValidator(); \
578         } \
579         virtual void validate(const xmltooling::XMLObject* xmlObject) const { \
580             const cname* ptr=dynamic_cast<const cname*>(xmlObject); \
581             if (!ptr) \
582                 throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()))
583
584 /**
585  * Ends the declaration of a Validator specialization.
586  */
587 #define END_XMLOBJECTVALIDATOR } }
588
589 /**
590  * Validator code that checks the object type.
591  * 
592  * @param cname     the name of the XMLObject specialization
593  */
594 #define XMLOBJECTVALIDATOR_CHECKTYPE(cname) \
595     const cname* ptr=dynamic_cast<const cname*>(xmlObject); \
596     if (!ptr) \
597         throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name()))
598
599 /**
600  * Validator code that checks for a required attribute, content, or singleton.
601  * 
602  * @param cname     the name of the XMLObject specialization
603  * @param proper    the proper name of the attribute, content, or singleton member 
604  */
605 #define XMLOBJECTVALIDATOR_REQUIRE(cname,proper) \
606     if (!ptr->get##proper()) \
607         throw xmltooling::ValidationException(#cname" must have "#proper".")
608
609 /**
610  * Validator code that checks for one of a pair of
611  * required attributes, content, or singletons.
612  * 
613  * @param cname     the name of the XMLObject specialization
614  * @param proper1   the proper name of the first attribute, content, or singleton member 
615  * @param proper2   the proper name of the second attribute, content, or singleton member 
616  */
617 #define XMLOBJECTVALIDATOR_ONEOF(cname,proper1,proper2) \
618     if (!ptr->get##proper1() && !ptr->get##proper2()) \
619         throw xmltooling::ValidationException(#cname" must have "#proper1" or "#proper2".")
620
621 /**
622  * Validator code that checks for one of a set of three
623  * required attributes, content, or singletons.
624  * 
625  * @param cname     the name of the XMLObject specialization
626  * @param proper1   the proper name of the first attribute, content, or singleton member
627  * @param proper2   the proper name of the second attribute, content, or singleton member
628  * @param proper3   the proper name of the third attribute, content, or singleton member
629  */
630 #define XMLOBJECTVALIDATOR_ONEOF3(cname,proper1,proper2,proper3) \
631     if (!ptr->get##proper1() && !ptr->get##proper2() && !ptr->get##proper3()) \
632         throw xmltooling::ValidationException(#cname" must have "#proper1", "#proper2", or "#proper3".")
633
634 /**
635  * Validator code that checks a co-constraint (if one present, the other must be)
636  * between a pair of attributes, content, or singletons.
637  * 
638  * @param cname     the name of the XMLObject specialization
639  * @param proper1   the proper name of the first attribute, content, or singleton member 
640  * @param proper2   the proper name of the second attribute, content, or singleton member 
641  */
642 #define XMLOBJECTVALIDATOR_NONEORBOTH(cname,proper1,proper2) \
643     if ((ptr->get##proper1() && !ptr->get##proper2()) || (!ptr->get##proper1() && ptr->get##proper2())) \
644         throw xmltooling::ValidationException(#cname" cannot have "#proper1" without "#proper2".")
645
646 /**
647  * Validator code that checks for a non-empty collection.
648  * 
649  * @param cname     the name of the XMLObject specialization
650  * @param proper    the proper name of the collection item 
651  */
652 #define XMLOBJECTVALIDATOR_NONEMPTY(cname,proper) \
653     if (ptr->get##proper##s().empty()) \
654         throw xmltooling::ValidationException(#cname" must have at least one "#proper".")
655
656 /**
657  * Declares/defines a Validator specialization that checks object type and
658  * a non-empty simple content model.
659  * 
660  * @param linkage   linkage specifier for the class
661  * @param cname     the name of the XMLObject specialization
662  */
663 #define XMLOBJECTVALIDATOR_SIMPLE(linkage,cname) \
664     BEGIN_XMLOBJECTVALIDATOR(linkage,cname); \
665         XMLOBJECTVALIDATOR_REQUIRE(cname,TextContent); \
666     END_XMLOBJECTVALIDATOR
667
668 #include <utility>
669
670 /**
671  * @namespace xmltooling
672  * Public namespace of XML Tooling library
673  */
674 namespace xmltooling {
675
676     /**
677      * Template function for cloning a sequence of XMLObjects.
678      * Invokes the clone() member on each element of the input sequence and adds the copy to
679      * the output sequence. Order is preserved.
680      * 
681      * @param in    input sequence to clone
682      * @param out   output sequence to copy cloned pointers into
683      */
684     template<class InputSequence,class OutputSequence> void clone(const InputSequence& in, OutputSequence& out) {
685         for (typename InputSequence::const_iterator i=in.begin(); i!=in.end(); i++) {
686             if (*i)
687                 out.push_back((*i)->clone());
688             else
689                 out.push_back(*i);
690         }
691     }
692
693     /**
694      * Functor for cleaning up heap objects in containers.
695      */
696     template<class T> struct cleanup
697     {
698         /**
699          * Function operator to delete an object.
700          * 
701          * @param ptr   object to delete
702          */
703         void operator()(T* ptr) {delete ptr;}
704         
705         /**
706          * Function operator to delete an object stored as const.
707          * 
708          * @param ptr   object to delete after casting away const
709          */
710         void operator()(const T* ptr) {delete const_cast<T*>(ptr);}
711     };
712
713     /**
714      * Functor for cleaning up heap objects in key/value containers.
715      */
716     template<class A,class B> struct cleanup_pair
717     {
718         /**
719          * Function operator to delete an object.
720          * 
721          * @param p   a pair in which the second component is the object to delete
722          */
723         void operator()(const std::pair<A,B*>& p) {delete p.second;}
724     };
725 };
726
727 #endif /* __xmltooling_base_h__ */