Handle variant element names, merge in wildcard class, add test cases.
[shibboleth/cpp-xmltooling.git] / xmltooling / XMLObjectBuilder.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 XMLObjectBuilder.h
19  * 
20  * Factory interface for XMLObjects 
21  */
22
23 #if !defined(__xmltooling_xmlobjbuilder_h__)
24 #define __xmltooling_xmlobjbuilder_h__
25
26 #include <map>
27 #include <xmltooling/QName.h>
28 #include <xmltooling/XMLObject.h>
29
30 #if defined (_MSC_VER)
31     #pragma warning( push )
32     #pragma warning( disable : 4250 4251 )
33 #endif
34
35 namespace xmltooling {
36
37     /**
38      * A factory interface for obtaining XMLObjects.
39      * Subclasses MAY supply additional factory methods.
40      */
41     class XMLTOOL_API XMLObjectBuilder
42     {
43     MAKE_NONCOPYABLE(XMLObjectBuilder);
44     public:
45         virtual ~XMLObjectBuilder() {}
46         
47         /**
48          * Creates an empty XMLObject with a particular element name.
49          * 
50          * @param namespaceURI          namespace URI for element
51          * @param elementLocalName      local name of element
52          * @param namespacePrefix       prefix of element name
53          * @return the empty XMLObject
54          */
55         virtual XMLObject* buildObject(
56             const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL
57             ) const=0;
58
59         /**
60          * Creates an empty XMLObject with a defaulted element name.
61          * 
62          * @return the empty XMLObject
63          */
64         virtual XMLObject* buildObject() const {
65             return buildObject(NULL,NULL,NULL);
66         }
67
68         /**
69          * Creates an empty XMLObject with a particular element name.
70          * 
71          * @param q     QName of element for object
72          * @return the empty XMLObject
73          */
74         virtual XMLObject* buildObject(const QName& q) const {
75             return buildObject(q.getNamespaceURI(),q.getLocalPart(),q.getPrefix());
76         }
77
78         /**
79          * Creates an unmarshalled XMLObject from a DOM Element.
80          * 
81          * @param element       the unmarshalling source
82          * @param bindDocument  true iff the XMLObject should take ownership of the DOM Document
83          * @return the unmarshalled XMLObject
84          */
85         virtual XMLObject* buildFromElement(DOMElement* element, bool bindDocument=false) const {
86             std::auto_ptr<XMLObject> ret(buildObject(element->getNamespaceURI(),element->getLocalName(),element->getPrefix()));
87             ret->unmarshall(element,bindDocument);
88             return ret.release();
89         }
90
91         /**
92          * Creates an unmarshalled XMLObject from the root of a DOM Document.
93          * 
94          * @param doc           the unmarshalling source
95          * @param bindDocument  true iff the XMLObject should take ownership of the DOM Document
96          * @return the unmarshalled XMLObject
97          */
98         virtual XMLObject* buildFromDocument(DOMDocument* doc, bool bindDocument=true) const {
99             return buildFromElement(doc->getDocumentElement(),bindDocument);
100         }
101
102         /**
103          * Creates an empty XMLObject using the default build method, if a builder can be found.
104          * 
105          * @param key   the key used to locate a builder
106          * @return  the empty object or NULL if no builder is available 
107          */
108         static XMLObject* buildOne(const QName& key) {
109             const XMLObjectBuilder* b=getBuilder(key);
110             if (b)
111                 return b->buildObject();
112             b=getDefaultBuilder();
113             return b ? b->buildObject() : NULL;
114         }
115
116         /**
117          * Creates an unmarshalled XMLObject using the default build method, if a builder can be found.
118          * 
119          * @param element       the unmarshalling source
120          * @param bindDocument  true iff the new XMLObject should take ownership of the DOM Document
121          * @return  the unmarshalled object or NULL if no builder is available 
122          */
123         static XMLObject* buildOneFromElement(DOMElement* element, bool bindDocument=false) {
124             const XMLObjectBuilder* b=getBuilder(element);
125             return b ? b->buildFromElement(element,bindDocument) : NULL;
126         }
127
128         /**
129          * Retrieves an XMLObjectBuilder using the key it was registered with.
130          * 
131          * @param key the key used to register the builder
132          * @return the builder or NULL
133          */
134         static const XMLObjectBuilder* getBuilder(const QName& key) {
135             std::map<QName,XMLObjectBuilder*>::const_iterator i=m_map.find(key);
136             return (i==m_map.end()) ? NULL : i->second;
137         }
138
139         /**
140          * Retrieves an XMLObjectBuilder for a given DOM element.
141          * If no match is found, the default builder is returned, if any.
142          * 
143          * @param element the element for which to locate a builder
144          * @return the builder or NULL
145          */
146         static const XMLObjectBuilder* getBuilder(const DOMElement* element);
147
148         /**
149          * Retrieves the default XMLObjectBuilder for DOM elements
150          * 
151          * @return the default builder or NULL
152          */
153         static const XMLObjectBuilder* getDefaultBuilder() {
154             return m_default;
155         }
156
157         /**
158          * Gets an immutable list of all the builders currently registered.
159          * 
160          * @return list of all the builders currently registered
161          */
162         static const std::map<QName,XMLObjectBuilder*>& getBuilders() {
163             return m_map;
164         }
165     
166         /**
167          * Registers a new builder for the given key.
168          * 
169          * @param builderKey the key used to retrieve this builder later
170          * @param builder the builder
171          */
172         static void registerBuilder(const QName& builderKey, XMLObjectBuilder* builder) {
173             deregisterBuilder(builderKey);
174             m_map[builderKey]=builder;
175         }
176
177         /**
178          * Registers a default builder
179          * 
180          * @param builder the default builder
181          */
182         static void registerDefaultBuilder(XMLObjectBuilder* builder) {
183             deregisterDefaultBuilder();
184             m_default=builder;
185         }
186
187         /**
188          * Deregisters a builder.
189          * 
190          * @param builderKey the key for the builder to be deregistered
191          */
192         static void deregisterBuilder(const QName& builderKey) {
193             delete getBuilder(builderKey);
194             m_map.erase(builderKey);
195         }
196
197         /**
198          * Deregisters default builder.
199          */
200         static void deregisterDefaultBuilder() {
201             delete m_default;
202             m_default=NULL;
203         }
204
205         /**
206          * Unregisters and destroys all registered builders. 
207          */
208         static void destroyBuilders();
209
210     protected:
211         XMLObjectBuilder() {}
212     
213     private:
214         static std::map<QName,XMLObjectBuilder*> m_map;
215         static XMLObjectBuilder* m_default;
216     };
217
218 };
219
220 #if defined (_MSC_VER)
221     #pragma warning( pop )
222 #endif
223
224 #endif /* __xmltooling_xmlobjbuilder_h__ */