1 // ANNA - Anna is Not 'N' Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // https://bitbucket.org/testillano/anna
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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
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.
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.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #ifndef anna_dbos_ObjectFacade_hpp
38 #define anna_dbos_ObjectFacade_hpp
40 #include <anna/core/RuntimeException.hpp>
42 #include <anna/dbms/DatabaseException.hpp>
44 #include <anna/dbos/StorageArea.hpp>
45 #include <anna/dbos/Creator.hpp>
46 #include <anna/dbos/Loader.hpp>
47 #include <anna/dbos/Recorder.hpp>
48 #include <anna/dbos/Eraser.hpp>
61 Clase que facilita el acceso y uso de las clases encargadas de la instanciacion de objetos a partir de los datos
62 contenidos en un medio fisico, que normalmente seria la tabla de una base de datos.
64 \param T clase debe ser heredada de anna::dbos::Object.
66 Ejemplo de definicion de una clase usando esta interfaz:
68 \include dbos_demo.p/oodb.d/hdrs/dbos_demo.oodb.Table01.h
70 Ejemplo de implementacion de la clase correspondiente a la definicion:
72 \include dbos_demo.p/oodb.d/oodb.Table01.cc
74 \see dbos_declare_object
75 \see dbos_prepare_object
77 template <typename T> class ObjectFacade {
80 Devuelve un numerico que puede ser usado en la definicion del area de almacenamiento.
82 \return Un numerico que puede ser usado en la definicion del area de almacenamiento.
83 \see Database::createStorageArea
85 static StorageId getStorageAreaId() throw() { return (StorageId) anna_ptrnumber_cast(&st_storageArea); }
88 Devuelve el area de almacenamiento asociado a esta clase.
89 \return Devuelve el area de almacenamiento asociado a esta clase.
91 static StorageArea* getStorageArea() throw() { return st_storageArea; }
94 Establece el area de almacenamiento asociado a esta clase, que deberiaser creado mediante la invocacin al metodo
95 Database::createStorageArea.
97 \param storageArea area de almacenamiento asociada esta clase.
99 \warning El area de almacenamiento debe establecerse antes de invocar a cualquier otro metodo de esta clase.
101 static void setStorageArea(StorageArea* storageArea) throw() {
102 (st_storageArea = storageArea)->setSizeof(sizeof(T));
106 Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
109 Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
110 debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
111 en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
112 otra combinacion de columnas que lo identifiquen univocamente.
114 \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
115 \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
116 que deseamos cargar en memoria.
118 \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
119 que al inicializar el area de almacenamiento asociado a esta clase se halla indicado un \em errorCode
120 igual a -1 en otro caso si no encuentra el objeto que cumpla el patron devolveria una
123 \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
124 cuando dejemos de usar la instancia.
126 static T* instance(dbms::Connection& connection, Loader& loader)
127 throw(RuntimeException, dbms::DatabaseException) {
128 if(st_storageArea == NULL) {
129 std::string msg(loader.asString());
130 msg += " | ObjectFacade uninitialized ";
131 throw RuntimeException(msg, ANNA_FILE_LOCATION);
134 return static_cast <T*>(st_storageArea->instance(connection, loader));
138 Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
141 Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
144 \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
145 que deseamos cargar en memoria.
147 \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
148 que al inicializar el area de almacenamiento asociado a esta clase se halla indicado un \em errorCode
149 igual a -1 en otro caso si no encuentra el objeto que cumpla el patron devolveria una
152 \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
153 cuando dejemos de usar la instancia.
155 static T* instance(Loader& loader)
156 throw(RuntimeException, dbms::DatabaseException) {
157 if(st_storageArea == NULL) {
158 std::string msg(loader.asString());
159 msg += " | ObjectFacade uninitialized ";
160 throw RuntimeException(msg, ANNA_FILE_LOCATION);
163 return static_cast <T*>(st_storageArea->instance(loader));
167 Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
170 Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
171 debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
172 en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
173 otra combinacion de columnas que lo identifiquen univocamente.
175 \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
176 \param crossedLoader Cargador encargado de encontrar la clave principal a aplicar con el #Loader
177 recibido como parámetro en base a una clave alternativa contenida en el mismo.
178 \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
179 que deseamos cargar en memoria.
181 \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
182 que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
183 caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
185 \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
186 cuando dejemos de usar la instancia.
188 static T* instance(dbms::Connection& connection, CrossedLoader& crossedLoader, Loader& loader)
189 throw(RuntimeException, dbms::DatabaseException) {
190 if(st_storageArea == NULL) {
191 std::string msg(loader.asString());
192 msg += " | ObjectFacade uninitialized ";
193 throw RuntimeException(msg, ANNA_FILE_LOCATION);
196 return static_cast <T*>(st_storageArea->instance(connection, crossedLoader, loader));
200 Crea un objeto en el area de almacenamiento un y lo prepara para ser transferido al medio fisico
203 Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
204 debe cargar. 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.
208 \param connection Conexion usada si fuera necesario acceder al medio fisico.
209 \param creator Creador encargado de generar el objeto de forma que sea facil de localizar posteriormente
210 en el area de almacenamiento.
212 \return La nueva instancia que cumple el patron establecido por el creador.
214 \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
215 cuando dejemos de usar la instancia.
217 static T* create(dbms::Connection& connection, Creator& creator)
218 throw(RuntimeException, dbms::DatabaseException) {
219 if(st_storageArea == NULL) {
220 std::string msg(creator.asString());
221 msg += " | ObjectFacade uninitialized ";
222 throw RuntimeException(msg, ANNA_FILE_LOCATION);
225 return static_cast <T*>(st_storageArea->create(connection, creator));
229 Devuelve la informacion de un objeto cargado desde el medio fisico.
231 Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
232 debe buscar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
233 en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
234 otra combinacion de columnas que lo identifiquen univocamente.
236 \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
238 \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL si el
239 objeto no fue cargado en el area de almacenamiento.
241 \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
242 cuando dejemos de usar la instancia.
244 static T* find(Loader& loader)
245 throw(RuntimeException) {
246 if(st_storageArea == NULL) {
247 std::string msg(loader.asString());
248 msg += " | ObjectFacade uninitialized ";
249 throw RuntimeException(msg, ANNA_FILE_LOCATION);
252 return static_cast <T*>(st_storageArea->find(loader));
256 Habilita la reutilizacion del espacio de memoria ocupado por un objeto alojado en el area de almacenamiento.
258 Este metodo no saca al objeto de la memoria de almacenamiento, sino que marca su espacio de memoria
259 como subceptible de ser reutilizado. De esta forma, si el numero de objetos cargados en memoria se
260 acerca al tamao maximo indicado en la inicializacion, se intentara reusar espacios libres en vez
261 de continuar ampliando la memoria reservada.
263 \param t Instancia del tipo T que vamos a liberar.
265 \warning Si el objeto recibido como parametro no fue reservado mediate alguno de los metodos de reserva de
266 objetos ofrecidos por esta clase no tendra ningun efecto.
268 static void release(T*& t)
270 if(st_storageArea == NULL)
274 st_storageArea->release(reinterpret_cast <Object**>(&t));
275 } catch(RuntimeException& ex) {
281 Descarga todos los objetos contenidos en el area de almacenamiento.
284 throw(RuntimeException) {
285 if(st_storageArea == NULL)
286 throw RuntimeException("ObjectFacade uninitialized ", ANNA_FILE_LOCATION);
288 st_storageArea->clear();
292 Devuelve de una copia del objeto recibido como parametro e incrementa la cuenta de utilizacion
293 asociada a la instancia.
295 \param t Instancia del tipo T obtenida mediate el metodo #instance.
297 \return Una copia del objeto recibido como parametro. Si el parametro recibido es NULL devolveria NULL.
299 \warning Cada llamada a este metodo deberia tener su correspondiente liberacion invocando a #release
300 cuando dejemos de usar la instancia.
302 static T* duplicate(const T* t)
303 throw(RuntimeException) {
304 if(st_storageArea == NULL)
305 throw RuntimeException("ObjectFacade uninitialized ", ANNA_FILE_LOCATION);
307 return static_cast <T*>(st_storageArea->duplicate(t));
311 Permite conocer si un determinado objeto esta alojado en el area de almacenamiento.
313 \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
315 \return \em true Si el objeto identificado por el Loader esta en el area de almacenamiento o
316 \em false en otro caso.
318 static bool isLoaded(const Loader& loader)
319 throw(RuntimeException) {
320 if(st_storageArea == NULL)
321 throw RuntimeException("ObjectFacade uninitialized ", ANNA_FILE_LOCATION);
323 return st_storageArea->isLoaded(loader);
327 Transfiere la informacion del objeto recibido como parametro al medio fisico usando el Recorder
328 recibido como parametro.
330 \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
331 \param recorder Grabador usado para transferir los datos al medio fisico.
333 static void apply(dbms::Connection& connection, Recorder& recorder)
334 throw(RuntimeException, dbms::DatabaseException) {
335 if(st_storageArea == NULL) {
336 std::string msg(recorder.asString());
337 msg += " | ObjectFacade uninitialized";
338 throw RuntimeException(msg, ANNA_FILE_LOCATION);
341 st_storageArea->apply(connection, recorder);
345 Elimina la informacion del objeto recibido como parametro del medio fisico usando el Eraser
346 recibido como parametro.
348 \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
349 \param eraser Objecto usado para eliminar los datos al medio fisico.
351 \warning Si la cuanta de utilizacion de T es 1 se liberaria en otro caso se devolveria una excepcion.
353 static void apply(dbms::Connection& connection, Eraser& eraser)
354 throw(RuntimeException, dbms::DatabaseException) {
355 if(st_storageArea == NULL) {
356 std::string msg(eraser.asString());
357 msg += " | ObjectFacade uninitialized";
358 throw RuntimeException(msg, ANNA_FILE_LOCATION);
361 st_storageArea->apply(connection, eraser);
365 Elimina toda la informacion referente al objeto recibido como parametro, siempre y cuando
366 solo tenga un unica referencia activa. Descarga el objeto de la memoria de almacenamiento,
368 \param t Instancia del tipo T que vamos a descargar de la memoria de almacenamiento.
370 \warning \li Si el objeto recibido como parametro no fue reservado mediate #instance no tiene
371 ningun efecto. \li La instancia a liberar solo puede tener 1 en su cuenta de utilizacion.
372 \li La memoria asignada a la instancia recibida es liberada, por lo que podemos evitar la invocacion
373 al metodo #release para esta instancia.
375 static void erase(T*& t)
376 throw(RuntimeException) {
377 if(st_storageArea == NULL)
380 st_storageArea->erase(reinterpret_cast <Object**>(&t));
384 Devuelve el puntero sobre el que estaria posicionado el iterador recibido como parametro.
385 \return El puntero sobre el que estaria posicionado el iterador recibido como parametro.
387 static T* data(StorageArea::iterator& ii) throw() { return static_cast <T*>(StorageArea::data(ii)); }
390 Devuelve el puntero sobre el que estaria posicionado el iterador recibido como parametro.
391 \return El puntero sobre el que estaria posicionado el iterador recibido como parametro.
393 static const T* data(StorageArea::const_iterator& ii) throw() { return static_cast <const T*>(StorageArea::data(ii)); }
396 Metodo creador de nuevas instancias de la clase T.
397 \return Una nueva instancia del tipo de objeto T.
398 \warning Solo deberia ser llamado desde anna::comm::StorageArea cuando sea preciso crear
399 nuevas instancias de objetos.
401 static Object* allocator() throw() { return new T; }
404 static StorageArea* st_storageArea;
416 Definicion a la que hay que invocar en la implementacion de la clase que hereda
417 de anna::dbos::ObjectFacade.
419 \param T Nombre de la clase que vamos a tratar en el ambito de C++.
421 #define dbos_prepare_object(T) \
422 template <> anna::dbos::StorageArea* anna::dbos::ObjectFacade< T >::st_storageArea = NULL
425 Definicion a la que hay que invocar dentro de la definicion de la clase que hereda
426 de anna::dbos::ObjectFacade.
428 \param T Nombre de la clase que vamos a tratar en el ambito de C++.
430 #define dbos_declare_object(T) \
431 friend class anna::dbos::ObjectFacade <T>