3eee63a94240891f84013bf2926bbd811810f593
[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 #include <log4cpp/Category.hh>
29
30 using namespace xmltooling;
31
32 AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
33     : m_log(log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), m_schemaLocation(NULL), m_noNamespaceSchemaLocation(NULL),
34         m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL)
35 {
36     addNamespace(Namespace(nsURI, prefix));
37     if (schemaType) {
38         m_typeQname = new QName(*schemaType);
39         addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix()));
40     }
41 }
42
43 AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src)
44     : m_namespaces(src.m_namespaces), m_log(src.m_log), m_schemaLocation(XMLString::replicate(src.m_schemaLocation)),
45         m_noNamespaceSchemaLocation(XMLString::replicate(src.m_noNamespaceSchemaLocation)),
46         m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL)
47 {
48     if (src.m_typeQname)
49         m_typeQname=new QName(*src.m_typeQname);
50 }
51
52 XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue)
53 {
54     if (!XMLString::equals(oldValue,newValue)) {
55         releaseThisandParentDOM();
56         XMLCh* newString = XMLString::replicate(newValue);
57         XMLString::release(&oldValue);
58         return newString;
59     }
60     return oldValue;
61 }
62
63 QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue)
64 {
65     if (!oldValue) {
66         if (newValue) {
67             releaseThisandParentDOM();
68             Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());
69             addNamespace(newNamespace);
70             return new QName(*newValue);
71         }
72         return NULL;
73     }
74
75     delete oldValue;
76     releaseThisandParentDOM();
77     if (newValue) {
78         Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());
79         addNamespace(newNamespace);
80         return new QName(*newValue);
81     }
82     return NULL;
83 }
84
85 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue)
86 {
87     if (!oldValue) {
88         if (newValue) {
89             releaseThisandParentDOM();
90             return new DateTime(*newValue);
91         }
92         return NULL;
93     }
94
95     delete oldValue;
96     releaseThisandParentDOM();
97     return newValue ? new DateTime(*newValue) : NULL;
98 }
99
100 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue)
101 {
102     delete oldValue;
103     releaseThisandParentDOM();
104     DateTime* ret = new DateTime(newValue);
105     ret->parseDateTime();
106     return ret;
107 }
108
109 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue)
110 {
111     delete oldValue;
112     releaseThisandParentDOM();
113     DateTime* ret = new DateTime(newValue);
114     ret->parseDateTime();
115     return ret;
116 }
117
118 XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue)
119 {
120     if (newValue && newValue->hasParent())
121         throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject");
122
123     if (!oldValue) {
124         if (newValue) {
125             releaseThisandParentDOM();
126             newValue->setParent(this);
127         }
128         return newValue;
129     }
130
131     if (oldValue != newValue) {
132         delete oldValue;
133         releaseThisandParentDOM();
134         if (newValue)
135             newValue->setParent(this);
136     }
137
138     return newValue;
139 }
140
141 void AbstractXMLObject::detach()
142 {
143     if (!getParent())
144         return;
145     else if (getParent()->hasParent())
146         throw XMLObjectException("Cannot detach an object whose parent is itself a child.");
147
148     // Pull ourselves out of the parent and then blast him.
149     getParent()->removeChild(this);
150     delete m_parent;
151     m_parent = NULL;
152 }