Xerces 3 revisions.
[shibboleth/cpp-xmltooling.git] / xmltoolingtest / XMLObjectBaseTestCase.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 #include <cxxtest/TestSuite.h>
18 #include <xmltooling/AbstractComplexElement.h>
19 #include <xmltooling/ElementProxy.h>
20 #include <xmltooling/exceptions.h>
21 #include <xmltooling/XMLObjectBuilder.h>
22 #include <xmltooling/XMLToolingConfig.h>
23 #include <xmltooling/io/AbstractXMLObjectMarshaller.h>
24 #include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>
25 #include <xmltooling/impl/AnyElement.h>
26 #include <xmltooling/impl/UnknownElement.h>
27 #include <xmltooling/util/ParserPool.h>
28 #include <xmltooling/util/XMLConstants.h>
29 #include <xmltooling/util/XMLHelper.h>
30 #include <xmltooling/util/XMLObjectChildrenList.h>
31
32 #ifndef XMLTOOLING_NO_XMLSEC
33     #include <xmltooling/signature/Signature.h>
34     using namespace xmlsignature;
35 #endif
36
37 using namespace xmltooling;
38 using namespace xercesc;
39 using namespace std;
40
41 extern string data_path;
42
43 #if defined (_MSC_VER)
44     #pragma warning( push )
45     #pragma warning( disable : 4250 4251 )
46 #endif
47
48 class SimpleXMLObject
49     : public AbstractComplexElement,
50         public AbstractDOMCachingXMLObject,
51         public AbstractXMLObjectMarshaller,
52         public AbstractXMLObjectUnmarshaller
53 {
54 protected:
55     SimpleXMLObject(const SimpleXMLObject& src)
56             : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src),
57                 m_id(XMLString::replicate(src.m_id)) {
58 #ifndef XMLTOOLING_NO_XMLSEC
59         m_children.push_back(NULL);
60         m_signature=m_children.begin();
61 #endif
62         VectorOf(SimpleXMLObject) mine=getSimpleXMLObjects();
63         for (vector<SimpleXMLObject*>::const_iterator i=src.m_simples.begin(); i!=src.m_simples.end(); i++) {
64             mine.push_back(dynamic_cast<SimpleXMLObject*>((*i)->clone()));
65         }
66     }
67
68 public:
69     static const XMLCh NAMESPACE[];
70     static const XMLCh NAMESPACE_PREFIX[];
71     static const XMLCh LOCAL_NAME[];
72     static const XMLCh DERIVED_NAME[];
73     static const XMLCh TYPE_NAME[];
74     static const XMLCh ID_ATTRIB_NAME[];
75
76     SimpleXMLObject(
77         const XMLCh* nsURI=NULL, const XMLCh* localName=NULL, const XMLCh* prefix=NULL, const QName* schemaType=NULL
78         ) : AbstractXMLObject(nsURI, localName, prefix, schemaType), m_id(NULL) {
79 #ifndef XMLTOOLING_NO_XMLSEC
80         m_children.push_back(NULL);
81         m_signature=m_children.begin();
82 #endif
83     }
84
85     virtual ~SimpleXMLObject() {
86         XMLString::release(&m_id);
87     }
88
89     XMLObject* clone() const {
90         auto_ptr<XMLObject> domClone(AbstractDOMCachingXMLObject::clone());
91         SimpleXMLObject* ret=dynamic_cast<SimpleXMLObject*>(domClone.get());
92         if (ret) {
93             domClone.release();
94             return ret;
95         }
96
97         return new SimpleXMLObject(*this);
98     }
99
100     const XMLCh* getXMLID() const { return getId(); }
101     const XMLCh* getId() const { return m_id; }
102     void setId(const XMLCh* id) { m_id=prepareForAssignment(m_id,id); }
103
104     const XMLCh* getValue() const { return getTextContent(); }
105     void setValue(const XMLCh* value) { setTextContent(value); }
106
107 #ifndef XMLTOOLING_NO_XMLSEC    
108     Signature* getSignature() const {
109         return dynamic_cast<Signature*>(*m_signature);
110     }
111
112     void setSignature(Signature* sig) {
113         *m_signature=prepareForAssignment(*m_signature,sig);
114     }
115 #endif
116
117     VectorOf(SimpleXMLObject) getSimpleXMLObjects() {
118         return VectorOf(SimpleXMLObject)(this, m_simples, &m_children, m_children.end());
119     }
120     
121     const std::vector<SimpleXMLObject*>& getSimpleXMLObjects() const {
122         return m_simples;
123     }
124
125 protected:
126     void marshallAttributes(xercesc::DOMElement* domElement) const {
127         if(getId()) {
128             domElement->setAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME, getId());
129             domElement->setIdAttributeNS(NULL, SimpleXMLObject::ID_ATTRIB_NAME);
130         }
131     }
132
133     void processChildElement(XMLObject* childXMLObject, const xercesc::DOMElement* root) {
134         SimpleXMLObject* simple=dynamic_cast<SimpleXMLObject*>(childXMLObject);
135         if (simple) {
136             getSimpleXMLObjects().push_back(simple);
137             return;
138         }
139         
140 #ifndef XMLTOOLING_NO_XMLSEC
141         Signature* sig=dynamic_cast<Signature*>(childXMLObject);
142         if (sig) {
143             setSignature(sig);
144             return;
145         }
146 #endif
147
148         throw UnmarshallingException("Unknown child element cannot be added to parent object.");
149     }
150
151     void processAttribute(const xercesc::DOMAttr* attribute) {
152         if (XMLHelper::isNodeNamed(attribute, NULL, SimpleXMLObject::ID_ATTRIB_NAME))
153             setId(attribute->getValue());
154         else
155             throw UnmarshallingException("Unknown attribute cannot be processed by parent object.");
156     }
157
158 private:
159     XMLCh* m_id;
160     vector<SimpleXMLObject*> m_simples;
161 #ifndef XMLTOOLING_NO_XMLSEC
162     list<XMLObject*>::iterator m_signature;
163 #endif
164 };
165
166 class SimpleXMLObjectBuilder : public XMLObjectBuilder
167 {
168 public:
169     XMLObject* buildObject() const {
170         return buildObject(SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME, SimpleXMLObject::NAMESPACE_PREFIX);
171     }
172
173     XMLObject* buildObject(
174         const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const QName* schemaType=NULL
175         ) const {
176         return new SimpleXMLObject(nsURI, localName, prefix, schemaType);
177     }
178
179     static SimpleXMLObject* buildSimpleXMLObject() {
180         const SimpleXMLObjectBuilder* b = dynamic_cast<const SimpleXMLObjectBuilder*>(
181             XMLObjectBuilder::getBuilder(QName(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME))
182             );
183         if (b)
184             return dynamic_cast<SimpleXMLObject*>(b->buildObject());
185         throw XMLObjectException("Unable to obtain typed builder for SimpleXMLObject.");
186     }
187 };
188
189 #if defined (_MSC_VER)
190     #pragma warning( pop )
191 #endif