Remove operation help.
[anna.git] / include / anna / dbos / AutoObject.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_AutoObject_hpp
10 #define anna_dbos_AutoObject_hpp
11
12 #include <anna/dbos/Object.hpp>
13
14 namespace anna {
15
16 namespace dbos {
17
18
19 /**
20    Facilita el uso de los punteros a objectos obtenidos a partir de los datos guardados en un medio fisico.
21
22    La idea de esta clase es que el constructor y el destructor de esta clase cooperan para reservar y/o
23    liberar correctamente la instancia de T asociada a esta instancia.
24
25    \param T Clase que vamos a gestionar.
26
27    En el siguiente ejemplo podemos ver la forma habitual de trabajar con un objeto persistente tiene
28    el incoveniente de que tenemos que tener en cuenta cada una de las situaciones en las que la
29    referencia obtenida mediante el metodo \em instantiate debe ser liberada.
30
31    \code
32    void Application::getServerSocketsData (vector <SocketData>& serverSocketsData) const
33       throw (RuntimeException)
34    {
35       LOGMETHOD (TraceMethod ("anna::Application", "getServerSocketsData", ANNA_FILE_LOCATION));
36
37       Facility* facility (NULL);
38       FacilityLoader facilityLoader;
39
40       try {
41          facility = Facility::instantiate (facilityLoader.setKey (a_thisFacility));   // (1)
42          LOGDEBUG (Logger::write (Logger::Debug, facility->asString (), ANNA_FILE_LOCATION));
43
44          getSocketsData (getThisHostName (), facility->getName (), a_thisCell, a_thisInstance, serverSocketsData);
45
46          Facility::release (facility);
47       }
48       catch (dbos::DatabaseException& edbos) {
49          Facility::release (facility);
50          throw RuntimeException (edbos.getText (), ANNA_FILE_LOCATION);
51       }
52       catch (RuntimeException&) {   // Tenemos que capturar esta excepcion para liberar el recurso.
53          Facility::release (facility);
54          throw;
55       }
56    }
57    \endcode
58
59    Como podemos ver a continuacion el siguiente metodo es mucho mas sencillo y aporta la gran ventaja de que
60    el sistema trabaja por nosotros para liberar correctamente los recursos.
61
62    \code
63    void Application::getServerSocketsData (vector <SocketData>& serverSocketsData) const
64       throw (RuntimeException)
65    {
66       LOGMETHOD (TraceMethod ("anna::Application", "getServerSocketsData", ANNA_FILE_LOCATION));
67
68       AutoObject <Facility> facility;
69       FacilityLoader facilityLoader;
70
71       try {
72          facility = Facility::instantiate (facilityLoader.setKey (a_thisFacility));   // (1)
73
74          LOGDEBUG (Logger::write (Logger::Debug, facility->asString (), ANNA_FILE_LOCATION));
75
76          getSocketsData (getThisHostName (), facility->getName (), a_thisCell, a_thisInstance, serverSocketsData);
77       }
78       catch (dbos::DatabaseException& edbos) {
79          throw RuntimeException (edbos.getText (), ANNA_FILE_LOCATION);
80       }
81    }
82    \endcode
83 */
84 template <typename T> class AutoObject {
85 public:
86   /**
87      Constructor.
88      \param t Instancia del objeto asociado a esta instancia.
89      \warning La instancia deberia haber sido obtenida mediate la invocacion a \em T::instantiate de la
90      clase persistente.
91   */
92   explicit AutoObject(T* t) : a_t(t) {;}
93
94   /**
95      Constructor.
96   */
97   AutoObject() : a_t(NULL) {;}
98
99   /**
100      Destructor. Invoca al metodo \em T::release
101   */
102   ~AutoObject() { if(a_t != NULL) T::release(a_t); }
103
104   /**
105      Operador ->
106      Permite invocar a metodos de la clase T.
107      \return La instancia de la clase T asociada a esta instancia.
108   */
109   T* operator -> () const throw() { return a_t; }
110
111   /**
112      Operador copia.
113      \param t Referencia al objeto que vamos a tratar.
114      \return La instancia de la clase T asociada a esta instancia.
115   */
116   T* operator = (T* t) throw() {
117     if(a_t != t) {
118       T::release(a_t);
119       a_t = t;
120     }
121
122     return a_t;
123   }
124
125   /**
126      Operador copia.
127      \param other Referencia al objeto que vamos a tratar.
128      \return La instancia de la clase T asociada a esta instancia.
129   */
130   T* operator = (const AutoObject <T>& other) throw(RuntimeException) {
131     return (this != &other)  ? (*this = T::duplicate(other.a_t)) : a_t;
132   }
133
134   /**
135      Operador de conversion.
136      \return La instancia de la clase T asociada a esta instancia.
137   */
138   operator T*() const throw() { return a_t; }
139
140 private:
141   T* a_t;
142 };
143
144
145 }
146 }
147
148
149
150 #endif
151
152