1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
9 #ifndef anna_xml_Node_hpp
10 #define anna_xml_Node_hpp
14 #include <anna/core/Allocator.hpp>
15 #include <anna/core/RuntimeException.hpp>
16 #include <anna/core/functions.hpp>
17 #include <anna/core/util/Recycler.hpp>
18 #include <anna/core/util/SortedVector.hpp>
20 #include <anna/xml/Namespace.hpp>
33 Nodo de documento XML.
35 Cada nodo puede tener una serie indeterminada de atributos y nodos hijos. Por ejemplo:
39 <xvc HeartBeat="20000">
41 <INetAddress Address="204.152.65.15" Port="2000"/>
42 <INetAddress Address="204.152.65.47" Port="2002"/>
45 <ethernet Mode="raw" VirtualAddress="1.1.1.100">
46 <Input Device="/dev/qfe" PhysicalAccessPoint="2" MAC="8:0:20:9e:ee:21"/>
47 <Output Device="/dev/qfe" PhysicalAccessPoint="2" MAC="8:0:20:9e:ee:c9"/>
53 El nodo \em xvc tiene un atributo (ver Attribute) llamado \em HeartBeat y dos nodos
54 hijos (\em broadcast y \em ethernet).
57 struct NamespaceByName {
58 static const std::string& value(const Namespace* ns) throw() { return ns->getName(); }
62 typedef std::vector <Node*> Children; /**< Estructura usada para guardar los nodos hijos */
63 typedef Children::iterator child_iterator; /**< Iterador sobre lista de nodos */
64 typedef Children::const_iterator const_child_iterator; /**< Iterador sobre lista de nodos no modificables */
66 typedef std::vector <Attribute*> Attributes; /**< Estructura usada para guardar los attributos */
67 typedef Attributes::iterator attribute_iterator; /**< Iterador sobre la lista de atributos no modificables. */
68 typedef Attributes::const_iterator const_attribute_iterator; /**< Iterador sobre la lista de atributos no modificables */
70 typedef SortedVector <Namespace, NamespaceByName, std::string> namespace_container;
71 typedef namespace_container::iterator namespace_iterator;
72 typedef namespace_container::const_iterator const_namespace_iterator;
76 \param name Nombre del nodo.
78 Node(const char* name);
86 Devuelve el nombre del nodo.
87 \return El nombre del nodo.
89 const char* getName() const throw() { return a_name.c_str(); }
92 * Devuelve el nombre del nodo.
93 * \return El nombre del nodo.
95 const std::string& getNameAsString() const throw() { return a_name; }
98 Devuelve la referencia al nodo predecesor de este nodo. Pueder ser NULL.
99 \return La referencia al nodo predecesor de este nodo. Pueder ser NULL.
101 const Node* getParent() const throw() { return a_parent; }
104 Devuelve la referencia al nodo predecesor de este nodo. Pueder ser NULL.
105 \return La referencia al nodo predecesor de este nodo. Pueder ser NULL.
107 Node* getParent() throw() { return const_cast <Node*>(a_parent); }
110 Devuelve la referencia al atributo que coincide con el nombre dado, si no existe lanzara
111 una excepcion de ejecucion.
112 \param name Nombre del atributo buscado.
113 \param exceptionWhenNotFound Indica el comportamiento en caso de no encontrar el atributo que
114 coincida con el nombre buscado.
115 \return La referencia al atributo que coincide con el nombre dado.
117 const Attribute* getAttribute(const char* name, const bool exceptionWhenNotFound = true) const throw(anna::RuntimeException);
120 Devuelve la referencia al texto asociado a este nodo. Pueder ser NULL.
121 \return La referencia al texto asociado a este nodo. Pueder ser NULL.
123 const Text* getText() const throw() { return a_text; }
126 * Devuelve el namespace asociado a este nodo. Puede ser NULL.
127 * \return el namespace asociado a este nodo. Puede ser NULL.
129 const Namespace* getNamespace() const throw() { return a_namespace; }
132 Devuelve un iterador al comienzo de la lista de nodo hijos.
134 A continuacion presentamos un ejemplo de como se recorreria lista de nodos
135 hijos de una determinado nodo.
139 using namespace anna::xml;
141 Node* theNode = ... <establece un valor correcto> ...
144 for (Node::iterator ii = theNode->begin (), maxii = theNode->end (); ii != maxii; ii ++) {
145 theChild = Node::node (ii);
147 .... <Procesar el hijo> ....
152 \return Un iterador al comienzo de la lista de nodo hijos.
154 child_iterator child_begin() throw() { return a_children.begin(); }
157 Devuelve un iterador al comienzo de la lista de nodos hijos no modificables.
159 A continuacion presentamos un ejemplo de como se recorreria lista de nodos
160 hijos de una determinado nodo no modificable.
164 using namespace anna::xml;
166 const Node* theNode = ... <establece un valor correcto> ...
167 const Node* theChild;
169 for (Node::const_iterator ii = theNode->begin (), maxii = theNode->end (); ii != maxii; ii ++) {
170 theChild = Node::node (ii);
172 .... <Procesar el hijo> ....
177 \return Un iterador al comienzo de la lista de nodo hijos no modificables.
179 const_child_iterator child_begin() const throw() { return a_children.begin(); }
182 Devuelve un iterador al comienzo de la lista de atributos no modificables.
183 \return Un iterador al comienzo de la lista de atributos no modificables.
185 const_attribute_iterator attribute_begin() const throw() { return a_attributes.begin(); }
188 Devuelve un iterador al comienzo de la lista de namespaces no modificables.
189 \return Un iterador al comienzo de la lista de namespaces no modificables.
191 const_namespace_iterator namespace_begin() const throw() { return a_root->a_namespaces->begin(); }
195 Devuelve un iterador al final de la lista de nodo hijos.
196 \return Un iterador al final de la lista de nodo hijos.
199 child_iterator child_end() throw() { return a_children.end(); }
202 Devuelve un iterador al final de la lista de nodo hijos no modificables.
203 \return Un iterador al final de la lista de nodo hijos no modificables.
206 const_child_iterator child_end() const throw() { return a_children.end(); }
209 * Devuelve el número de hijos definidos.
210 * \return el número de hijos definidos.
212 int child_size() const throw() { return a_children.size(); }
215 Devuelve un iterador al final de la lista de atributos no modificables.
216 \return Un iterador al final de la lista de atributos no modificables.
218 const_attribute_iterator attribute_end() const throw() { return a_attributes.end(); }
221 Devuelve un iterador al comienzo de la lista de namespaces no modificables.
222 \return Un iterador al comienzo de la lista de namespaces no modificables.
224 const_namespace_iterator namespace_end() const throw() { return a_root->a_namespaces->end(); }
227 * Devuelve el número de namespace definidos.
228 * \return el número de namespace definidos.
230 int namespace_size() const throw() { return a_root->a_namespaces->size(); }
233 Busca un nodo sucesor directo de este cuyo nombre coincida con el nombre recibido
236 \param childName Nombre del nodo hijo que estamos buscando.
237 \param exceptionWhenNotFound Indica el comportamiento en caso de no encontrar ningun nodo hijo que
238 coincida con el nombre buscado.
240 \return Referencia al nodo hijo que coincide con el nombre buscado. Si exceptionWhenNotFound es \em false
241 y ninguno de los hijos cumple con la busqueda sera NULL.
243 const Node* find(const char* childName, const bool exceptionWhenNotFound = true) const
244 throw(RuntimeException);
247 Crea un atributo que depende de este nodo.
248 \param name Nombre del atributo.
249 \param value Valor asociado al atributo.
250 \param _namespace Referencia al namespace al que pertenece el atributo. Puede ser NULL.
251 \return La instancia del nuevo atributo.
253 xml::Attribute* createAttribute(const char* name, const char* value, const Namespace* _namespace = NULL) throw();
256 Crea un atributo que depende de este nodo.
257 \param name Nombre del atributo.
258 \param value Valor asociado al atributo.
259 \param _namespace Referencia al namespace al que pertenece el atributo. Puede ser NULL.
260 \return La instancia del nuevo atributo.
262 xml::Attribute* createAttribute(const char* name, const std::string& value, const Namespace* _namespace = NULL) throw() {
263 return createAttribute(name, value.c_str(), _namespace);
267 Crea un atributo que depende de este nodo.
268 \param name Nombre del atributo.
269 \param value Valor asociado al atributo.
270 \param _namespace Referencia al namespace al que pertenece el atributo. Puede ser NULL.
271 \return La instancia del nuevo atributo.
273 xml::Attribute* createAttribute(const char* name, const int value, const Namespace* _namespace = NULL) throw() {
274 return createAttribute(name, anna::functions::asString(value), _namespace);
278 Crea un atributo que depende de este nodo.
279 \param name Nombre del atributo.
280 \param value Valor asociado al atributo. Pasamos como puntero para que no se creen ambiguedades
281 con el codigo escrito hasta ahora.
282 \param _namespace Referencia al namespace al que pertenece el atributo. Puede ser NULL.
283 \return La instancia del nuevo atributo.
285 xml::Attribute* createAttribute(const char* name, const S64* value, const Namespace* _namespace = NULL) throw() {
286 return createAttribute(name, anna::functions::asString(*value), _namespace);
290 Crea un atributo que depende de este nodo.
291 \param name Nombre del atributo.
292 \param value Valor asociado al atributo. Pasamos como puntero para que no se creen ambiguedades
293 con el codigo escrito hasta ahora.
294 \param _namespace Referencia al namespace al que pertenece el atributo. Puede ser NULL.
295 \return La instancia del nuevo atributo.
297 xml::Attribute* createAttribute(const char* name, const U64* value, const Namespace* _namespace = NULL) throw() {
298 return createAttribute(name, anna::functions::asString(*value), _namespace);
302 Crea el texto asociado a este nodo.
303 \param text contain Valor del texto asociado a este nodo.
304 \return La instancia del nuevo texto.
306 xml::Text* createText(const char* text) throw(RuntimeException);
309 Crea el texto asociado a este nodo.
310 \param text contain Valor del texto asociado a este nodo.
311 \return La instancia del nuevo texto.
313 xml::Text* createText(const std::string& text) throw(RuntimeException) { return createText(text.c_str()); }
316 Crea un nuevo nodo que depende de este.
317 \param name Nombre del nodo hijo.
319 Node* createChild(const char* name) throw();
322 * Crea un nuevo namespace (si procede) que podemos usar para asignar a los distintos nodos. Si el nodo ya existe y la referencia no coincide
323 * con la registrada se obtendrá una excepción.
325 * \param name Nombre del nuevo namespace.
326 * \param reference URI de la que obtener las definiciones.
327 * \return La instancia de un namespace con los parámetros indicados.
329 const Namespace* createNamespace(const char* name, const char* reference) throw(RuntimeException) {
330 std::string _name(name);
331 return createNamespace(_name, reference);
335 * Crea un nuevo namespace (si procede) que podemos usar para asignar a los distintos nodos. Si el nodo ya existe y la referencia no coincide
336 * con la registrada se obtendrá una excepción.
338 * \param name Nombre del nuevo namespace.
339 * \param reference URI de la que obtener las definiciones.
340 * \return La instancia de un namespace con los parámetros indicados.
342 const Namespace* createNamespace(const std::string& name, const char* reference) throw(RuntimeException);
345 * Establece el namespace asociado a este nodo.
346 * \param _namespace Instancia del namespace que vamos a asociar al nodo.
348 void setNamespace(const Namespace* _namespace) throw() { a_namespace = _namespace; }
351 * Devuelve la instancia del namespace que coincide con el nombre recibido como parámetro. Puede ser NULL.
352 * \return la instancia del namespace que coincide con el nombre recibido como parámetro. Puede ser NULL.
354 Namespace* namespace_find(const char* name, const bool exceptionWhenNotFound = true) throw(RuntimeException) {
355 const std::string _name(name);
356 return namespace_find(_name, exceptionWhenNotFound);
360 * Devuelve la instancia del namespace que coincide con el nombre recibido como parámetro. Puede ser NULL.
361 * \return la instancia del namespace que coincide con el nombre recibido como parámetro. Puede ser NULL.
363 Namespace* namespace_find(const std::string& name, const bool exceptionWhenNotFound = true) throw(RuntimeException);
366 * Devuelve la instancia del namespace que coincide con el nombre recibido como parámetro. Puede ser NULL.
367 * \return la instancia del namespace que coincide con el nombre recibido como parámetro. Pueder ser NULL.
369 const Namespace* namespace_find(const char* name, const bool exceptionWhenNotFound = true) const throw(RuntimeException) {
370 return const_cast <Node*>(this)->namespace_find(name, exceptionWhenNotFound);
374 * Devuelve la instancia del namespace que coincide con el nombre recibido como parámetro. Puede ser NULL.
375 * \return la instancia del namespace que coincide con el nombre recibido como parámetro. Pueder ser NULL.
377 const Namespace* namespace_find(const std::string& name, const bool exceptionWhenNotFound = true) const throw(RuntimeException) {
378 return const_cast <Node*>(this)->namespace_find(name, exceptionWhenNotFound);
382 * Libera todos los componentes (atributos, namespaces y nodos hijos) asociados a este nodo.
384 void clear() throw();
387 Devuelve una cadena con toda la información relevante de esta instancia.
388 \return Una cadena con toda la información relevante de esta instancia.
390 std::string asString() const throw();
393 Devuelve la refencia al nodo sobre el que se encuentra el iterador pasado como
395 \param ii Iterador que estamos recorriendo.
396 \return La refencia al nodo sobre el que se encuentra el iterador pasado como
399 static Node* node(child_iterator& ii) throw() { return *ii; }
402 Devuelve la refencia al nodo sobre el que se encuentra el iterador pasado como parámetro.
403 \param ii Iterador que estamos recorriendo.
404 \return La refencia al nodo sobre el que se encuentra el iterador pasado como parámetro.
406 static const Node* node(const_child_iterator& ii) throw() { return *ii; }
409 Devuelve la refencia al atributo sobre el que se encuentra el iterador pasado como parámetro.
410 \param ii Iterador que estamos recorriendo.
411 \return La refencia al atributo sobre el que se encuentra el iterador pasado como parámetro.
413 static const Attribute* attribute(const_attribute_iterator& ii) throw() { return *ii; }
416 Devuelve la refencia al namespace sobre el que se encuentra el iterador pasado como parámetro.
417 \param ii Iterador que estamos recorriendo.
418 \return La refencia al namespace sobre el que se encuentra el iterador pasado como parámetro.
420 static const Namespace* xnamespace(const_namespace_iterator& ii) throw() { return namespace_container::data(ii);; }
424 Devuelve la refencia al atributo sobre el que se encuentra el iterador pasado como parámetro.
425 \param ii Iterador que estamos recorriendo.
426 \return La refencia al atributo sobre el que se encuentra el iterador pasado como parámetro.
428 static Attribute* attribute(attribute_iterator& ii) throw() { return *ii; }
432 const Node* a_parent;
435 Attributes a_attributes;
437 const Namespace* a_namespace;
439 // Esta instancia sólo la creará el nodo root.
440 namespace_container* a_namespaces;
442 typedef Recycler <Node> node_pool;
443 typedef Recycler <Attribute> attribute_pool;
444 typedef Recycler <Text> text_pool;
446 typedef Recycler <Namespace> namespace_pool;
448 node_pool* a_node_pool;
449 attribute_pool* a_attribute_pool;
450 text_pool* a_text_pool;
451 namespace_pool* a_namespace_pool;
453 /* Para evitar que se pueda crear desde el exterior */
456 void setRoot(Node* root) throw() { a_root = root; }
457 void setName(const char* name) throw() { a_name = name; }
459 static const Attribute* find(const char* attrName, const_attribute_iterator, const_attribute_iterator) throw();
462 friend class Allocator<Node>;
464 friend class Decompressor;