1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #include <anna/core/functions.hpp>
39 #include <anna/xml/Node.hpp>
40 #include <anna/xml/Attribute.hpp>
41 #include <anna/xml/Text.hpp>
45 using namespace anna::xml;
48 * Si el nodo no tiene padre => debe crear los pool de datos en los que sus descendientes irán
49 * creando los objetos que vayan siendo necesarios.
51 * Éste es el constructor que se usará para instanciar al nodo ROOT.
53 Node::Node(const char* name) : a_name(name), a_parent(NULL), a_text(NULL), a_namespace(NULL) {
54 a_node_pool = new node_pool;
55 a_attribute_pool = new attribute_pool;
56 a_text_pool = new text_pool;
57 a_namespace_pool = new namespace_pool;
58 a_namespaces = new namespace_container;
63 * Si el nodo tiene padre => copiará las instancias de los pools de datos.
65 Node::Node() : a_parent(NULL), a_text(NULL), a_namespace(NULL) {
67 a_attribute_pool = NULL;
69 a_namespace_pool = NULL;
77 if(a_parent == NULL) {
79 delete a_attribute_pool;
81 delete a_namespace_pool;
88 for(attribute_iterator aa = a_attributes.begin(), maxaa = a_attributes.end(); aa != maxaa; aa ++)
89 a_attribute_pool->release(attribute(aa));
93 for(Children::iterator cc = a_children.begin(), maxcc = a_children.end(); cc != maxcc; cc ++) {
96 a_node_pool->release(aux);
102 a_text_pool->release(a_text);
106 // Si es el nodo root ....
107 if(a_parent == NULL) {
108 a_namespaces->clear();
109 a_namespace_pool->clear();
115 const Attribute* Node::getAttribute(const char* name, const bool exceptionWhenNotFound) const
116 throw(RuntimeException) {
117 const Attribute* result(NULL);
118 result = find(name, attribute_begin(), attribute_end());
120 if(result == NULL && exceptionWhenNotFound == true) {
121 string msg = asString();
122 msg += " | Attribute: ";
124 msg += " | Not found";
125 throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
131 xml::Attribute* Node::createAttribute(const char* name, const char* value, const Namespace* _namespace)
133 Attribute* attribute = a_attribute_pool->create();
134 attribute->setNode(this);
135 attribute->setName(name);
136 attribute->setValue(value);
137 attribute->setNamespace(_namespace);
138 a_attributes.push_back(attribute);
142 xml::Text* Node::createText(const char* text)
143 throw(RuntimeException) {
145 string msg = asString();
147 msg += a_text->asString();
148 msg += " | Node has already text assigned";
149 throw RuntimeException(msg, ANNA_FILE_LOCATION);
152 a_text = a_text_pool->create();
153 a_text->setNode(this);
154 a_text->setValue(text);
158 Node* Node::createChild(const char* name)
160 Node* result = a_node_pool->create();
161 result->a_parent = this;
162 result->setName(name);
163 result->a_node_pool = a_node_pool;
164 result->a_attribute_pool = a_attribute_pool;
165 result->a_text_pool = a_text_pool;
166 result->a_root = a_root;
167 a_children.push_back(result);
172 * Recordar que todos los namespaces se crean sólo en el nodo ROOT.
174 const Namespace* Node::createNamespace(const std::string& name, const char* reference)
175 throw(RuntimeException) {
176 const Namespace* result = NULL;
178 if((result = namespace_find(name, false)) != NULL) {
179 if(result->getReference() != reference) {
180 string msg(result->asString());
181 msg += " | New reference: ";
183 msg += " | Namespace already defined";
184 throw RuntimeException(msg, ANNA_FILE_LOCATION);
188 Namespace* newns = a_namespace_pool->create();
189 newns->setName(name);
190 newns->setReference(reference);
191 a_namespaces->add(newns);
194 result = a_root->createNamespace(name, reference);
200 const Node* Node::find(const char* childName, const bool exceptionWhenNotFound) const
201 throw(RuntimeException) {
204 for(Node::Children::const_iterator ii = a_children.begin(), maxii = a_children.end(); ii != maxii; ii ++) {
207 if(anna_strcmp(child->a_name.c_str(), childName) == 0)
211 if(exceptionWhenNotFound == true) {
212 std::string msg("Successor '");
214 msg += "' not found at node '";
217 throw RuntimeException(msg, ANNA_FILE_LOCATION);
223 Namespace* Node::namespace_find(const std::string& name, const bool exceptionWhenNotFound)
224 throw(RuntimeException) {
225 Namespace* result = a_root->a_namespaces->find(name);
227 if(result == NULL && exceptionWhenNotFound == true) {
228 string msg(asString());
229 msg += " | Namespace: ";
231 msg += " | Namespace is not defined";
232 throw RuntimeException(msg, ANNA_FILE_LOCATION);
238 string Node::asString() const
240 string result("xml::Node { Name: ");
243 if(a_namespace != NULL) {
245 result += a_namespace->asString();
248 return result += " }";
251 const Attribute* Node::find(const char* attrName, const_attribute_iterator begin, const_attribute_iterator end)
253 Attribute* attribute;
255 for(; begin != end; begin ++) {
258 if(anna_strcmp(attribute->getName(), attrName) == 0)