--- /dev/null
+// 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_dbms_Database_hpp
+#define anna_dbms_Database_hpp
+
+#include <vector>
+
+#include <anna/app/Component.hpp>
+
+#include <anna/dbms/Connection.hpp>
+
+namespace anna {
+
+namespace comm {
+class INetAddress;
+class Delivery;
+}
+
+namespace dbms {
+
+class Statement;
+class InputBind;
+class OutputBind;
+class Data;
+class FailRecoveryHandler;
+class StatementTranslator;
+
+/**
+ Clase que modela la interaccion entre la base y nuestra aplicacion.
+*/
+class Database : public app::Component {
+public:
+ /**
+ Numero maximo de conexiones que podemos crear.
+ */
+ static const int MaxConnection = 32;
+
+ /**
+ Formas de conexion a la base de datos.
+ */
+ struct Type {
+ enum _v { Local, Remote } value;
+ Type() : value(Local) {;}
+ Type(const _v v) : value(v) {;}
+ Type(const Type& v) : value(v.value) {;}
+ operator int () const throw() { return value; }
+ };
+
+ typedef std::vector <Connection*>::const_iterator const_connection_iterator; /**<Iterador para acceder a las conexiones de esta base de datos */
+ typedef std::vector <Statement*>::const_iterator const_statement_iterator; /**<Iterador para acceder a las conexiones de esta base de datos */
+
+ /**
+ Destructor.
+ */
+ virtual ~Database();
+
+ /**
+ Devuelve el tipo de conexion de esta base de datos.
+ \return El tipo de conexion de esta base de datos.
+ */
+ const Type& getType() const throw() { return a_type; }
+
+ /**
+ Devuelve el nombre de la base de datos indicado en el constructor.
+ \return El nombre de la base de datos indicado en el constructor.
+ */
+ const std::string& getName() const throw() { return a_name; }
+
+ /**
+ Establece el manejador encargado de actuar cuando la recuperacion de la conexion falla.
+ El manejador por defecto no realiza ninguna activad.
+ \param failRecoveryHandler Manejador que seria invocado en caso de que no sea posible recuperar
+ una determina conexion.
+ */
+ void setFailRecoveryHandler(FailRecoveryHandler* failRecoveryHandler) throw() { a_failRecoveryHandler = failRecoveryHandler; }
+
+ /**
+ * Establece el traductor de sentencias SQL usado ajustar las sentencias SQL al
+ * motor de base de datos usados en la aplicaciĆ³n.
+ */
+ void setStatementTranslator(StatementTranslator* statementTranslator) throw() { a_statementTranslator = statementTranslator; }
+
+ /**
+ Crea y registra una nueva conexion con esta base de datos.
+ La clase usada para conectar con esta base de datos dependeria de la implementacion particular, que
+ seria definida por el metodo #allocateConnection.
+
+ \param name Nombre logico de la conexion a crear.
+ @param user Nombre del usuario con el que realizamos la conexion.
+ @param password Codigo de acceso del usuario.
+
+ @return La instancia de la nueva conexion a la base de datos.
+ */
+ Connection* createConnection(const char* name, const char* user, const char* password)
+ throw(RuntimeException, DatabaseException);
+
+ /**
+ Devuelve la conexion asociada al nombre logico recibido como parametro.
+ \param name Nombre logico de la conexion que queremos obtener.
+ \return La conexion asociada al nombre logico recibido como parametro.
+ \warning Si la conexion logica no existe no puede ser usada se lanzara una excepcion.
+ */
+ Connection& findConnection(const char* name) throw(RuntimeException);
+
+ /**
+ Devuelve un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
+ \return Un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
+ */
+ const_connection_iterator connection_begin() const throw() { return a_connections.begin(); }
+
+ /**
+ Devuelve un iterator al final de la lista de conexiones establecidas con esta base de datos.
+ \return Un iterator al final de la lista de conexiones establecidas con esta base de datos.
+ */
+ const_connection_iterator connection_end() const throw() { return a_connections.end(); }
+
+ /**
+ Crea y registra una nueva sentencia SQL asociada a esta base de datos.
+ La clase usada para interpretar la sentencia SQL dependera de la implementacion particular definida
+ mediante el metodo #allocateStatement.
+
+ \param name Nombre logico de esta sentencia.
+ \param expression Expresion asociada a la sentencia.
+ \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
+ la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
+ aunque falle se invocara a Connection::commit. Solo aplicara en sentencias que no sean de seleccion.
+
+ \return Una nueva instancia de una conexion a base de datos. No puede ser NULL.
+ */
+ Statement* createStatement(const char* name, const char* expression, const bool isCritical = true)
+ throw(RuntimeException);
+
+ /**
+ Crea y registra una nueva sentencia SQL asociada a esta base de datos.
+ La clase usada para interpretar la sentencia SQL dependera de la implementacion particular definida
+ mediante el metodo #allocateStatement.
+
+ \param name Nombre logico de esta sentencia.
+ \param expression Expresion asociada a la sentencia.
+ \param isCritical Si vale \em true indica que si la ejecucion de esta sentencia falla al desbloquear
+ la conexion con la que ejecutamos esta sentencia se invocara a Connection::rollback, en otro caso
+ aunque falle se invocara a Connection::commit. Solo aplicara en sentencias que no sean de seleccion.
+
+ \return Una nueva instancia de una conexion a base de datos. No puede ser NULL.
+ */
+ Statement* createStatement(const char* name, const std::string& expression, const bool isCritical = true)
+ throw(RuntimeException) {
+ return createStatement(name, expression.c_str(), isCritical);
+ }
+
+ /**
+ Devuelve la instancia de la sentencia SQL asociada al nombre recibido como parametro.
+
+ @return La instancia de la sentencia SQL asociada al nombre recibido.
+ Puede ser NULL si el nombre no fue registrado previamente con #createStatement.
+ */
+ Statement* findStatement(const char* name) throw();
+
+ /**
+ Libera los recursos de la sentencia SQL recibida como parametro.
+ \param statement Instancia de la sentencia SQL a liberar. deberia haber sido obtenida mediante
+ el metodo #createStatement.
+ */
+ void releaseStatement(Statement* statement) throw();
+
+ /**
+ Devuelve un iterator al comienzo de la lista de sentencias SQL creadas en esta base de datos.
+ \return Un iterator al comienzo de la lista de sentencias SQL creadas en esta base de datos.
+ */
+ const_statement_iterator statement_begin() const throw() { return a_statements.begin(); }
+
+ /**
+ Devuelve un iterator al final de la lista de sentencias SQL creadas en esta base de datos.
+ \return Un iterator al final de la lista de sentencias SQL creadas en esta base de datos.
+ */
+ const_statement_iterator statement_end() const throw() { return a_statements.end(); }
+
+ /**
+ Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
+ \param ii Iterator que deberia estar comprendido entre #statement_begin y #statement_end.
+ \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
+ */
+ static Statement* statement(const_statement_iterator& ii) throw() { return *ii; }
+
+ /**
+ Devuelve una cadena con la informacion mas relevante de esta instancia.
+ \return Una cadena con la informacion mas relevante de esta instancia.
+ */
+ virtual std::string asString() const throw();
+
+ /**
+ Devuelve un documento XML con la informacion mas relevante de esta instancia.
+ \param parent Nodo XML del que colgar la informacion referente a esta instancia.
+ \return Un documento XML con la informacion mas relevante de esta instancia.
+ */
+ virtual xml::Node* asXML(xml::Node* parent) const throw();
+
+ /**
+ Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
+ \param ii Iterator que deberia estar comprendido entre #connection_begin y #connection_end.
+ \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
+ */
+ static const Connection* connection(const_connection_iterator& ii) throw() { return *ii; }
+
+protected:
+ typedef std::vector <Connection*>::iterator connection_iterator; /**<Iterador para acceder a las conexiones de esta base de datos */
+
+ /**
+ Contructor.
+ \param rdbmsmsName Nombre del RDMS que gestiona esta base de datos.
+ \param dbmsName Nombre de la base de datos.
+ */
+ Database(const char* rdbmsmsName, const char* dbmsName);
+
+ /**
+ Recupera el estado de una conexion perdida.
+ \warning Este metodo se invoca automaticamente desde el nucleo de ANNA.dbms y nunca deberia
+ ser invocado por el programador.
+ \param connection Instancia de la conexion en la que hemos detectado el fallo.
+ \param tryCounter numero de intentos de recuperacion de la conexion.
+ */
+ void recover(Connection& connection, const int tryCounter) throw(RuntimeException);
+
+ /**
+ Inicializa las conexiones definidas sobre esta base de datos. Este metodo se invocaria
+ automaticamente desde el nucleo de ANNA.
+ Slo seria necesario invocarlo cuando nuestro programa no tenga asociada ninguna aplicacion
+ que se encarga de inicializar los componentes.
+ */
+ virtual void do_initialize() throw(RuntimeException);
+
+ /**
+ Elimina las conexiones definidas sobre esta base de datos. Este metodo se invocaria automaticamente
+ desde el nucleo de ANNA.
+ */
+ virtual void do_stop() throw();
+
+ /**
+ Devuelve un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
+ \return Un iterator al comienzo de la lista de conexiones establecidas con esta base de datos.
+ */
+ connection_iterator connection_begin() throw() { return a_connections.begin(); }
+
+ /**
+ Devuelve un iterator al final de la lista de conexiones establecidas con esta base de datos.
+ \return Un iterator al final de la lista de conexiones establecidas con esta base de datos.
+ */
+ connection_iterator connection_end() throw() { return a_connections.end(); }
+
+ /**
+ Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
+ \param ii Iterator que deberia estar comprendido entre #connection_begin y #connection_end.
+ \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
+ */
+ static Connection* connection(connection_iterator& ii) throw() { return *ii; }
+
+private:
+ const std::string a_name;
+ std::vector <Connection*> a_connections;
+ std::vector <Statement*> a_statements;
+ const Type a_type;
+ FailRecoveryHandler* a_failRecoveryHandler;
+ StatementTranslator* a_statementTranslator;
+
+ Database(const Database&);
+
+ void do_cloneChild() throw(RuntimeException);
+
+ virtual Connection* allocateConnection(const std::string& name, const char* user, const char* password)
+ throw(RuntimeException) = 0;
+
+ virtual Statement* allocateStatement(const char* name, const std::string& expression, const bool isCritical)
+ throw(RuntimeException) = 0;
+
+ virtual InputBind* allocateInputBind(const char* name, Data& data)
+ throw(RuntimeException) = 0;
+ virtual void deallocate(InputBind* inputBind) throw() = 0;
+
+ virtual OutputBind* allocateOutputBind(const char* name, Data& data)
+ throw(RuntimeException) = 0;
+ virtual void deallocate(OutputBind* outputBind) throw() = 0;
+
+ friend class Statement;
+ friend ResultCode Connection::execute(Statement*) throw(RuntimeException, DatabaseException);
+};
+
+}
+}
+
+#endif