Updated license
[anna.git] / include / anna / http / wims20 / Abstract.hpp
1 // ANNA - Anna is Not Nothingness 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_http_wims20_Abstract_hpp
38 #define anna_http_wims20_Abstract_hpp
39
40 #include <vector>
41
42 #include <anna/core/RuntimeException.hpp>
43 #include <anna/core/util/Recycler.hpp>
44
45 namespace anna {
46
47 namespace http {
48
49 namespace wims20 {
50
51 /**
52    Permite interpretar una URI según las recomendaciones de WIMS 2.0, lo que facilita
53    el desarrollo de aplicaciones integradas en Web 2.0; estas recomendaciones indican
54    cómo debe formarse la petición Abstract (REpresentational State Transfer) para permitir
55    el desarrollo de cualquier servicio.
56
57    El formato general de una URI según la recomendación de WIMS 2.0 es:
58
59    <p>
60 http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters
61    </p>
62
63    Dónde los campos tienen siguen la siguiente especificación:
64    \li http://domain-openapis: Identifica el recurso del Open API. Formará parte de la configuración
65    de nuestro API (servicio) particular.
66    \li path-openapis: Recurso opcional que ajusta la ruta hacia los recursos de éste API. Formará parte
67    de la configuración de nuestro API (servicio) particular.
68    \li serviceID: Identificador de recurso.
69    \li guid: Identificador del usuario que solicita la petición.
70    \li other_possible_level: Opcionalmente se pueden indicar tantos niveles jerárquicos como fuera
71    necesario para el servicio.
72    \li query_parameters: Lista de parámetros. Si hay más de un parámetro se separará con '&'.
73 */
74 class Abstract {
75 public:
76   typedef std::vector <std::string*> other_level_container;
77   typedef other_level_container::iterator other_level_iterator;
78   typedef other_level_container::const_iterator const_other_level_iterator;
79
80   /**
81    * Los parámetros se ordenan en el mismo orden en que fueron indicados
82    * por eso no se guardan sobre un std::map, ya que al volcarlos sobre la
83    * cadena que actuará como URI aparecerían ordenados alfabéticamente y
84    * quizás el servidor no lo espera así.
85    */
86   typedef std::pair <std::string*, std::string*> parameter_pkv;
87   typedef std::vector <parameter_pkv> parameter_container;
88   typedef parameter_container::iterator parameter_iterator;
89   typedef parameter_container::const_iterator const_parameter_iterator;
90
91   /**
92    * Destructor
93    */
94   virtual ~Abstract();
95
96   /**
97    * Devuelve el campo \em domain-openapis establecido en el contructor.
98    * \return el campo \em domain-openapis establecido en el contructor.
99    */
100   const std::string& getDomain() const throw() { return a_domain; }
101
102   /**
103    * Devuelve el campo \em path-openapis
104    * \return El campo \em path-openapis, puede ser NULL.
105    */
106   const std::string* getPath() const throw() { return a_path; }
107
108   /**
109    * Devuelve el servicio de la OpenAPI.
110    * \param Identificador de servicio usado en la OpenAPI.
111    */
112   const std::string& getServiceID() const throw() { return a_serviceID; }
113
114   /**
115    * Devuelve identificador de usuario que interacciona con el servicio.
116    * \return El identificador de usuario que interacciona con el servicio.
117    */
118   const std::string& getGUID() const throw() { return a_guid; }
119
120   /**
121    * Establece el servicio de la OpenAPI.
122    * \param serviceID Identificador de servicio usado en la OpenAPI.
123    */
124   void setServiceID(const std::string& serviceID) throw() { a_serviceID = serviceID; a_fixedPart.clear(); }
125
126   /**
127    * Establece el identificador de usuario que interacciona con el servicio.
128    * \param guid Identificador de usuario. Dónde por usuario se entiende cualquier elemento
129    * que pueda intereccionar con nuestro servicio
130    */
131   void setGUID(const std::string& guid) throw() { a_guid = guid; a_fixedPart.clear(); }
132
133   /**
134    * Devuelve \em true si la estructura contiene parámetros o \em false en otro caso.
135    * \return \em true si la estructura contiene parámetros o \em false en otro caso.
136    */
137   bool hasParameters() const throw() { return a_parameters != NULL && a_parameters->empty() == false; }
138
139   /**
140    * Devuelve \em true si la estructura contiene niveles opcionales o \em false en otro caso.
141    * \return \em true si la estructura contiene niveles opcionales o \em false en otro caso.
142    */
143   bool hasOtherLevels() const throw() { return a_otherLevels != NULL && a_otherLevels->empty() == false; }
144
145   /**
146    * Limpia el contenido asociado al parámetro \em other_possible_level. Sólo debería
147    * invocarse a este método en caso de que el servicio destino de la petición haya cambiado.
148    */
149   virtual void clearOtherLevels() throw();
150
151   /**
152    * Limpia el contenido asociado a los parámetros. Sólo debería invocarse a éste método en caso
153    * de que el número de parámetros a enviar sea distinto al de la petición anterior.
154    * Si son los mismos parámetros con el mismo nombre, deberíamos reutilizar el máximo número
155    * de veces.
156    */
157   virtual void clearParameters() throw();
158
159   /**
160    * Inicializa los toda la información asociada a esta instancia.
161    */
162   void clear() throw() {
163     clearOtherLevels();
164     clearParameters();
165   }
166
167   /**
168    * Devuelce una cadena con la información relevante sobre esta clase.
169    * \return una cadena con la información relevante sobre esta clase.
170    */
171   std::string asString() const throw();
172
173   /**
174    * Devuelve un iterator al comienzo de la lista de niveles adicionales.
175    * \return un iterator al comienzo de la lista de niveles adicionales.
176    * \warning Sólo se puede invocar a este método si #hasOtherLevels devuelve \em true.
177    */
178   other_level_iterator other_level_begin() throw() { return a_otherLevels->begin(); }
179
180   /**
181    * Devuelve un iterator al final de la lista de niveles adicionales.
182    * \return un iterator al final de la lista de niveles adicionales.
183    * \warning Sólo se puede invocar a este método si #hasOtherLevels devuelve \em true.
184    */
185   other_level_iterator other_level_end() throw() { return a_otherLevels->end(); }
186
187   /**
188    * Devuelve el valor asociado al iterador.
189    * \param ii Iterador sobre los niveles opcionales.
190    * \return el valor asociado al iterador.
191    */
192   static std::string* otherLevel(other_level_iterator ii) throw() { return *ii; }
193
194   /**
195    * Devuelve un iterator al comienzo de la lista de niveles adicionales.
196    * \return un iterator al comienzo de la lista de niveles adicionales.
197    * \warning Sólo se puede invocar a este método si #hasOtherLevels devuelve \em true.
198    */
199   const_other_level_iterator other_level_begin() const throw() { return a_otherLevels->begin(); }
200
201   /**
202    * Devuelve un iterator al final de la lista de niveles adicionales.
203    * \return un iterator al final de la lista de niveles adicionales.
204    * \warning Sólo se puede invocar a este método si #hasOtherLevels devuelve \em true.
205    */
206   const_other_level_iterator other_level_end() const throw() { return a_otherLevels->end(); }
207
208   /**
209    * Devuelve el valor asociado al iterador.
210    * \param ii Iterador sobre los niveles opcionales.
211    * \return el valor asociado al iterador.
212    */
213   static const std::string& otherLevel(const_other_level_iterator ii) throw() { return **ii; }
214
215   /**
216    * Devuelve un iterator al comienzo de la lista de niveles adicionales.
217    * \return un iterator al comienzo de la lista de niveles adicionales.
218    * \warning Sólo se puede invocar a este método si #hasParameters devuelve \em true.
219    */
220   const_parameter_iterator parameter_begin() const throw() { return a_parameters->begin(); }
221
222   /**
223    * Devuelve un iterator al final de la lista de niveles adicionales.
224    * \return un iterator al final de la lista de niveles adicionales.
225    * \warning Sólo se puede invocar a este método si #hasParameters devuelve \em true.
226    */
227   const_parameter_iterator parameter_end() const throw() { return a_parameters->end(); }
228
229   /**
230    * Devuelve el nombre del parámetro asociado al iterador.
231    * \param ii Iterador sobre los niveles opcionales.
232    * \return el nombre del parámetro asociado al iterador.
233    */
234   static const std::string& parameter_name(const_parameter_iterator ii) throw() { return *(ii->first); }
235
236   /**
237    * Devuelve el valor del parámetro asociado al iterador.
238    * \param ii Iterador sobre los niveles opcionales.
239    * \return el valor del parámetro asociado al iterador.
240    */
241   static const std::string& parameter_value(const_parameter_iterator ii) throw() { return *(ii->second); }
242
243 protected:
244   other_level_container* a_otherLevels;
245   parameter_container* a_parameters;
246
247   /**
248    * Contructor indicando el parámetro opcional \em path-openapis. Estos dos parámetros se obtendrá como
249    * parte de la configuración de nuestro sistema.
250    * \param domain: Identifica el recurso del OpenAPI.
251    * \param path: Parámetro opcional que ajusta la ruta hacia los recusos de éste API.
252    */
253   Abstract(const char* whatis, const std::string& domain, const std::string& path);
254
255   /**
256    * Constructor que no usará el parámetro opcional \em path-openapis. Este parámetro se obtendrá como
257    * parte de la configuración de nuestro sistema.
258    * \param domain: Identifica el recurso del OpenAPI.
259    */
260   explicit Abstract(const char* whatis, const std::string& domain);
261
262   /**
263    * Calcula la parte fija de la petición en base a #calculeShortFixedPart, el \em serviceID y el \em GUID.
264    * Mientras estos dos últimos campos se mantengan constrantes, el resultado de este método no cambia.
265    * \return Una cadena con la parte fija de la petición.
266    */
267   const std::string& calculeFixedPart() throw(RuntimeException);
268
269   /**
270    * Calcula la parte fija corta de la petición. Tiene en cuenta el \em domain-openapis y si existe
271    * el path-openapis. Si fuera necesario incluye el identificador de protocolo "http://".
272    * \return Una cadena con la parte fija corta de la petición.
273    */
274   const std::string& calculeShortFixedPart() throw(RuntimeException);
275
276   /**
277    * Optimiza la creación y liberación de cadenas que usa el proceso de interpretación continuamente.
278    * \warning Exclusivamente uso interno.
279    */
280   std::string* createString() throw(RuntimeException) { return a_string_pool.create(); }
281
282   /**
283    * Optimiza la creación y liberación de cadenas que usa el proceso de interpretación continuamente.
284    * \warning Exclusivamente uso interno.
285    */
286   std::string* createString(const char* value) throw(RuntimeException) {
287     std::string* result = a_string_pool.create();
288     *result = value;
289     return result;
290   }
291
292   /**
293    * Optimiza la creación y liberación de cadenas que usa el proceso de interpretación continuamente.
294    * \warning Exclusivamente uso interno.
295    */
296   std::string* createString(const std::string& value) throw(RuntimeException) { return createString(value.c_str()); }
297
298   /**
299    * Optimiza la creación y liberación de cadenas que usa el proceso de interpretación continuamente.
300    * \warning Exclusivamente uso interno.
301    */
302   void destroyString(std::string* str) throw() { a_string_pool.release(str); }
303
304   /**
305    * Amplía la lista de niveles.
306    * \param otherLevel Nombre del nivel con el que ampliar las lista.
307    */
308   void other_level_add(const std::string& otherLevel) throw(RuntimeException);
309
310   /**
311    * Amplía la lista de parámetros con una nueva pareja (Nombre, Valor).
312    * \param name Nombre del parámetro a crear.
313    * \param value Valor asociado al parámetro.
314    */
315   void parameter_set(const std::string& name, const std::string& value) throw(RuntimeException);
316
317   /**
318    * Devuelve un iterator al comienzo de la lista de niveles adicionales.
319    * \return un iterator al comienzo de la lista de niveles adicionales.
320    * \warning Sólo se puede invocar a este método si #hasParameters devuelve \em true.
321    */
322   parameter_iterator parameter_begin() throw() { return a_parameters->begin(); }
323
324   /**
325    * Devuelve un iterator al final de la lista de niveles adicionales.
326    * \return un iterator al final de la lista de niveles adicionales.
327    * \warning Sólo se puede invocar a este método si #hasParameters devuelve \em true.
328    */
329   parameter_iterator parameter_end() throw() { return a_parameters->end(); }
330
331   /**
332    * Devuelve el nombre del parámetro asociado al iterador.
333    * \param ii Iterador sobre los niveles opcionales.
334    * \return el nombre del parámetro asociado al iterador.
335    */
336   static std::string* parameter_name(parameter_iterator ii) throw() { return ii->first; }
337
338   /**
339    * Devuelve el valor del parámetro asociado al iterador.
340    * \param ii Iterador sobre los niveles opcionales.
341    * \return el valor del parámetro asociado al iterador.
342    */
343   static std::string* parameter_value(parameter_iterator ii) throw() { return ii->second; }
344
345   /**
346    * Concatena las cadenas recibidas teniendo en entre ambas debe de haber un carácter '/'.
347    */
348   static void appendWithSlash(std::string& target, const std::string& other) throw();
349
350 private:
351   const std::string a_whatis;
352   const std::string a_domain;
353   std::string* a_path;
354   std::string a_serviceID;
355   std::string a_guid;
356   Recycler <std::string> a_string_pool;
357   std::string a_fixedPart;
358 };
359
360
361 }
362 }
363 }
364
365 #endif