Remove operation help.
[anna.git] / include / anna / dbos / ObjectFacade.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_dbos_ObjectFacade_hpp
10 #define anna_dbos_ObjectFacade_hpp
11
12 #include <anna/core/RuntimeException.hpp>
13
14 #include <anna/dbms/DatabaseException.hpp>
15
16 #include <anna/dbos/StorageArea.hpp>
17 #include <anna/dbos/Creator.hpp>
18 #include <anna/dbos/Loader.hpp>
19 #include <anna/dbos/Recorder.hpp>
20 #include <anna/dbos/Eraser.hpp>
21
22 namespace anna {
23
24 namespace dbms {
25 class Connection;
26 }
27
28 namespace dbos {
29
30 class Object;
31
32 /**
33    Clase que facilita el acceso y uso de las clases encargadas de la instanciacion de objetos a partir de los datos
34    contenidos en un medio fisico, que normalmente seria la tabla de una base de datos.
35
36    \param T clase debe ser heredada de anna::dbos::Object.
37
38    Ejemplo de definicion de una clase usando esta interfaz:
39
40    \include dbos_demo.p/oodb.d/hdrs/dbos_demo.oodb.Table01.h
41
42    Ejemplo de implementacion de la clase correspondiente a la definicion:
43
44    \include dbos_demo.p/oodb.d/oodb.Table01.cc
45
46    \see dbos_declare_object
47    \see dbos_prepare_object
48 */
49 template <typename T> class ObjectFacade {
50 public:
51   /**
52      Devuelve un numerico que puede ser usado en la definicion del area de almacenamiento.
53
54      \return Un numerico que puede ser usado en la definicion del area de almacenamiento.
55      \see Database::createStorageArea
56   */
57   static StorageId getStorageAreaId() throw() { return (StorageId) anna_ptrnumber_cast(&st_storageArea); }
58
59   /**
60       Devuelve el area de almacenamiento asociado a esta clase.
61       \return Devuelve el area de almacenamiento asociado a esta clase.
62   */
63   static StorageArea* getStorageArea() throw() { return st_storageArea; }
64
65   /**
66      Establece el area de almacenamiento asociado a esta clase, que deberiaser creado mediante la invocacin al metodo
67      Database::createStorageArea.
68
69      \param storageArea area de almacenamiento asociada esta clase.
70
71      \warning El area de almacenamiento debe establecerse antes de invocar a cualquier otro metodo de esta clase.
72   */
73   static void setStorageArea(StorageArea* storageArea) throw() {
74     (st_storageArea = storageArea)->setSizeof(sizeof(T));
75   }
76
77   /**
78      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
79      una clase C++.
80
81      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
82      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
83      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
84      otra combinacion de columnas que lo identifiquen univocamente.
85
86      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
87      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
88      que deseamos cargar en memoria.
89
90      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
91      que al inicializar el area de almacenamiento asociado a esta clase se halla indicado un \em errorCode
92      igual a -1 en otro caso si no encuentra el objeto que cumpla el patron devolveria  una
93      excepcion.
94
95      \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
96      cuando dejemos de usar la instancia.
97   */
98   static T* instance(dbms::Connection& connection, Loader& loader)
99   throw(RuntimeException, dbms::DatabaseException) {
100     if(st_storageArea == NULL) {
101       std::string msg(loader.asString());
102       msg += " | ObjectFacade uninitialized ";
103       throw RuntimeException(msg, ANNA_FILE_LOCATION);
104     }
105
106     return static_cast <T*>(st_storageArea->instance(connection, loader));
107   }
108
109   /**
110      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
111      una clase C++.
112
113      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
114      debe cargar.
115
116      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
117      que deseamos cargar en memoria.
118
119      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
120      que al inicializar el area de almacenamiento asociado a esta clase se halla indicado un \em errorCode
121      igual a -1 en otro caso si no encuentra el objeto que cumpla el patron devolveria  una
122      excepcion.
123
124      \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
125      cuando dejemos de usar la instancia.
126   */
127   static T* instance(Loader& loader)
128   throw(RuntimeException, dbms::DatabaseException) {
129     if(st_storageArea == NULL) {
130       std::string msg(loader.asString());
131       msg += " | ObjectFacade uninitialized ";
132       throw RuntimeException(msg, ANNA_FILE_LOCATION);
133     }
134
135     return static_cast <T*>(st_storageArea->instance(loader));
136   }
137
138   /**
139       Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
140       una clase C++.
141
142       Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
143       debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
144       en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
145       otra combinacion de columnas que lo identifiquen univocamente.
146
147       \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
148       \param  crossedLoader Cargador encargado de encontrar la clave principal a aplicar con el #Loader
149       recibido como parámetro en base a una clave alternativa contenida en el mismo.
150       \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
151       que deseamos cargar en memoria.
152
153       \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
154       que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
155       caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
156
157       \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
158       cuando dejemos de usar la instancia.
159    */
160   static T* instance(dbms::Connection& connection, CrossedLoader& crossedLoader,  Loader& loader)
161   throw(RuntimeException, dbms::DatabaseException) {
162     if(st_storageArea == NULL) {
163       std::string msg(loader.asString());
164       msg += " | ObjectFacade uninitialized ";
165       throw RuntimeException(msg, ANNA_FILE_LOCATION);
166     }
167
168     return static_cast <T*>(st_storageArea->instance(connection, crossedLoader, loader));
169   }
170
171   /**
172       Crea un objeto en el area de almacenamiento un y lo prepara para ser transferido al medio fisico
173       si fuera necesario.
174
175       Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
176       debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
177       en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
178       otra combinacion de columnas que lo identifiquen univocamente.
179
180       \param connection Conexion usada si fuera necesario acceder al medio fisico.
181       \param creator Creador encargado de generar el objeto de forma que sea facil de localizar posteriormente
182       en el area de almacenamiento.
183
184       \return La nueva instancia que cumple el patron establecido por el creador.
185
186       \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
187       cuando dejemos de usar la instancia.
188    */
189   static T* create(dbms::Connection& connection, Creator& creator)
190   throw(RuntimeException, dbms::DatabaseException) {
191     if(st_storageArea == NULL) {
192       std::string msg(creator.asString());
193       msg += " | ObjectFacade uninitialized ";
194       throw RuntimeException(msg, ANNA_FILE_LOCATION);
195     }
196
197     return static_cast <T*>(st_storageArea->create(connection, creator));
198   }
199
200   /**
201       Devuelve la informacion de un objeto cargado desde el medio fisico.
202
203       Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
204       debe buscar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
205       en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
206       otra combinacion de columnas que lo identifiquen univocamente.
207
208       \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
209
210       \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL si el
211       objeto no fue cargado en el area de almacenamiento.
212
213       \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
214       cuando dejemos de usar la instancia.
215    */
216   static T* find(Loader& loader)
217   throw(RuntimeException) {
218     if(st_storageArea == NULL) {
219       std::string msg(loader.asString());
220       msg += " | ObjectFacade uninitialized ";
221       throw RuntimeException(msg, ANNA_FILE_LOCATION);
222     }
223
224     return static_cast <T*>(st_storageArea->find(loader));
225   }
226
227   /**
228      Habilita la reutilizacion del espacio de memoria ocupado por un objeto alojado en el area de almacenamiento.
229
230      Este metodo no saca al objeto de la memoria de almacenamiento, sino que marca su espacio de memoria
231      como subceptible de ser reutilizado. De esta forma, si el numero de objetos cargados en memoria se
232      acerca al tamao maximo indicado en la inicializacion, se intentara reusar espacios libres en vez
233      de continuar ampliando la memoria reservada.
234
235      \param t Instancia del tipo T que vamos a liberar.
236
237      \warning Si el objeto recibido como parametro no fue reservado mediate alguno de los metodos de reserva de
238      objetos ofrecidos por esta clase no tendra ningun efecto.
239   */
240   static void release(T*& t)
241   throw() {
242     if(st_storageArea == NULL)
243       return;
244
245     try {
246       st_storageArea->release(reinterpret_cast <Object**>(&t));
247     } catch(RuntimeException& ex) {
248       ex.trace();
249     }
250   }
251
252   /**
253      Descarga todos los objetos contenidos en el area de almacenamiento.
254   */
255   static void clear()
256   throw(RuntimeException) {
257     if(st_storageArea == NULL)
258       throw RuntimeException("ObjectFacade uninitialized ", ANNA_FILE_LOCATION);
259
260     st_storageArea->clear();
261   }
262
263   /**
264      Devuelve de una copia del objeto recibido como parametro e incrementa la cuenta de utilizacion
265      asociada a la instancia.
266
267      \param t Instancia del tipo T obtenida mediate el metodo #instance.
268
269      \return Una copia del objeto recibido como parametro. Si el parametro recibido es NULL devolveria NULL.
270
271      \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
272      cuando dejemos de usar la instancia.
273   */
274   static T* duplicate(const T* t)
275   throw(RuntimeException) {
276     if(st_storageArea == NULL)
277       throw RuntimeException("ObjectFacade uninitialized ", ANNA_FILE_LOCATION);
278
279     return static_cast <T*>(st_storageArea->duplicate(t));
280   }
281
282   /**
283      Permite conocer si un determinado objeto esta alojado en el area de almacenamiento.
284
285      \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
286
287      \return \em true Si el objeto identificado por el Loader esta en el area de almacenamiento o
288      \em false en otro caso.
289   */
290   static bool isLoaded(const Loader& loader)
291   throw(RuntimeException) {
292     if(st_storageArea == NULL)
293       throw RuntimeException("ObjectFacade uninitialized ", ANNA_FILE_LOCATION);
294
295     return st_storageArea->isLoaded(loader);
296   }
297
298   /**
299      Transfiere la informacion del objeto recibido como parametro al medio fisico usando el Recorder
300      recibido como parametro.
301
302      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
303      \param recorder Grabador usado para transferir los datos al medio fisico.
304   */
305   static void apply(dbms::Connection& connection, Recorder& recorder)
306   throw(RuntimeException, dbms::DatabaseException) {
307     if(st_storageArea == NULL) {
308       std::string msg(recorder.asString());
309       msg += " | ObjectFacade uninitialized";
310       throw RuntimeException(msg, ANNA_FILE_LOCATION);
311     }
312
313     st_storageArea->apply(connection, recorder);
314   }
315
316   /**
317      Elimina la informacion del objeto recibido como parametro del medio fisico usando el Eraser
318      recibido como parametro.
319
320      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
321      \param eraser Objecto usado para eliminar los datos al medio fisico.
322
323      \warning Si la cuanta de utilizacion de T es 1 se liberaria en otro caso se devolveria una excepcion.
324   */
325   static void apply(dbms::Connection& connection, Eraser& eraser)
326   throw(RuntimeException, dbms::DatabaseException) {
327     if(st_storageArea == NULL) {
328       std::string msg(eraser.asString());
329       msg += " | ObjectFacade uninitialized";
330       throw RuntimeException(msg, ANNA_FILE_LOCATION);
331     }
332
333     st_storageArea->apply(connection, eraser);
334   }
335
336   /**
337      Elimina toda la informacion referente al objeto recibido como parametro, siempre y cuando
338      solo tenga un unica referencia activa. Descarga el objeto de la memoria de almacenamiento,
339
340      \param t Instancia del tipo T que vamos a descargar de la memoria de almacenamiento.
341
342      \warning \li Si el objeto recibido como parametro no fue reservado mediate #instance no tiene
343      ningun efecto. \li La instancia a liberar solo puede tener 1 en su cuenta de utilizacion.
344      \li La memoria asignada a la instancia recibida es liberada, por lo que podemos evitar la invocacion
345      al metodo #release para esta instancia.
346   */
347   static void erase(T*& t)
348   throw(RuntimeException) {
349     if(st_storageArea == NULL)
350       return;
351
352     st_storageArea->erase(reinterpret_cast <Object**>(&t));
353   }
354
355   /**
356      Devuelve el puntero sobre el que estaria posicionado el iterador recibido como parametro.
357      \return El puntero sobre el que estaria posicionado el iterador recibido como parametro.
358   */
359   static T* data(StorageArea::iterator& ii) throw() { return static_cast <T*>(StorageArea::data(ii)); }
360
361   /**
362      Devuelve el puntero sobre el que estaria posicionado el iterador recibido como parametro.
363      \return El puntero sobre el que estaria posicionado el iterador recibido como parametro.
364   */
365   static const T* data(StorageArea::const_iterator& ii) throw() { return static_cast <const T*>(StorageArea::data(ii)); }
366
367   /**
368      Metodo creador de nuevas instancias de la clase T.
369      \return Una nueva instancia del tipo de objeto T.
370      \warning Solo deberia ser llamado desde anna::comm::StorageArea cuando sea preciso crear
371      nuevas instancias de objetos.
372   */
373   static Object* allocator() throw() { return new T; }
374
375 protected:
376   static StorageArea* st_storageArea;
377
378   /**
379      Constructor.
380   */
381   ObjectFacade() {}
382 };
383
384 }
385 }
386
387 /**
388    Definicion a la que hay que invocar en la implementacion de la clase que hereda
389    de anna::dbos::ObjectFacade.
390
391    \param T Nombre de la clase que vamos a tratar en el ambito de C++.
392 */
393 #define dbos_prepare_object(T) \
394    template <> anna::dbos::StorageArea* anna::dbos::ObjectFacade< T >::st_storageArea = NULL
395
396 /**
397    Definicion a la que hay que invocar dentro de la definicion de la clase que hereda
398    de anna::dbos::ObjectFacade.
399
400    \param T Nombre de la clase que vamos a tratar en el ambito de C++.
401 */
402 #define dbos_declare_object(T) \
403    friend class anna::dbos::ObjectFacade <T>
404
405
406 #endif