Multi-line svn commit, see body.
[shibboleth/cpp-xmltooling.git] / xmltooling / AbstractXMLObject.cpp
1 /*\r
2 *  Copyright 2001-2006 Internet2\r
3  * \r
4 * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *     http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 /**\r
18  * AbstractXMLObject.cpp\r
19  * \r
20  * An abstract implementation of XMLObject.\r
21  */\r
22 \r
23 #include "internal.h"\r
24 #include "AbstractXMLObject.h"\r
25 #include "exceptions.h"\r
26 \r
27 #include <algorithm>\r
28 #include <log4cpp/Category.hh>\r
29 \r
30 using namespace xmltooling;\r
31 \r
32 AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)\r
33     : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), m_schemaLocation(NULL),\r
34         m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL)\r
35 {\r
36     addNamespace(Namespace(nsURI, prefix));\r
37     if (schemaType) {\r
38         m_typeQname = new QName(*schemaType);\r
39         addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix()));\r
40     }\r
41 }\r
42 \r
43 AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src)\r
44     : m_namespaces(src.m_namespaces), m_log(src.m_log), m_schemaLocation(XMLString::replicate(src.m_schemaLocation)),\r
45         m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL)\r
46 {\r
47     if (src.m_typeQname)\r
48         m_typeQname=new QName(*src.m_typeQname);\r
49 }\r
50 \r
51 XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue)\r
52 {\r
53     if (!XMLString::equals(oldValue,newValue)) {\r
54         releaseThisandParentDOM();\r
55         XMLCh* newString = XMLString::replicate(newValue);\r
56         XMLString::release(&oldValue);\r
57         return newString;\r
58     }\r
59     return oldValue;\r
60 }\r
61 \r
62 QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue)\r
63 {\r
64     if (!oldValue) {\r
65         if (newValue) {\r
66             releaseThisandParentDOM();\r
67             Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());\r
68             addNamespace(newNamespace);\r
69             return new QName(*newValue);\r
70         }\r
71         return NULL;\r
72     }\r
73 \r
74     delete oldValue;\r
75     releaseThisandParentDOM();\r
76     if (newValue) {\r
77         Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix());\r
78         addNamespace(newNamespace);\r
79         return new QName(*newValue);\r
80     }\r
81     return NULL;\r
82 }\r
83 \r
84 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue)\r
85 {\r
86     if (!oldValue) {\r
87         if (newValue) {\r
88             releaseThisandParentDOM();\r
89             return new DateTime(*newValue);\r
90         }\r
91         return NULL;\r
92     }\r
93 \r
94     delete oldValue;\r
95     releaseThisandParentDOM();\r
96     return newValue ? new DateTime(*newValue) : NULL;\r
97 }\r
98 \r
99 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue)\r
100 {\r
101     delete oldValue;\r
102     releaseThisandParentDOM();\r
103     DateTime* ret = new DateTime(newValue);\r
104     ret->parseDateTime();\r
105     return ret;\r
106 }\r
107 \r
108 DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue)\r
109 {\r
110     delete oldValue;\r
111     releaseThisandParentDOM();\r
112     DateTime* ret = new DateTime(newValue);\r
113     ret->parseDateTime();\r
114     return ret;\r
115 }\r
116 \r
117 XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue)\r
118 {\r
119     if (newValue && newValue->hasParent())\r
120         throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject");\r
121 \r
122     if (!oldValue) {\r
123         if (newValue) {\r
124             releaseThisandParentDOM();\r
125             newValue->setParent(this);\r
126         }\r
127         return newValue;\r
128     }\r
129 \r
130     if (oldValue != newValue) {\r
131         delete oldValue;\r
132         releaseThisandParentDOM();\r
133         if (newValue)\r
134             newValue->setParent(this);\r
135     }\r
136 \r
137     return newValue;\r
138 }\r
139 \r
140 void AbstractXMLObject::detach()\r
141 {\r
142     if (!getParent())\r
143         return;\r
144     else if (getParent()->hasParent())\r
145         throw XMLObjectException("Cannot detach an object whose parent is itself a child.");\r
146 \r
147     // Pull ourselves out of the parent and then blast him.\r
148     getParent()->removeChild(this);\r
149     delete m_parent;\r
150     m_parent = NULL;\r
151 }\r