bug in RC
[anna.git] / include / anna / core / util / TextComposer.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_core_util_TextComposer_hpp
10 #define anna_core_util_TextComposer_hpp
11
12 #include <vector>
13
14 #include <anna/core/RuntimeException.hpp>
15 #include <anna/core/mt/Mutex.hpp>
16 #include <anna/core/mt/Guard.hpp>
17 #include <anna/core//DataBlock.hpp>
18
19 #include <anna/core/util/TextVariable.hpp>
20
21 namespace anna {
22
23 class TextManager;
24 class TextVariable;
25
26 /**
27    Compositor de textos dinamicos.
28
29    Antes de invocar al metodo TextComposer::apply para obtener la cadena resultante de
30    sustituir los enginees dinamicos habra que establecer el valor de cada uno de
31    estos.
32
33    La indicacion de forma es igual a la usada en los metodos printf, sprintf, etc ...
34
35    Por ejemplo para establecer los valores de un compositor con la expresion:
36    "Error en el circuito ${circuit:%d} de la central ${central:%05d} procesando mensaje ${messageid:%s}", deberiamos tener
37    un codigo similar al que presentamos a continuacion:
38
39    \code
40    util::TextComposer& ttcc = textManager.find (N);
41
42    util::TextComposer::Protector textComposer (ttcc);
43    textComposer ["circuit"] = a;
44    textComposer ["central"] = b;
45    textComposer ["messageid"] = c;
46
47    // Una vez hecho esto podemos obtener el texto
48    std::cout << textComposer.apply () << std::endl;
49    \endcode
50
51    Donde hemos hecho las siguientes suposiciones:
52       \li \em textManager es un gestor de texto definido dentro del ambito del ejemplo.
53       \li \em N es el numero del compositor que deberia ser creado previamente indicando
54       la expresion usada en el ejemplo.
55       \li \em a Es una variable de tipo entero.
56       \li \em b Es una variable de tipo entero.
57       \li \em c Es una variable de tipo cadena.
58 */
59 class TextComposer : std::vector <TextVariable*> {
60   typedef std::vector <TextVariable*> container;
61   typedef container::iterator variable_iterator;
62   typedef container::const_iterator const_variable_iterator;
63
64 public:
65
66   /**
67      Destructor.
68   */
69   ~TextComposer();
70
71   TextVariable& operator[](const char* varName) throw(RuntimeException) {
72     return *(find(varName, Exception::Mode::Throw));
73   }
74
75   /**
76    * Método que realiza la interpretación del texto de esta instancia.
77    * Si la instancia se crea mediante un #util::TextManager no es necesario invocar a este método.
78    */
79   void initialize() throw(RuntimeException);
80
81   /**
82      Devuelve el identificador del compositor, que coincidira con el indicado a la hora
83      de crear el compositor mediante el metodo TextManager::create.
84      \return El identificador del compositor.
85   */
86   const int getId() const throw() { return a_id; }
87
88   /**
89      Devuelve el nº de variables asociadas al texto.
90      \return el nº de variables asociadas al texto.
91   */
92   int getNumberOfVariables() const throw() { return container::size(); }
93
94   /**
95      Devuelve una cadena con la informacion relevante de este objeto.
96      \return Una cadena con la informacion relevante de este objeto.
97   */
98   String asString() const throw();
99
100 protected:
101   /**
102      Constructor.
103      \param id Identificador del compositor de texto.
104      \param expression Expression asociada al compositor. El numero de variables que hay que
105      establecer antes de invocar a apply dependera de este texto.
106   */
107   TextComposer(const int id, const char* expression) : a_id(id), a_expression(expression), a_prefix(NULL), a_buffer(true) {;}
108
109   /**
110      Crea el texto teniendo en cuenta la expression y el contenido de las  variables asociadas.
111      \return El texto teniendo en cuenta la expression y el contenido de las  variables asociadas.
112   */
113   String apply() const throw(RuntimeException);
114
115   /**
116    * Devuelve la instancia de la variable a la que apunta el iterador.
117    * return la instancia de la variable a la que apunta el iterador.
118    */
119   static TextVariable* textVariable(variable_iterator ii) throw() { return *ii; }
120
121   /**
122    * Devuelve la instancia de la variable a la que apunta el iterador.
123    * return la instancia de la variable a la que apunta el iterador.
124    */
125   static const TextVariable* textVariable(const_variable_iterator ii) throw() { return *ii; }
126
127 private:
128   const int a_id;
129   const String a_expression;
130   String* a_prefix;
131   Mutex a_mutex;
132   mutable DataBlock a_buffer;
133
134   TextComposer(const TextComposer&);
135
136   TextVariable* find(const char* name, const Exception::Mode::_v) throw(RuntimeException);
137   void lock() throw(RuntimeException) { a_mutex.lock(); }
138   void unlock() throw() { a_mutex.unlock(); }
139
140   static TextVariable::Type::_v calculeType(const char* format) throw(RuntimeException);
141
142   friend class TextManager;
143 //   friend class Guard <TextComposer>;
144 //   friend class Protector;
145 };
146
147 }
148
149 #endif
150