Revised builder API
[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          * The results are undefined if elementLocalName is NULL or empty.
50          * 
51          * @param namespaceURI          namespace URI for element
52          * @param elementLocalName      local name of element
53          * @param namespacePrefix       prefix of element name
54          * @return the empty XMLObject
55          */
56         virtual XMLObject* buildObject(
57             const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL
58             ) const=0;
59
60         /**
61          * Creates an empty XMLObject with a particular element name.
62          * 
63          * @param q     QName of element for object
64          * @return the empty XMLObject
65          */
66         XMLObject* buildFromQName(const QName& q) const {
67             return buildObject(q.getNamespaceURI(),q.getLocalPart(),q.getPrefix());
68         }
69
70         /**
71          * Creates an unmarshalled XMLObject from a DOM Element.
72          * 
73          * @param element       the unmarshalling source
74          * @param bindDocument  true iff the XMLObject should take ownership of the DOM Document
75          * @return the unmarshalled XMLObject
76          */
77         XMLObject* buildFromElement(DOMElement* element, bool bindDocument=false) const {
78             std::auto_ptr<XMLObject> ret(buildObject(element->getNamespaceURI(),element->getLocalName(),element->getPrefix()));
79             ret->unmarshall(element,bindDocument);
80             return ret.release();
81         }
82
83         /**
84          * Creates an unmarshalled XMLObject from the root of a DOM Document.
85          * 
86          * @param doc           the unmarshalling source
87          * @param bindDocument  true iff the XMLObject should take ownership of the DOM Document
88          * @return the unmarshalled XMLObject
89          */
90         XMLObject* buildFromDocument(DOMDocument* doc, bool bindDocument=true) const {
91             return buildFromElement(doc->getDocumentElement(),bindDocument);
92         }
93
94         /**
95          * Creates an empty XMLObject using the default build method, if a builder can be found.
96          * 
97          * @param key   the element key used to locate a builder
98          * @return  the empty object or NULL if no builder is available 
99          */
100         static XMLObject* buildOne(const QName& key) {
101             const XMLObjectBuilder* b=getBuilder(key);
102             if (b)
103                 return b->buildFromQName(key);
104             b=getDefaultBuilder();
105             return b ? b->buildFromQName(key) : NULL;
106         }
107
108         /**
109          * Creates an unmarshalled XMLObject using the default build method, if a builder can be found.
110          * 
111          * @param element       the unmarshalling source
112          * @param bindDocument  true iff the new XMLObject should take ownership of the DOM Document
113          * @return  the unmarshalled object or NULL if no builder is available 
114          */
115         static XMLObject* buildOneFromElement(DOMElement* element, bool bindDocument=false) {
116             const XMLObjectBuilder* b=getBuilder(element);
117             return b ? b->buildFromElement(element,bindDocument) : NULL;
118         }
119
120         /**
121          * Retrieves an XMLObjectBuilder using the key it was registered with.
122          * 
123          * @param key the key used to register the builder
124          * @return the builder or NULL
125          */
126         static const XMLObjectBuilder* getBuilder(const QName& key) {
127             std::map<QName,XMLObjectBuilder*>::const_iterator i=m_map.find(key);
128             return (i==m_map.end()) ? NULL : i->second;
129         }
130
131         /**
132          * Retrieves an XMLObjectBuilder for a given DOM element.
133          * If no match is found, the default builder is returned, if any.
134          * 
135          * @param element the element for which to locate a builder
136          * @return the builder or NULL
137          */
138         static const XMLObjectBuilder* getBuilder(const DOMElement* element);
139
140         /**
141          * Retrieves the default XMLObjectBuilder for DOM elements
142          * 
143          * @return the default builder or NULL
144          */
145         static const XMLObjectBuilder* getDefaultBuilder() {
146             return m_default;
147         }
148
149         /**
150          * Gets an immutable list of all the builders currently registered.
151          * 
152          * @return list of all the builders currently registered
153          */
154         static const std::map<QName,XMLObjectBuilder*>& getBuilders() {
155             return m_map;
156         }
157     
158         /**
159          * Registers a new builder for the given key.
160          * 
161          * @param builderKey the key used to retrieve this builder later
162          * @param builder the builder
163          */
164         static void registerBuilder(const QName& builderKey, XMLObjectBuilder* builder) {
165             deregisterBuilder(builderKey);
166             m_map[builderKey]=builder;
167         }
168
169         /**
170          * Registers a default builder
171          * 
172          * @param builder the default builder
173          */
174         static void registerDefaultBuilder(XMLObjectBuilder* builder) {
175             deregisterDefaultBuilder();
176             m_default=builder;
177         }
178
179         /**
180          * Deregisters a builder.
181          * 
182          * @param builderKey the key for the builder to be deregistered
183          */
184         static void deregisterBuilder(const QName& builderKey) {
185             delete getBuilder(builderKey);
186             m_map.erase(builderKey);
187         }
188
189         /**
190          * Deregisters default builder.
191          */
192         static void deregisterDefaultBuilder() {
193             delete m_default;
194             m_default=NULL;
195         }
196
197         /**
198          * Unregisters and destroys all registered builders. 
199          */
200         static void destroyBuilders();
201
202     protected:
203         XMLObjectBuilder() {}
204     
205     private:
206         static std::map<QName,XMLObjectBuilder*> m_map;
207         static XMLObjectBuilder* m_default;
208     };
209
210 };
211
212 #if defined (_MSC_VER)
213     #pragma warning( pop )
214 #endif
215
216 #endif /* __xmltooling_xmlobjbuilder_h__ */