Revert "Remove mysql and oracle resources for anna-ericsson project"
[anna.git] / include / anna / dbos / AutoObject.hpp
diff --git a/include/anna/dbos/AutoObject.hpp b/include/anna/dbos/AutoObject.hpp
new file mode 100644 (file)
index 0000000..6c3992e
--- /dev/null
@@ -0,0 +1,152 @@
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+#ifndef anna_dbos_AutoObject_hpp
+#define anna_dbos_AutoObject_hpp
+
+#include <anna/dbos/Object.hpp>
+
+namespace anna {
+
+namespace dbos {
+
+
+/**
+   Facilita el uso de los punteros a objectos obtenidos a partir de los datos guardados en un medio fisico.
+
+   La idea de esta clase es que el constructor y el destructor de esta clase cooperan para reservar y/o
+   liberar correctamente la instancia de T asociada a esta instancia.
+
+   \param T Clase que vamos a gestionar.
+
+   En el siguiente ejemplo podemos ver la forma habitual de trabajar con un objeto persistente tiene
+   el incoveniente de que tenemos que tener en cuenta cada una de las situaciones en las que la
+   referencia obtenida mediante el metodo \em instantiate debe ser liberada.
+
+   \code
+   void Application::getServerSocketsData (vector <SocketData>& serverSocketsData) const
+      throw (RuntimeException)
+   {
+      LOGMETHOD (TraceMethod ("anna::Application", "getServerSocketsData", ANNA_FILE_LOCATION));
+
+      Facility* facility (NULL);
+      FacilityLoader facilityLoader;
+
+      try {
+         facility = Facility::instantiate (facilityLoader.setKey (a_thisFacility));   // (1)
+         LOGDEBUG (Logger::write (Logger::Debug, facility->asString (), ANNA_FILE_LOCATION));
+
+         getSocketsData (getThisHostName (), facility->getName (), a_thisCell, a_thisInstance, serverSocketsData);
+
+         Facility::release (facility);
+      }
+      catch (dbos::DatabaseException& edbos) {
+         Facility::release (facility);
+         throw RuntimeException (edbos.getText (), ANNA_FILE_LOCATION);
+      }
+      catch (RuntimeException&) {   // Tenemos que capturar esta excepcion para liberar el recurso.
+         Facility::release (facility);
+         throw;
+      }
+   }
+   \endcode
+
+   Como podemos ver a continuacion el siguiente metodo es mucho mas sencillo y aporta la gran ventaja de que
+   el sistema trabaja por nosotros para liberar correctamente los recursos.
+
+   \code
+   void Application::getServerSocketsData (vector <SocketData>& serverSocketsData) const
+      throw (RuntimeException)
+   {
+      LOGMETHOD (TraceMethod ("anna::Application", "getServerSocketsData", ANNA_FILE_LOCATION));
+
+      AutoObject <Facility> facility;
+      FacilityLoader facilityLoader;
+
+      try {
+         facility = Facility::instantiate (facilityLoader.setKey (a_thisFacility));   // (1)
+
+         LOGDEBUG (Logger::write (Logger::Debug, facility->asString (), ANNA_FILE_LOCATION));
+
+         getSocketsData (getThisHostName (), facility->getName (), a_thisCell, a_thisInstance, serverSocketsData);
+      }
+      catch (dbos::DatabaseException& edbos) {
+         throw RuntimeException (edbos.getText (), ANNA_FILE_LOCATION);
+      }
+   }
+   \endcode
+*/
+template <typename T> class AutoObject {
+public:
+  /**
+     Constructor.
+     \param t Instancia del objeto asociado a esta instancia.
+     \warning La instancia deberia haber sido obtenida mediate la invocacion a \em T::instantiate de la
+     clase persistente.
+  */
+  explicit AutoObject(T* t) : a_t(t) {;}
+
+  /**
+     Constructor.
+  */
+  AutoObject() : a_t(NULL) {;}
+
+  /**
+     Destructor. Invoca al metodo \em T::release
+  */
+  ~AutoObject() { if(a_t != NULL) T::release(a_t); }
+
+  /**
+     Operador ->
+     Permite invocar a metodos de la clase T.
+     \return La instancia de la clase T asociada a esta instancia.
+  */
+  T* operator -> () const throw() { return a_t; }
+
+  /**
+     Operador copia.
+     \param t Referencia al objeto que vamos a tratar.
+     \return La instancia de la clase T asociada a esta instancia.
+  */
+  T* operator = (T* t) throw() {
+    if(a_t != t) {
+      T::release(a_t);
+      a_t = t;
+    }
+
+    return a_t;
+  }
+
+  /**
+     Operador copia.
+     \param other Referencia al objeto que vamos a tratar.
+     \return La instancia de la clase T asociada a esta instancia.
+  */
+  T* operator = (const AutoObject <T>& other) throw(RuntimeException) {
+    return (this != &other)  ? (*this = T::duplicate(other.a_t)) : a_t;
+  }
+
+  /**
+     Operador de conversion.
+     \return La instancia de la clase T asociada a esta instancia.
+  */
+  operator T*() const throw() { return a_t; }
+
+private:
+  T* a_t;
+};
+
+
+}
+}
+
+
+
+#endif
+
+