/***************************************************************************
* 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 <qobject.h>
#include <qvaluelist.h>
#include <qmutex.h>
#include <exception>
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<GCS::GElementID> 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<GCS::GElementID> getAllElementIDs() throw(GStorageException);
QValueList<GCS::GElementID> 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<GCS::GElement*> getElements(QValueList<GCS::GElementID> 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<GCS::GElementID> 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<GCS::GElementID> 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<GCS::GElementID> 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
syntax highlighted by Code2HTML, v. 0.9.1