/*************************************************************************** * Copyright (C) 2005 by the G System Team * * http://www.g-system.at * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to * * the following conditions: * * * * The above copyright notice and this permission notice shall be * * included in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.* * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * ***************************************************************************/ #ifndef GWEGSTORAGE_H #define GWEGSTORAGE_H #include #include #include #include class QSqlDatabase; class QDomDocument; class QStringList; namespace GCS { class GElement; class GElementID; class GAgent; class GEnergy; class GForm; class GVector3; class GWorldData; } namespace GWE { /** * \class GStorageException GStorage.h * \brief An exception that can is thrown from GStorage objects. * @author Raphael Langerhorst * * @todo Improve MySQL support and avoid special case handling (driver) */ class GStorageException : public std::exception { private: /** * The actual text. */ QString Text; public: /** * Creates a storage exception with a descriptive error message. */ GStorageException(QString error) : Text(error) {} /** * Virtual destructor. */ virtual ~GStorageException() throw() {} /** * @return the error description. */ QString toString() {return Text;} }; /** * \class GStorage GStorage.he * \brief Provides persistent data storage, using a DBMS * @author Raphael Langerhorst * * Usually this class is used like this: * * @code * * GStorage* storage = new GStorage(); * storage->setDatabase("QSQLITE",":memory:","user","password"); * storage->connectDatabase(); //returns false on failure * storage->initializeDatabase(); //returns false on failure * * GXmlDataController* dc = new GXmlDataController(storage,network); * * @endcode * * Please consult the G System Architecture for the DB layout. * @note GStorage inherits QMutex, the application is responsible * of serializing access to GStorage objects! */ class GStorage : public QObject, public QMutex { Q_OBJECT protected: /** * The database itself. * @see connectDatabase() */ QSqlDatabase* Database; /** * The database type or driver. * @see setDatabaseDriver() */ QString DbDriver; /** * The database name. * @see setDatabaseName() */ QString DbName; /** * The host where the DBMS is running. * If no host is given, a local connection is used. * @see setDatabaseHost() */ QString DbHost; /** * The port on which the DBMS is listening. * If the port is set to 0 (the default) then the default * port of the database driver is used instead. * @see setDatabasePort() */ int DbPort; /** * The database user. * @see setDatabaseUser() */ QString DbUser; /** * The database password. * @see setDatabasePassword() */ QString DbPassword; public: /** * Constructor. */ GStorage(QObject *parent = 0, const char *name = 0); /** * Destructor. */ virtual ~GStorage(); /** * Sets the database type or driver to use. * You can get all available drivers with QSqlDatabase::drivers(). * @see QSqlDatabase::drivers() * @see DbDriver */ void setDatabaseDriver(QString driver); /** * Set the actual database connection string. The form of the string * usually differs depending on the database driver that is used. * @see DbName */ void setDatabaseName(QString connection); /** * Sets the host where the DBMS is running. * Leave empty for local connections. * @see DbHost */ void setDatabaseHost(QString host); /** * Sets the port on which the DBMS is listening. * Leave empty or set to 0 for the default port. * @see DbPort */ void setDatabasePort(int port); /** * Set the user with which to connect to the database. * @see DbUser */ void setDatabaseUser(QString user); /** * Set the user's password. * @see DbPassword */ void setDatabasePassword(QString password); /** * Set all database parameters at once. * @note this does not connect to the database, use connectDatabase() * for this purpose. */ void setDatabase(QString driver, QString name, QString user, QString password, QString host="", int port=0); /** * Connects to database. * You must set all database parameters before connecting. * @see setDatabase() * @return true on success. */ bool connectDatabase(); /** * @return true if database is open. */ bool isDatabaseConnected(); /** * Creates all tables, ... * You must connect to the database before initializing. * @see connectDatabase() * @return true if it was possible to prepare the database for real usage. */ bool initializeDatabase(); /** * Disconnects from database. * @return true if connection was already closed or if closing was successfull. */ bool disconnectDatabase(); /** * @return the last SQL error. */ QString getLastDatabaseError(); //BEGIN Data management protected: GCS::GVector3 getVector3(unsigned long id) throw(GStorageException); public: //BEGIN GWE stuff // get QStringList getAllServers() throw(GStorageException); bool getServerExists(const QString& server) throw(GStorageException); QStringList getServersForElementChildren(const GCS::GElementID& parent) throw(GStorageException); QValueList getElementsForServer(const QString& server) throw(GStorageException); QString getManagingServerForElement(const GCS::GElementID& id) throw(GStorageException); QString getServerPresence(const QString& server) throw(GStorageException); QStringList getServersSubscribedToElementUpdates(const GCS::GElementID& id) throw(GStorageException); QStringList getServersSubscribedToDataUpdates(const GCS::GElementID& id) throw(GStorageException); QStringList getServersSubscribedToEnergyUpdates(const GCS::GElementID& id) throw(GStorageException); QStringList getServersSubscribedToFormUpdates(const GCS::GElementID& id) throw(GStorageException); // modifications: /** * A new server is added on registration. */ void addServer(const QString& server, const QString& presence) throw(GStorageException); void updateServerPresence(const QString& server, const QString& presence) throw(GStorageException); /** * Also removes all associated subscriptions of course. * A server is generally removed when it unregisters. */ void removeServer(const QString& server) throw(GStorageException); /** * @param type must be either element, data, energy or form */ void setSubscription(const GCS::GElementID& element, const QString& server, const QString& type) throw(GStorageException); /** * @param type must be either element, data, energy or form */ void clearSubscription(const GCS::GElementID& element, const QString& server, const QString& type) throw(GStorageException); void updateManagingServer(const GCS::GElementID& element, const QString& new_server) throw(GStorageException); //END GWE stuff //BEGIN Element stuff // NOTE the agent list has only one column, it might be extended in the future // get bool getElementExists(const GCS::GElementID& id) throw(GStorageException); QValueList getAllElementIDs() throw(GStorageException); QValueList getAllElementIDsByServer(const QString& managing_server) throw(GStorageException); /** * @todo use views if the database supports it to select a whole element with one select! * @param data pointer to the used data controller, like the GXmlDataController */ GCS::GElement* getElement(const GCS::GElementID& id, const GCS::GWorldData* data) throw(GStorageException); QValueList getElements(QValueList id_list, const GCS::GWorldData* worlddata) throw(GStorageException); QDomDocument* getElementData(const GCS::GElementID& id) throw(GStorageException); GCS::GEnergy* getElementEnergy(const GCS::GElementID& id) throw(GStorageException); GCS::GForm* getElementForm(const GCS::GElementID& id) throw(GStorageException); QValueList getChildren(const GCS::GElementID& id) throw(GStorageException); GCS::GElementID getParent(const GCS::GElementID& id) throw(GStorageException); QStringList getElementAgents(const GCS::GElementID& id) throw(GStorageException); GCS::GElementID getConnection(const GCS::GElementID& id) throw(GStorageException); QStringList getAllAgents() throw(GStorageException); /** * @return empty string if agent does not exist */ QString getAgent(const QString& agent) throw(GStorageException); // modifications void addElement(const GCS::GElement* element, const QString& managing_server) throw(GStorageException); void updateElement(const GCS::GElement* element) throw(GStorageException); void removeElement(const GCS::GElementID& id) throw(GStorageException); void removeElements(QValueList id_list) throw(GStorageException); void reparentElement(const GCS::GElementID& element, const GCS::GElementID& old_parent, const GCS::GElementID& new_parent) throw(GStorageException); void changeConnection(const GCS::GElementID& element, const GCS::GElementID& connection) throw(GStorageException); void addElementAgent(const GCS::GElementID& element, const QString& agent) throw(GStorageException); void removeElementAgent(const GCS::GElementID& element, const QString& agent) throw(GStorageException); /** * @return list of agents that were removed. */ QStringList removeAllElementAgents(const GCS::GElementID& element) throw(GStorageException); /** * @return list of elements that had the agent included. */ QValueList removeAgentFromAllElements(const QString& agent) throw(GStorageException); void updateData(const GCS::GElementID& element, const QDomDocument* data) throw(GStorageException); void updateEnergy(const GCS::GElementID& element, const GCS::GEnergy* energy) throw(GStorageException); void updateForm(const GCS::GElementID& element, const GCS::GForm* form) throw(GStorageException); void removeAllAgents() throw(GStorageException); void addAgent(const QString& agent) throw(GStorageException); /** * @note you should make sure that the removed agent is not used by * any element, see removeAgentFromAllElements() */ void removeAgent(const QString& agent) throw(GStorageException); //END Element stuff //END Data management }; } #endif