Xerces 3 revisions.
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractXMLObject.cpp
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 /**
18  * AbstractXMLObject.cpp
19  *
20  * An abstract implementation of XMLObject.
21  */
22
23 #include "internal.h"
24 #include "AbstractXMLObject.h"
25 #include "exceptions.h"
26
27 #include <algorithm>
28
29 using namespace xmltooling;
30
31 using xercesc::XMLString;
32
33 AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
34     : m_log(logging::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")),
35         m_schemaLocation(NULL), m_noNamespaceSchemaLocation(NULL), m_nil(xmlconstants::XML_BOOL_NULL),
36         m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL)
37 {
38     addNamespace(Namespace(nsURI, prefix));
39     if (schemaType) {
40         m_typeQname = new QName(*schemaType);
41         addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix()));
42     }
43 }
44
45 AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src)
46     : m_namespaces(src.m_namespaces), m_log(src.m_log), m_schemaLocation(XMLString::replicate(src.m_schemaLocation)),
47         m_noNamespaceSchemaLocation(XMLString::replicate(src.m_noNamespaceSchemaLocation)), m_nil(src.m_nil),
48         m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL)
49 {
50     if (src.m_typeQname)
51         m_typeQname=new QName(*src.m_typeQname);
52 }
53
54 AbstractXMLObject::~AbstractXMLObject()
55 {
56     delete m_typeQname;
57     xercesc::XMLString::release(&m_schemaLocation);
58     xercesc::XMLString::release(&m_noNamespaceSchemaLocation);
59 }
60
61 void XMLObject::setNil(const XMLCh* value) {
62     if (value) {
63         switch (*value) {
64             case xercesc::chLatin_t:
65                 nil(xmlconstants::XML_BOOL_TRUE);
66                 break;
67             case xercesc::chLatin_f:
68                 nil(xmlconstants::XML_BOOL_FALSE);
69                 break;
70             case xercesc::chDigit_1:
71                 nil(xmlconstants::XML_BOOL_ONE);
72                 break;
73             case xercesc::chDigit_0:
74                 nil(xmlconstants::XML_BOOL_ZERO);
75                 break;
76             default:
77                 nil(xmlconstants::XML_BOOL_NULL);
78         }
79     }
80     else {
81         nil(xmlconstants::XML_BOOL_NULL);
82     }
83 }
84
85 XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue)
86 {
87     if (!XMLString::equals(oldValue,newValue)) {
88         releaseThisandParentDOM();
89         XMLCh* newString = XMLString::replicate(newValue);
90         XMLString::release(&oldValue);
91         return newString;
92     }
93     return oldValue;
94 }
95
96 QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue)
97 {
98     if (!oldValue) {
99         if (newValue) {
100             releaseThisandParentDOM();
101             Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());
102             addNamespace(newNamespace);
103             return new QName(*newValue);
104         }
105         return NULL;
106     }
107
108     delete oldValue;
109     releaseThisandParentDOM();
110     if (newValue) {
111         Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());
112         addNamespace(newNamespace);
113         return new QName(*newValue);
114     }
115     return NULL;
116 }
117
118 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue)
119 {
120     if (!oldValue) {
121         if (newValue) {
122             releaseThisandParentDOM();
123             return new DateTime(*newValue);
124         }
125         return NULL;
126     }
127
128     delete oldValue;
129     releaseThisandParentDOM();
130     return newValue ? new DateTime(*newValue) : NULL;
131 }
132
133 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue, bool duration)
134 {
135     delete oldValue;
136     releaseThisandParentDOM();
137     DateTime* ret = new DateTime(newValue, duration);
138     if (duration)
139         ret->parseDuration();
140     else
141         ret->parseDateTime();
142     return ret;
143 }
144
145 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue, bool duration)
146 {
147     delete oldValue;
148     releaseThisandParentDOM();
149     DateTime* ret = new DateTime(newValue);
150     if (duration)
151         ret->parseDuration();
152     else
153         ret->parseDateTime();
154     return ret;
155 }
156
157 XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue)
158 {
159     if (newValue && newValue->hasParent())
160         throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject");
161
162     if (!oldValue) {
163         if (newValue) {
164             releaseThisandParentDOM();
165             newValue->setParent(this);
166         }
167         return newValue;
168     }
169
170     if (oldValue != newValue) {
171         delete oldValue;
172         releaseThisandParentDOM();
173         if (newValue)
174             newValue->setParent(this);
175     }
176
177     return newValue;
178 }
179
180 void AbstractXMLObject::detach()
181 {
182     if (!getParent())
183         return;
184     else if (getParent()->hasParent())
185         throw XMLObjectException("Cannot detach an object whose parent is itself a child.");
186
187     // Pull ourselves out of the parent and then blast him.
188     getParent()->removeChild(this);
189     delete m_parent;
190     m_parent = NULL;
191 }