First commit
[anna.git] / include / anna / core / util / TextComposer.hpp
1 // ANNA - Anna is Not 'N' Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
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
16 // distribution.
17 //     * Neither the name of Google Inc. 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.
20 //
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.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_core_util_TextComposer_hpp
38 #define anna_core_util_TextComposer_hpp
39
40 #include <vector>
41
42 #include <anna/core/RuntimeException.hpp>
43 #include <anna/core/mt/Mutex.hpp>
44 #include <anna/core/mt/Guard.hpp>
45 #include <anna/core//DataBlock.hpp>
46
47 #include <anna/core/util/TextVariable.hpp>
48
49 namespace anna {
50
51 class TextManager;
52 class TextVariable;
53
54 /**
55    Compositor de textos dinamicos.
56
57    Antes de invocar al metodo TextComposer::apply para obtener la cadena resultante de
58    sustituir los enginees dinamicos habra que establecer el valor de cada uno de
59    estos.
60
61    La indicacion de forma es igual a la usada en los metodos printf, sprintf, etc ...
62
63    Por ejemplo para establecer los valores de un compositor con la expresion:
64    "Error en el circuito ${circuit:%d} de la central ${central:%05d} procesando mensaje ${messageid:%s}", deberiamos tener
65    un codigo similar al que presentamos a continuacion:
66
67    \code
68    util::TextComposer& ttcc = textManager.find (N);
69
70    util::TextComposer::Protector textComposer (ttcc);
71    textComposer ["circuit"] = a;
72    textComposer ["central"] = b;
73    textComposer ["messageid"] = c;
74
75    // Una vez hecho esto podemos obtener el texto
76    std::cout << textComposer.apply () << std::endl;
77    \endcode
78
79    Donde hemos hecho las siguientes suposiciones:
80       \li \em textManager es un gestor de texto definido dentro del ambito del ejemplo.
81       \li \em N es el numero del compositor que deberia ser creado previamente indicando
82       la expresion usada en el ejemplo.
83       \li \em a Es una variable de tipo entero.
84       \li \em b Es una variable de tipo entero.
85       \li \em c Es una variable de tipo cadena.
86 */
87 class TextComposer : std::vector <TextVariable*> {
88   typedef std::vector <TextVariable*> container;
89   typedef container::iterator variable_iterator;
90   typedef container::const_iterator const_variable_iterator;
91
92 public:
93
94   /**
95      Destructor.
96   */
97   ~TextComposer();
98
99   TextVariable& operator[](const char* varName) throw(RuntimeException) {
100     return *(find(varName, Exception::Mode::Throw));
101   }
102
103   /**
104    * Método que realiza la interpretación del texto de esta instancia.
105    * Si la instancia se crea mediante un #util::TextManager no es necesario invocar a este método.
106    */
107   void initialize() throw(RuntimeException);
108
109   /**
110      Devuelve el identificador del compositor, que coincidira con el indicado a la hora
111      de crear el compositor mediante el metodo TextManager::create.
112      \return El identificador del compositor.
113   */
114   const int getId() const throw() { return a_id; }
115
116   /**
117      Devuelve el nº de variables asociadas al texto.
118      \return el nº de variables asociadas al texto.
119   */
120   int getNumberOfVariables() const throw() { return container::size(); }
121
122   /**
123      Devuelve una cadena con la informacion relevante de este objeto.
124      \return Una cadena con la informacion relevante de este objeto.
125   */
126   String asString() const throw();
127
128 protected:
129   /**
130      Constructor.
131      \param id Identificador del compositor de texto.
132      \param expression Expression asociada al compositor. El numero de variables que hay que
133      establecer antes de invocar a apply dependera de este texto.
134   */
135   TextComposer(const int id, const char* expression) : a_id(id), a_expression(expression), a_prefix(NULL), a_buffer(true) {;}
136
137   /**
138      Crea el texto teniendo en cuenta la expression y el contenido de las  variables asociadas.
139      \return El texto teniendo en cuenta la expression y el contenido de las  variables asociadas.
140   */
141   String apply() const throw(RuntimeException);
142
143   /**
144    * Devuelve la instancia de la variable a la que apunta el iterador.
145    * return la instancia de la variable a la que apunta el iterador.
146    */
147   static TextVariable* textVariable(variable_iterator ii) throw() { return *ii; }
148
149   /**
150    * Devuelve la instancia de la variable a la que apunta el iterador.
151    * return la instancia de la variable a la que apunta el iterador.
152    */
153   static const TextVariable* textVariable(const_variable_iterator ii) throw() { return *ii; }
154
155 private:
156   const int a_id;
157   const String a_expression;
158   String* a_prefix;
159   Mutex a_mutex;
160   mutable DataBlock a_buffer;
161
162   TextComposer(const TextComposer&);
163
164   TextVariable* find(const char* name, const Exception::Mode::_v) throw(RuntimeException);
165   void lock() throw(RuntimeException) { a_mutex.lock(); }
166   void unlock() throw() { a_mutex.unlock(); }
167
168   static TextVariable::Type::_v calculeType(const char* format) throw(RuntimeException);
169
170   friend class TextManager;
171 //   friend class Guard <TextComposer>;
172 //   friend class Protector;
173 };
174
175 }
176
177 #endif
178