Normalize xml processing
[anna.git] / include / anna / xml / Node.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
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 //
7
8
9 #ifndef anna_xml_Node_hpp
10 #define anna_xml_Node_hpp
11
12 #include <vector>
13
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>
19
20 #include <anna/xml/Namespace.hpp>
21
22 namespace anna {
23
24 namespace xml {
25
26 class Parser;
27 class Attribute;
28 class Text;
29 class XPath;
30 class Decompressor;
31
32 /**
33    Nodo de documento XML.
34
35    Cada nodo puede tener una serie indeterminada de atributos y nodos hijos. Por ejemplo:
36
37    \code
38
39    <xvc HeartBeat="20000">
40       <broadcast>
41          <INetAddress Address="204.152.65.15" Port="2000"/>
42          <INetAddress Address="204.152.65.47" Port="2002"/>
43       </broadcast>
44
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"/>
48       </ethernet>
49    </xvc>
50
51    \endcode
52
53    El nodo \em xvc tiene un atributo (ver Attribute) llamado \em HeartBeat y dos nodos
54    hijos (\em broadcast y \em ethernet).
55 */
56 class Node {
57   struct NamespaceByName {
58     static const std::string& value(const Namespace* ns) throw() { return ns->getName(); }
59   };
60
61 public:
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 */
65
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 */
69
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;
73
74   /**
75      Constructor.
76      \param name Nombre del nodo.
77   */
78   Node(const char* name);
79
80   /**
81      Destructor.
82   */
83   virtual ~Node();
84
85   /**
86      Devuelve el nombre del nodo.
87      \return El nombre del nodo.
88   */
89   const char* getName() const throw() { return a_name.c_str(); }
90
91   /**
92    * Devuelve el nombre del nodo.
93    * \return El nombre del nodo.
94    */
95   const std::string& getNameAsString() const throw() { return a_name; }
96
97   /**
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.
100   */
101   const Node* getParent() const throw() { return a_parent; }
102
103   /**
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.
106   */
107   Node* getParent() throw() { return const_cast <Node*>(a_parent); }
108
109   /**
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.
116   */
117   const Attribute* getAttribute(const char* name, const bool exceptionWhenNotFound = true) const throw(anna::RuntimeException);
118
119   /**
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.
122   */
123   const Text* getText() const throw() { return a_text; }
124
125   /**
126    * Devuelve el namespace asociado a este nodo. Puede ser NULL.
127    * \return el namespace asociado a este nodo. Puede ser NULL.
128    */
129   const Namespace* getNamespace() const throw() { return a_namespace; }
130
131   /**
132      Devuelve un iterador al comienzo de la lista de nodo hijos.
133
134      A continuacion presentamos un ejemplo de como se recorreria lista de nodos
135      hijos de una determinado nodo.
136
137      \code
138
139      using namespace anna::xml;
140
141      Node* theNode = ... <establece un valor correcto> ...
142      Node* theChild;
143
144      for (Node::iterator ii = theNode->begin (), maxii = theNode->end (); ii != maxii; ii ++) {
145         theChild = Node::node (ii);
146
147         .... <Procesar el hijo> ....
148      }
149
150      \endcode
151
152      \return Un iterador al comienzo de la lista de nodo hijos.
153   */
154   child_iterator child_begin() throw() { return a_children.begin(); }
155
156   /**
157      Devuelve un iterador al comienzo de la lista de nodos hijos no modificables.
158
159      A continuacion presentamos un ejemplo de como se recorreria lista de nodos
160      hijos de una determinado nodo no modificable.
161
162      \code
163
164      using namespace anna::xml;
165
166      const Node* theNode = ... <establece un valor correcto> ...
167      const Node* theChild;
168
169      for (Node::const_iterator ii = theNode->begin (), maxii = theNode->end (); ii != maxii; ii ++) {
170         theChild = Node::node (ii);
171
172         .... <Procesar el hijo> ....
173      }
174
175      \endcode
176
177      \return Un iterador al comienzo de la lista de nodo hijos no modificables.
178   */
179   const_child_iterator child_begin() const throw() { return a_children.begin(); }
180
181   /**
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.
184   */
185   const_attribute_iterator attribute_begin() const throw() { return a_attributes.begin(); }
186
187   /**
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.
190   */
191   const_namespace_iterator namespace_begin() const throw() { return a_root->a_namespaces->begin(); }
192
193
194   /**
195      Devuelve un iterador al final de la lista de nodo hijos.
196      \return Un iterador al final de la lista de nodo hijos.
197      \see #child_begin
198   */
199   child_iterator child_end() throw() { return a_children.end(); }
200
201   /**
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.
204      \see #begin
205   */
206   const_child_iterator child_end() const throw() { return a_children.end(); }
207
208   /**
209    * Devuelve el número de hijos definidos.
210    * \return el número de hijos definidos.
211    */
212   int child_size() const throw() { return a_children.size(); }
213
214   /**
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.
217   */
218   const_attribute_iterator attribute_end() const throw() { return a_attributes.end(); }
219
220   /**
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.
223   */
224   const_namespace_iterator namespace_end() const throw() { return a_root->a_namespaces->end(); }
225
226   /**
227    * Devuelve el número de namespace definidos.
228    * \return el número de namespace definidos.
229    */
230   int namespace_size() const throw() { return a_root->a_namespaces->size(); }
231
232   /**
233      Busca un nodo sucesor directo de este cuyo nombre coincida con el nombre recibido
234      como parámetro.
235
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.
239
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.
242   */
243   const Node* find(const char* childName, const bool exceptionWhenNotFound = true) const
244   throw(RuntimeException);
245
246   /**
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.
252   */
253   xml::Attribute* createAttribute(const char* name, const char* value, const Namespace* _namespace = NULL) throw();
254
255   /**
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.
261   */
262   xml::Attribute* createAttribute(const char* name, const std::string& value, const Namespace* _namespace = NULL) throw() {
263     return createAttribute(name, value.c_str(), _namespace);
264   }
265
266   /**
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.
272   */
273   xml::Attribute* createAttribute(const char* name, const int value, const Namespace* _namespace = NULL) throw() {
274     return createAttribute(name, anna::functions::asString(value), _namespace);
275   }
276
277   /**
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.
284   */
285   xml::Attribute* createAttribute(const char* name, const S64* value, const Namespace* _namespace = NULL) throw() {
286     return createAttribute(name, anna::functions::asString(*value), _namespace);
287   }
288
289   /**
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.
296   */
297   xml::Attribute* createAttribute(const char* name, const U64* value, const Namespace* _namespace = NULL) throw() {
298     return createAttribute(name, anna::functions::asString(*value), _namespace);
299   }
300
301   /**
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.
305   */
306   xml::Text* createText(const char* text) throw(RuntimeException);
307
308   /**
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.
312   */
313   xml::Text* createText(const std::string& text) throw(RuntimeException) { return createText(text.c_str()); }
314
315   /**
316      Crea un nuevo nodo que depende de este.
317      \param name Nombre del nodo hijo.
318   */
319   Node* createChild(const char* name) throw();
320
321   /**
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.
324    *
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.
328    */
329   const Namespace* createNamespace(const char* name, const char* reference) throw(RuntimeException) {
330     std::string _name(name);
331     return createNamespace(_name, reference);
332   }
333
334   /**
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.
337    *
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.
341    */
342   const Namespace* createNamespace(const std::string& name, const char* reference) throw(RuntimeException);
343
344   /**
345    * Establece el namespace asociado a este nodo.
346    * \param _namespace Instancia del namespace que vamos a asociar al nodo.
347    */
348   void setNamespace(const Namespace* _namespace) throw() { a_namespace = _namespace; }
349
350   /**
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.
353    */
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);
357   }
358
359   /**
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.
362    */
363   Namespace* namespace_find(const std::string& name,  const bool exceptionWhenNotFound = true) throw(RuntimeException);
364
365   /**
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.
368    */
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);
371   }
372
373   /**
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.
376    */
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);
379   }
380
381   /**
382    * Libera todos los componentes (atributos, namespaces y nodos hijos) asociados a este nodo.
383    */
384   void clear() throw();
385
386   /**
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.
389   */
390   std::string asString() const throw();
391
392   /**
393      Devuelve la refencia al nodo sobre el que se encuentra el iterador pasado como
394      parámetro.
395      \param ii Iterador que estamos recorriendo.
396      \return La refencia al nodo sobre el que se encuentra el iterador pasado como
397      parámetro.
398   */
399   static Node* node(child_iterator& ii) throw() { return *ii; }
400
401   /**
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.
405   */
406   static const Node* node(const_child_iterator& ii) throw() { return *ii; }
407
408   /**
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.
412   */
413   static const Attribute* attribute(const_attribute_iterator& ii) throw() { return *ii; }
414
415   /**
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.
419   */
420   static const Namespace* xnamespace(const_namespace_iterator& ii) throw() { return namespace_container::data(ii);; }
421
422 protected:
423   /**
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.
427   */
428   static Attribute* attribute(attribute_iterator& ii) throw() { return *ii; }
429
430 private:
431   std::string a_name;
432   const Node* a_parent;
433   Node* a_root;
434   Children a_children;
435   Attributes a_attributes;
436   Text* a_text;
437   const Namespace* a_namespace;
438
439   // Esta instancia sólo la creará el nodo root.
440   namespace_container* a_namespaces;
441
442   typedef Recycler <Node> node_pool;
443   typedef Recycler <Attribute> attribute_pool;
444   typedef Recycler <Text> text_pool;
445
446   typedef Recycler <Namespace> namespace_pool;
447
448   node_pool* a_node_pool;
449   attribute_pool* a_attribute_pool;
450   text_pool* a_text_pool;
451   namespace_pool* a_namespace_pool;
452
453   /* Para evitar que se pueda crear desde el exterior */
454   Node();
455
456   void setRoot(Node* root) throw() { a_root = root; }
457   void setName(const char* name) throw() { a_name = name; }
458
459   static const Attribute* find(const char* attrName, const_attribute_iterator, const_attribute_iterator) throw();
460
461   // Allow sort in compiler
462   attribute_iterator attribute_begin() throw() { return a_attributes.begin(); }
463   attribute_iterator attribute_end() throw() { return a_attributes.end(); }
464
465   friend class Parser;
466   friend class Allocator<Node>;
467   friend class XPath;
468   friend class Decompressor;
469   friend class Compiler;
470 };
471
472 }
473 }
474
475 #endif