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