Revision f12670e9
Von Christian Ehringfeld vor etwa 10 Jahren hinzugefügt
| EntityManager.pro | ||
|---|---|---|
|  | ||
| #QMAKE_CXXFLAGS +=  -Winit-self
 | ||
| CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
 | ||
|  | ||
| DISTFILES += \
 | ||
|     README.md \
 | ||
|     LICENSE \
 | ||
|     Doxyfile
 | ||
| README.md | ||
|---|---|---|
| Tutorial(wip):
 | ||
| https://synlos.net/redmine/projects/entitymanager/wiki/Tutorial
 | ||
|  | ||
| ### Minimum requirements
 | ||
|  | ||
| - GCC 4.8 or clang 3.3
 | ||
| - >= Qt 5.4
 | ||
| - any platform supported by Qt
 | ||
|  | ||
| ## German
 | ||
| Mit dem CuteEntityManager ist es möglich, Entities zu persistieren, zu 
 | ||
| samples/simple/main.cpp | ||
|---|---|---|
|                                 "Müsli"));
 | ||
|     auto ep = a.objectCast<CuteEntityManager::Entity>();
 | ||
|     qDebug() << e->create(ep, true, true);
 | ||
|     int i = 0;
 | ||
|  | ||
|     while(false); {
 | ||
|         i++;
 | ||
|     }
 | ||
|     qDebug()  << i;
 | ||
|  | ||
|     return 0;
 | ||
| }
 | ||
| src/database.cpp | ||
|---|---|---|
| using namespace CuteEntityManager;
 | ||
|  | ||
| Database::Database(QSqlDatabase database, bool loggerActivated, bool logQueries,
 | ||
|                    bool logErrors) {
 | ||
|                    bool logErrors, MsgType type) {
 | ||
|     this->database = database;
 | ||
|     this->init();
 | ||
|     this->connectionName = this->database.connectionName();
 | ||
|     this->initLogger(loggerActivated, logQueries, logErrors);
 | ||
|     this->initLogger(loggerActivated, logQueries, logErrors, type);
 | ||
| }
 | ||
|  | ||
| Database::Database(QString databaseType, QString connectionName,
 | ||
|                    QString hostname,
 | ||
|                    QString databasename,
 | ||
|                    QString username, QString password, qint64 port, bool loggerActivated,
 | ||
|                    bool logQueries, bool logErrors, QString databaseOptions) {
 | ||
|                    bool logQueries, bool logErrors, QString databaseOptions, MsgType type) {
 | ||
|     this->database = QSqlDatabase::addDatabase(databaseType, connectionName);
 | ||
|     this->connectionName = connectionName;
 | ||
|     if (!hostname.isEmpty()) {
 | ||
| ... | ... | |
|         this->database.setConnectOptions(databaseOptions);
 | ||
|     }
 | ||
|     this->init();
 | ||
|     this->initLogger(loggerActivated, logQueries, logErrors);
 | ||
|     this->initLogger(loggerActivated, logQueries, logErrors, type);
 | ||
| }
 | ||
|  | ||
| void Database::init() {
 | ||
| ... | ... | |
|                                     QSqlDriver::Transactions);
 | ||
| }
 | ||
|  | ||
| void Database::initLogger(bool activated, bool logQueries, bool logErrors) {
 | ||
| void Database::initLogger(bool activated, bool logQueries, bool logErrors,
 | ||
|                           MsgType type) {
 | ||
|     this->logQueries = logQueries;
 | ||
|     this->logErrors = logErrors;
 | ||
|     if (activated) {
 | ||
|         this->logger = new Logger(QDir::currentPath() + "/db" + this->connectionName +
 | ||
|                                   ".log");
 | ||
|                                   ".log", type);
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| src/database.h | ||
|---|---|---|
| #include "enums/databasetype.h"
 | ||
| #include "logger.h"
 | ||
| namespace CuteEntityManager {
 | ||
| #ifdef QT_DEBUG
 | ||
| #define DEFAULTMSGTYPE MsgType::DEBUG
 | ||
| #else
 | ||
| #define DEFAULTMSGTYPE MsgType::CRITICAL
 | ||
| #endif
 | ||
| class Database {
 | ||
|   private:
 | ||
|     QSqlDatabase database;
 | ||
| ... | ... | |
|     bool supportTransactions;
 | ||
|     Logger *logger = nullptr;
 | ||
|     void init();
 | ||
|     void initLogger(bool activated, bool logQueries, bool logErrors);
 | ||
|     void initLogger(bool activated, bool logQueries, bool logErrors, MsgType type);
 | ||
|     bool logQueries;
 | ||
|     bool logErrors;
 | ||
|  | ||
|   public:
 | ||
|     Database(QSqlDatabase database, bool loggerActivated = true,
 | ||
|              bool logQueries = false, bool logErrors = true);
 | ||
|              bool logQueries = false, bool logErrors = true,MsgType type= DEFAULTMSGTYPE);
 | ||
|     ~Database();
 | ||
|     Database(QString databaseType, QString connectionName = QString(""),
 | ||
|              QString hostname = QString(""),
 | ||
|              QString databasename = QString("") ,
 | ||
|              QString username = QString(""), QString password = QString(""),
 | ||
|              qint64 port = 0, bool loggerActivated = true, bool logQueries = false,
 | ||
|              bool logErrors = true, QString databaseOptions = "");
 | ||
|              bool logErrors = true, QString databaseOptions = "",MsgType type= DEFAULTMSGTYPE);
 | ||
|     QSqlDatabase getDatabase();
 | ||
|     QString getConnectionName();
 | ||
|     QSqlQuery getQuery();
 | ||
| src/entityinspector.cpp | ||
|---|---|---|
| #include <QDateTime>
 | ||
| using namespace CuteEntityManager;
 | ||
|  | ||
| EntityInspector::EntityInspector() {
 | ||
|     this->initLogger();
 | ||
| EntityInspector::EntityInspector(const MsgType msgType) {
 | ||
|     this->initLogger(msgType);
 | ||
| }
 | ||
|  | ||
| EntityInspector::~EntityInspector() {
 | ||
| ... | ... | |
|     QStringList classes = EntityInstanceFactory::getRegisteredClasses();
 | ||
|     QString msg = QDateTime::currentDateTime().toString(Qt::ISODate) +
 | ||
|                   " - Start checking entities\n";
 | ||
|     qInfo() << msg;
 | ||
|     this->logger->logMsg(msg);
 | ||
|     this->logger->logMsg(msg, MsgType::INFO);
 | ||
|     bool ok = true;
 | ||
|     for (int i = 0; i < classes.size(); ++i) {
 | ||
|         bool r = this->checkEntity(classes.at(i));
 | ||
| ... | ... | |
|             msg += classes.at(i) + " is erroneous!";
 | ||
|             msg += "\n";
 | ||
|             msg += "###############################\n";
 | ||
|             qWarning() << msg;
 | ||
|             this->logger->logMsg(msg, MsgType::CRITICAL);
 | ||
|             ok = false;
 | ||
|         } else {
 | ||
|             msg = "Entity class " + classes.at(i) + " seems ok.\n";
 | ||
|             qInfo() << msg;
 | ||
|             this->logger->logMsg(msg, MsgType::INFO);
 | ||
|         }
 | ||
|         this->logger->logMsg(msg);
 | ||
|     }
 | ||
|     msg = QDateTime::currentDateTime().toString(Qt::ISODate) +
 | ||
|           " - End checking entities\n";
 | ||
|     qInfo() << msg;
 | ||
|     this->logger->logMsg(msg);
 | ||
|     this->logger->logMsg(msg, MsgType::INFO);
 | ||
|     return ok;
 | ||
| }
 | ||
|  | ||
| bool EntityInspector::checkEntity(QString name) {
 | ||
|     QString msg = "--------------------\n";
 | ||
|     msg += "Checking " + name + " now.\n";
 | ||
|     qDebug() << msg;
 | ||
|     auto entity = this->instantiateEntity(name, msg);
 | ||
|     this->logger->logMsg(msg, MsgType::DEBUG);
 | ||
|     auto entity = this->instantiateEntity(name);
 | ||
|     bool ok = true;
 | ||
|     if (entity) {
 | ||
|         bool relations = this->verifyRelations(entity, msg);
 | ||
|         bool pk = this->checkPrimaryKey(entity, msg);
 | ||
|         this->verifyBlobAttributes(entity, msg);
 | ||
|         this->verifyTransientAttributes(entity, msg);
 | ||
|         bool relations = this->verifyRelations(entity);
 | ||
|         bool pk = this->checkPrimaryKey(entity);
 | ||
|         this->verifyBlobAttributes(entity);
 | ||
|         this->verifyTransientAttributes(entity);
 | ||
|         ok = pk && relations;
 | ||
|         delete entity;
 | ||
|         entity = nullptr;
 | ||
|     }
 | ||
|     this->logger->logMsg(msg);
 | ||
|     return ok;
 | ||
| }
 | ||
|  | ||
| Entity *EntityInspector::instantiateEntity(const QString name, QString &msg) {
 | ||
| Entity *EntityInspector::instantiateEntity(const QString name) {
 | ||
|     auto entity = EntityInstanceFactory::createInstance(name);
 | ||
|     QString internMsg = "";
 | ||
|     QString msg = "";
 | ||
|     if (entity) {
 | ||
|         internMsg = name + " is instantiable.";
 | ||
|         qInfo() << internMsg;
 | ||
|         msg = name + " is instantiable.";
 | ||
|         this->logger->logMsg(msg, MsgType::INFO);
 | ||
|     } else {
 | ||
|         internMsg = name + " is NOT instantiable!";
 | ||
|         qCritical() << internMsg;
 | ||
|         msg = name + " is NOT instantiable!";
 | ||
|         this->logger->logMsg(msg, MsgType::CRITICAL);
 | ||
|     }
 | ||
|     msg += internMsg + "\n";
 | ||
|     return entity;
 | ||
| }
 | ||
|  | ||
| void EntityInspector::checkMetaProperties(QHash<QString, QMetaProperty>
 | ||
|         &metaProperties, QString &msg, bool &ok, QHash<QString, Relation> &relations) {
 | ||
|         &metaProperties, bool &ok, QHash<QString, Relation> &relations) {
 | ||
|     QString msg = "";
 | ||
|     for (auto i = metaProperties.constBegin(); i != metaProperties.constEnd();
 | ||
|             ++i) {
 | ||
|         QString typeName = QString(i.value().typeName());
 | ||
| ... | ... | |
|             msg += i.key() + " must use QSharedPointer.\n";
 | ||
|         }
 | ||
|     }
 | ||
|     this->logger->logMsg(msg, MsgType::CRITICAL);
 | ||
| }
 | ||
|  | ||
| bool EntityInspector::verifyRelations(Entity *&entity, QString &msg) {
 | ||
| bool EntityInspector::verifyRelations(Entity *&entity) {
 | ||
|     bool ok = true;
 | ||
|     auto metaProperties = EntityHelper::getMetaProperties(entity);
 | ||
|     auto relations = entity->getRelations();
 | ||
|     QString iMsg = "";
 | ||
|     this->checkMetaProperties(metaProperties, iMsg, ok, relations);
 | ||
|     QString msg = "";
 | ||
|     this->checkMetaProperties(metaProperties, ok, relations);
 | ||
|     for (auto i = relations.constBegin(); i != relations.constEnd(); ++i) {
 | ||
|         this->checkRelationTypos(i.key(), i.value(), iMsg, ok);
 | ||
|         this->checkRelationTypos(i.key(), i.value(), ok);
 | ||
|         if (!metaProperties.contains(i.key())) {
 | ||
|             iMsg += "For relation " + i.key() + " no property exists!";
 | ||
|             msg += "For relation " + i.key() + " no property exists!";
 | ||
|             ok = false;
 | ||
|         } else {
 | ||
|             auto metaProperty = metaProperties.value(i.key());
 | ||
|             if (!QString(metaProperty.typeName()).contains("QSharedPointer")) {
 | ||
|                 iMsg += "Property " + QString(metaProperty.name()) +
 | ||
|                         " must be a type like QList<QSharedPointer<T>> or simply QSharedPointer<T>.";
 | ||
|                 msg += "Property " + QString(metaProperty.name()) +
 | ||
|                        " must be a type like QList<QSharedPointer<T>> or simply QSharedPointer<T>.";
 | ||
|             } else {
 | ||
|                 auto var = metaProperty.read(entity);
 | ||
|                 bool rel = this->checkRelation(var, i.value(), msg, metaProperty);
 | ||
|                 bool rel = this->checkRelation(var, i.value(), metaProperty);
 | ||
|                 if (!rel) {
 | ||
|                     ok = false;
 | ||
|                 } else {
 | ||
|                     this->checkRelationMappings(metaProperty, i.value(), msg, ok);
 | ||
|                     this->checkRelationMappings(metaProperty, i.value(), ok);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
|     if (!iMsg.isEmpty()) {
 | ||
|         qCritical() << iMsg;
 | ||
|         msg += iMsg;
 | ||
|     if (!msg.isEmpty()) {
 | ||
|         this->logger->logMsg(msg, MsgType::CRITICAL);
 | ||
|     }
 | ||
|     return ok;
 | ||
| }
 | ||
|  | ||
| void EntityInspector::verifyTransientAttributes(Entity *&entity, QString &msg) {
 | ||
| void EntityInspector::verifyTransientAttributes(Entity *&entity) {
 | ||
|     auto metaProperties = EntityHelper::getMetaProperties(entity);
 | ||
|     auto relations = entity->getRelations();
 | ||
|     auto transientAttributes = entity->getTransientAttributes();
 | ||
|     auto blobs = entity->getBLOBColumns();
 | ||
|     QString iMsg = "";
 | ||
|     QString msg = "";
 | ||
|     for (int i = 0; i < transientAttributes.size(); ++i) {
 | ||
|         QString attr = transientAttributes.at(i);
 | ||
|         if (!metaProperties.contains(attr)) {
 | ||
|             iMsg += "No transient attribute called " + attr + ".\n";
 | ||
|             msg += "No transient attribute called " + attr + ".\n";
 | ||
|         }
 | ||
|         if (relations.contains(transientAttributes.at(i))) {
 | ||
|             iMsg += "A transient attribute should not be declared as relation: " +
 | ||
|                     attr + ".\n";
 | ||
|             msg += "A transient attribute should not be declared as relation: " +
 | ||
|                    attr + ".\n";
 | ||
|         }
 | ||
|         if (blobs.contains(attr)) {
 | ||
|             iMsg += "A transient attribute should not be declared as blob column: " + attr +
 | ||
|                     ".\n";
 | ||
|             msg += "A transient attribute should not be declared as blob column: " + attr +
 | ||
|                    ".\n";
 | ||
|         }
 | ||
|     }
 | ||
|     if (!iMsg.isEmpty()) {
 | ||
|         qWarning() << iMsg;
 | ||
|         msg += iMsg;
 | ||
|     if (!msg.isEmpty()) {
 | ||
|         this->logger->logMsg(msg, MsgType::WARNING);
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| bool EntityInspector::checkRelation(const QVariant &entity,
 | ||
|                                     const Relation &r, QString &msg, const QMetaProperty &property) const {
 | ||
|     QString iMsg = "";
 | ||
|                                     const Relation &r, const QMetaProperty &property) const {
 | ||
|     QString msg = "";
 | ||
|     bool many = r.getType() == RelationType::MANY_TO_MANY
 | ||
|                 || r.getType() == RelationType::ONE_TO_MANY;
 | ||
|     QString propType = QString(property.type());
 | ||
|     bool canConvertList = entity.canConvert<QVariantList>() || (many
 | ||
|                           && propType.contains("QList"));
 | ||
|     if ((many && !canConvertList)) {
 | ||
|         iMsg = "Relation type of " + r.getPropertyName() +
 | ||
|                " must be MANY_TO_MANY or ONE_TO_MANY.\n";
 | ||
|         iMsg += "Or you can change the attribute type to QSharedPointer<T>.\n";
 | ||
|         msg = "Relation type of " + r.getPropertyName() +
 | ||
|               " must be MANY_TO_MANY or ONE_TO_MANY.\n";
 | ||
|         msg += "Or you can change the attribute type to QSharedPointer<T>.\n";
 | ||
|     } else if ((!many && canConvertList)) {
 | ||
|         iMsg = "Relation type of " + r.getPropertyName() +
 | ||
|                " must be MANY_TO_ONE or ONE_TO_ONE.\n";
 | ||
|         iMsg += "Or you can change the attribute type to QList<QSharedPointer<T>>.\n";
 | ||
|         msg = "Relation type of " + r.getPropertyName() +
 | ||
|               " must be MANY_TO_ONE or ONE_TO_ONE.\n";
 | ||
|         msg += "Or you can change the attribute type to QList<QSharedPointer<T>>.\n";
 | ||
|     }
 | ||
|     if (many && r.getType() == RelationType::ONE_TO_MANY
 | ||
|             && r.getMappedBy().isEmpty()) {
 | ||
|         iMsg += "Relation " + r.getPropertyName() +
 | ||
|                 " needs a mappedBy attribute of the foreign class.\n";
 | ||
|         msg += "Relation " + r.getPropertyName() +
 | ||
|                " needs a mappedBy attribute of the foreign class.\n";
 | ||
|     }
 | ||
|     if (!iMsg.isEmpty()) {
 | ||
|         msg += iMsg;
 | ||
|         qCritical() << iMsg;
 | ||
|     if (!msg.isEmpty()) {
 | ||
|         this->logger->logMsg(msg, MsgType::CRITICAL);
 | ||
|         return false;
 | ||
|     }
 | ||
|     return true;
 | ||
| }
 | ||
|  | ||
| void EntityInspector::checkRelationTypos(const QString &name, const Relation &r,
 | ||
|         QString &msg, bool &ok) {
 | ||
|         bool &ok) {
 | ||
|     if (name != r.getPropertyName()) {
 | ||
|         ok = false;
 | ||
|         msg += "Relation " + name + " has a typo.\n";
 | ||
|         msg += "Name " + name + "and relation name " + r.getPropertyName() +
 | ||
|                " are not equal.\n";
 | ||
|         this->logger->logMsg("Relation " + name + " has a typo.\n" + "Name " + name +
 | ||
|                              "and relation name " + r.getPropertyName() +
 | ||
|                              " are not equal.\n", MsgType::WARNING);
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| void EntityInspector::checkRelationMappings(QMetaProperty &property,
 | ||
|         const Relation &r, QString &msg, bool &ok) {
 | ||
|         const Relation &r, bool &ok) {
 | ||
|     QString foreignEntityName = EntityInstanceFactory::extractEntityType(
 | ||
|                                     property.typeName());
 | ||
|     auto foreignInstance = EntityInstanceFactory::createInstance(foreignEntityName);
 | ||
| ... | ... | |
|         }
 | ||
|         if (r.getMappedBy().isEmpty()) {
 | ||
|             if (foundMappedBy == 0) {
 | ||
|                 msg += "Optional: The relation " + r.getPropertyName() +
 | ||
|                        " is not mapped in foreign class " + foreignEntityName +
 | ||
|                        ". You could map it.\n";
 | ||
|                 this->logger->logMsg("Optional: The relation " + r.getPropertyName() +
 | ||
|                                      " is not mapped in foreign class " + foreignEntityName +
 | ||
|                                      ". You could map it.\n", MsgType::INFO);
 | ||
|             } else if (foundMappedBy > 1) {
 | ||
|                 msg += "The relation " + r.getPropertyName() + " is mapped several times (" +
 | ||
|                        QString::number(foundMappedBy) + ") by foreign class " + foreignEntityName +
 | ||
|                        ". You should map it only once!\n";
 | ||
|                 this->logger->logMsg("The relation " + r.getPropertyName() +
 | ||
|                                      " is mapped several times (" +
 | ||
|                                      QString::number(foundMappedBy) + ") by foreign class " + foreignEntityName +
 | ||
|                                      ". You should map it only once!\n", MsgType::WARNING);
 | ||
|                 ok = false;
 | ||
|             }
 | ||
|         } else if (!foundForeignMappedRelation) {
 | ||
|             msg += "Relation " + r.getPropertyName() + " with mappedBy attribute " +
 | ||
|                    r.getMappedBy() + " has no mapped relation in " + foreignEntityName +
 | ||
|                    " class!\n";
 | ||
|             this->logger->logMsg("Relation " + r.getPropertyName() +
 | ||
|                                  " with mappedBy attribute " +
 | ||
|                                  r.getMappedBy() + " has no mapped relation in " + foreignEntityName +
 | ||
|                                  " class!\n", MsgType::CRITICAL);
 | ||
|             ok = false;
 | ||
|         }
 | ||
|         delete foreignInstance;
 | ||
|         foreignInstance = nullptr;
 | ||
|     } else {
 | ||
|         msg += "Can't create object for property/relation " + r.getPropertyName() +
 | ||
|                "!\n";
 | ||
|         msg += "Classname: " + foreignEntityName + "\n";
 | ||
|         msg += "Is the class registered?\n";
 | ||
|         this->logger->logMsg("Can't create object for property/relation " +
 | ||
|                              r.getPropertyName() +
 | ||
|                              "\n" + "Classname: " + foreignEntityName + "\n" + "Is the class registered?\n",
 | ||
|                              MsgType::CRITICAL);
 | ||
|         ok = false;
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| bool EntityInspector::checkPrimaryKey(Entity *&entity, QString &msg) {
 | ||
| bool EntityInspector::checkPrimaryKey(Entity *&entity) {
 | ||
|     QString pk = entity->getPrimaryKey();
 | ||
|     auto metaprops = EntityHelper::getMetaProperties(entity);
 | ||
|     QString iMsg = "";
 | ||
|     bool ok = true;
 | ||
|     if (!metaprops.contains(pk)) {
 | ||
|         ok = false;
 | ||
|         iMsg = "Property " + pk +
 | ||
|                " for primary key not exists. Please check your getPrimaryKey() method!\n";
 | ||
|         this->logger->logMsg("Property " + pk +
 | ||
|                              " for primary key not exists. Please check your getPrimaryKey() method!\n",
 | ||
|                              MsgType::CRITICAL);
 | ||
|     }
 | ||
|     qCritical() << iMsg;
 | ||
|     msg += iMsg;
 | ||
|     return ok;
 | ||
| }
 | ||
|  | ||
| void EntityInspector::verifyBlobAttributes(Entity *&entity, QString &msg) {
 | ||
| void EntityInspector::verifyBlobAttributes(Entity *&entity) {
 | ||
|     auto metaprops = EntityHelper::getMetaProperties(entity);
 | ||
|     auto blobs = entity->getBLOBColumns();
 | ||
|     QString iMsg = "";
 | ||
|     QString msg = "";
 | ||
|     for (int i = 0; i < blobs.size(); ++i) {
 | ||
|         QString name = blobs.at(i);
 | ||
|         if (!metaprops.contains(name)) {
 | ||
|             iMsg += "For blob column " + name + " no property exists.\n";
 | ||
|             msg += "For blob column " + name + " no property exists.\n";
 | ||
|         }
 | ||
|     }
 | ||
|     qWarning() << iMsg;
 | ||
|     msg += iMsg;
 | ||
|     this->logger->logMsg(msg, MsgType::WARNING);
 | ||
| }
 | ||
|  | ||
| void EntityInspector::initLogger() {
 | ||
|     this->logger = new Logger(QDir::currentPath() + "/entity.log");
 | ||
| void EntityInspector::initLogger(const MsgType msgType) {
 | ||
|     this->logger = new Logger(QDir::currentPath() + "/entity.log", msgType);
 | ||
| }
 | ||
| src/entityinspector.h | ||
|---|---|---|
|  */
 | ||
| class EntityInspector {
 | ||
|   public:
 | ||
|     EntityInspector();
 | ||
|     EntityInspector(const MsgType msgType = MsgType::DEBUG);
 | ||
|     ~EntityInspector();
 | ||
|     bool checkRegisteredEntities();
 | ||
|     bool checkEntity(QString name);
 | ||
|  | ||
|   private:
 | ||
|     Entity *instantiateEntity(const QString name, QString &msg);
 | ||
|     bool verifyRelations(Entity *&entity, QString &msg);
 | ||
|     void verifyTransientAttributes(Entity *&entity, QString &msg);
 | ||
|     bool checkRelation(const QVariant &entity, const Relation &r, QString &msg,
 | ||
|     Entity *instantiateEntity(const QString name);
 | ||
|     bool verifyRelations(Entity *&entity);
 | ||
|     void verifyTransientAttributes(Entity *&entity);
 | ||
|     bool checkRelation(const QVariant &entity, const Relation &r,
 | ||
|                        const QMetaProperty &property) const;
 | ||
|     void checkRelationTypos(const QString &name, const Relation &r, QString &msg,
 | ||
|     void checkRelationTypos(const QString &name, const Relation &r,
 | ||
|                             bool &ok);
 | ||
|     void checkRelationMappings(QMetaProperty &property, const Relation &r,
 | ||
|                                QString &msg, bool &ok);
 | ||
|     bool checkPrimaryKey(Entity *&entity, QString &msg);
 | ||
|     void verifyBlobAttributes(Entity *&entity, QString &msg);
 | ||
|                                bool &ok);
 | ||
|     bool checkPrimaryKey(Entity *&entity);
 | ||
|     void verifyBlobAttributes(Entity *&entity);
 | ||
|     void checkMetaProperties(QHash<QString, QMetaProperty> &metaProperties,
 | ||
|                              QString &msg, bool &ok, QHash<QString, Relation> &relations);
 | ||
|     void initLogger();
 | ||
|                              bool &ok, QHash<QString, Relation> &relations);
 | ||
|     void initLogger(const MsgType msgType);
 | ||
|     Logger *logger = nullptr;
 | ||
| };
 | ||
| }
 | ||
| src/entitymanager.cpp | ||
|---|---|---|
|                             ignoreHasChanged, validate, relationsIgnoreHasChanged);
 | ||
| }
 | ||
|  | ||
| EntityManager::EntityManager(QSqlDatabase database,
 | ||
|                              bool logQueries, const bool inspectEntities) : QObject() {
 | ||
|     auto db = new Database(database, true, logQueries);
 | ||
| EntityManager::EntityManager(QSqlDatabase database, bool logQueries,
 | ||
|                              const bool inspectEntities,
 | ||
|                              MsgType logActions) : QObject() {
 | ||
|     auto db = new Database(database, true, logQueries, true, logActions);
 | ||
|     this->db = QSharedPointer<Database>(db);
 | ||
|     this->init(inspectEntities);
 | ||
|     this->init(inspectEntities,logActions);
 | ||
| }
 | ||
|  | ||
| EntityManager::EntityManager(const QString &databaseType, QString databasename ,
 | ||
|                              QString hostname, QString username, QString password, QString port,
 | ||
|                              bool logQueries, QString databaseOptions,
 | ||
|                              const bool inspectEntities) : QObject() {
 | ||
|     auto db = new Database(databaseType, this->createConnection(), hostname,
 | ||
|                            databasename, username,
 | ||
|                            password,
 | ||
|                            port.toInt(), true, logQueries, true, databaseOptions);
 | ||
|     this->db = QSharedPointer<Database>(db);
 | ||
|     this->init(inspectEntities);
 | ||
| }
 | ||
|  | ||
| void EntityManager::init(bool inspect) {
 | ||
| void EntityManager::init(bool inspect,const MsgType msgType) {
 | ||
|     auto schema = Database::getSchema(Database::getDatabaseType(
 | ||
|                                           this->db->getDatabase().driverName()), this->db);
 | ||
|     this->schema = QSharedPointer<Schema>(schema);
 | ||
| ... | ... | |
|     this->queryInterpreter = QSharedPointer<QueryInterpreter>(new QueryInterpreter(
 | ||
|                                  this->schema->getQueryBuilder()));
 | ||
|     this->appendToInstanceList();
 | ||
| #ifdef QT_DEBUG
 | ||
|     inspect = true;
 | ||
| #endif
 | ||
|     if (inspect) {
 | ||
|         EntityInspector inspector = EntityInspector();
 | ||
|         EntityInspector inspector = EntityInspector(msgType);
 | ||
|         inspector.checkRegisteredEntities();
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| EntityManager::EntityManager(const QString &databaseType, QString databasename,
 | ||
|                              QString hostname, QString username, QString password, QString port,
 | ||
|                              bool logQueries, QString databaseOptions, const bool inspectEntities,
 | ||
|                              CuteEntityManager::MsgType logActions) : QObject() {
 | ||
|     auto db = new Database(databaseType, this->createConnection(), hostname,
 | ||
|                            databasename, username,
 | ||
|                            password,
 | ||
|                            port.toInt(), true, logQueries, true, databaseOptions, logActions);
 | ||
|     this->db = QSharedPointer<Database>(db);
 | ||
|     this->init(inspectEntities,logActions);
 | ||
| }
 | ||
|  | ||
| EntityManager::~EntityManager() {
 | ||
|     EntityManager::removeConnectionName(this->db->getConnectionName());
 | ||
|     EntityManager::instances.remove(this->objectName());
 | ||
| src/entitymanager.h | ||
|---|---|---|
| #include "querybuilder.h"
 | ||
| #include "validators/errormsg.h"
 | ||
| namespace CuteEntityManager {
 | ||
| #ifdef QT_DEBUG
 | ||
| #define DEFAULTMSGTYPE MsgType::DEBUG
 | ||
| #define INSPECTENTITIES true
 | ||
| #else
 | ||
| #define DEFAULTMSGTYPE MsgType::CRITICAL
 | ||
| #define INSPECTENTITIES false
 | ||
| #endif
 | ||
|  | ||
|  | ||
| class Logger;
 | ||
| class QueryInterpreter;
 | ||
| ... | ... | |
|     bool hasChanged(QSharedPointer<Entity> &entity);
 | ||
|  | ||
|   public:
 | ||
|     EntityManager(QSqlDatabase database, bool logQueries = false, const bool inspectEntities = false);
 | ||
|     EntityManager(QSqlDatabase database, bool logQueries = false,
 | ||
|                   const bool inspectEntities = INSPECTENTITIES,
 | ||
|                   MsgType logActions = DEFAULTMSGTYPE);
 | ||
|     EntityManager(const QString &databaseType, QString databasename = "" ,
 | ||
|                   QString hostname = "",
 | ||
|                   QString username = "",
 | ||
|                   QString password = "", QString port = "", bool logQueries = false,
 | ||
|                   QString databaseOptions = "", const bool inspectEntities = false);
 | ||
|                   QString databaseOptions = "", const bool inspectEntities = INSPECTENTITIES,
 | ||
|                   MsgType logActions = DEFAULTMSGTYPE);
 | ||
|     virtual ~EntityManager();
 | ||
|     static QStringList getConnectionNames();
 | ||
|     static void removeConnectionName(const QString &name);
 | ||
| ... | ... | |
|         return newList;
 | ||
|     }
 | ||
|  | ||
|     void init(bool inspect);
 | ||
|     void init(bool inspect, const MsgType msgType);
 | ||
|     QList<QHash<QString, QVariant> > findAll(const QSharedPointer<Entity> &e);
 | ||
|     void resolveRelations(const QSharedPointer<Entity> &entity,
 | ||
|                           const QHash<QString, QVariant> &map, const bool refresh = false);
 | ||
| src/logger.cpp | ||
|---|---|---|
| #include <QDateTime>
 | ||
|  | ||
| using namespace CuteEntityManager;
 | ||
| Logger::Logger(QString path) {
 | ||
|  | ||
| Logger::Logger(QString path, MsgType min) {
 | ||
|     this->path = path;
 | ||
|     this->minimum = min;
 | ||
| }
 | ||
|  | ||
| Logger::~Logger() {
 | ||
| ... | ... | |
|             QString msg = "{" + QString("\"time\":\"") +
 | ||
|                           QDateTime::currentDateTime().toString(Qt::ISODate) + QString("\"") + errorMsg;
 | ||
|             msg += this->generateLogMsg(q) + "}";
 | ||
|             this->logMsg(msg);
 | ||
|             if (errorMsg.isEmpty()) {
 | ||
|                 qDebug() << msg.replace("\"", "'");
 | ||
|             } else {
 | ||
|                 qWarning() << msg.replace("\"", "'");
 | ||
|             }
 | ||
|             this->logMsg(msg, errorMsg.isEmpty() ? MsgType::DEBUG : MsgType::WARNING);
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| void Logger::lastError(const QSqlError &e) {
 | ||
|     if (e.isValid()) {
 | ||
|         this->logMsg(this->generateLogMsg(e));
 | ||
|         this->logMsg(this->generateLogMsg(e), MsgType::WARNING);
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| void Logger::logMsg(const QString &value) {
 | ||
|     QFile log(this->getPath());
 | ||
|     log.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
 | ||
|     log.seek(log.size());
 | ||
|     QTextStream stream(&log);
 | ||
|     stream.setCodec("UTF-8");
 | ||
|     stream << value;
 | ||
|     stream << "\n";
 | ||
|     stream.flush();
 | ||
|     log.close();
 | ||
| void Logger::logMsg(const QString &value, const MsgType type) {
 | ||
|     if (!value.isEmpty() && this->shouldBeLogged(type)) {
 | ||
|         this->outputToConsole(type, value);
 | ||
|         QFile log(this->getPath());
 | ||
|         log.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
 | ||
|         log.seek(log.size());
 | ||
|         QTextStream stream(&log);
 | ||
|         stream.setCodec("UTF-8");
 | ||
|         stream << value;
 | ||
|         stream << "\n";
 | ||
|         stream.flush();
 | ||
|         log.close();
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| QString Logger::generateLogMsg(const QSqlQuery &q, bool withValues) const {
 | ||
| ... | ... | |
|     return r;
 | ||
| }
 | ||
|  | ||
| bool Logger::shouldBeLogged(const MsgType &type) const {
 | ||
|     switch (type) {
 | ||
|     case MsgType::DEBUG:
 | ||
|         return this->minimum == MsgType::DEBUG;
 | ||
|     case MsgType::INFO:
 | ||
|         return this->minimum == MsgType::DEBUG || this->minimum == MsgType::INFO;
 | ||
|     case MsgType::WARNING:
 | ||
|         return this->minimum == MsgType::DEBUG || this->minimum == MsgType::INFO
 | ||
|                || this->minimum == MsgType::WARNING;
 | ||
|     case MsgType::CRITICAL:
 | ||
|         return this->minimum == MsgType::DEBUG || this->minimum == MsgType::INFO
 | ||
|                || this->minimum == MsgType::WARNING || this->minimum == MsgType::CRITICAL;
 | ||
|     default:
 | ||
|         return true;
 | ||
|         break;
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| void Logger::outputToConsole(const MsgType &type, const QString &msg) const {
 | ||
|     switch (type) {
 | ||
|     case MsgType::DEBUG:
 | ||
|         qDebug() << msg;
 | ||
|         break;
 | ||
|     case MsgType::INFO:
 | ||
|         qInfo() << msg;
 | ||
|         break;
 | ||
|     case MsgType::WARNING:
 | ||
|         qWarning() << msg;
 | ||
|         break;
 | ||
|     case MsgType::CRITICAL:
 | ||
|         qCritical() << msg;
 | ||
|         break;
 | ||
|     case MsgType::FATAL:
 | ||
|         qFatal(msg.toUtf8().constData());
 | ||
|         break;
 | ||
|     }
 | ||
| }
 | ||
|  | ||
| MsgType Logger::getMinimum() const {
 | ||
|     return minimum;
 | ||
| }
 | ||
|  | ||
| void Logger::setMinimum(const MsgType &value) {
 | ||
|     minimum = value;
 | ||
| }
 | ||
|  | ||
| QString Logger::getPath() {
 | ||
|     if (this->path.isEmpty()) {
 | ||
|         this->path = this->defaultPath();
 | ||
| src/logger.h | ||
|---|---|---|
| #include <QSqlError>
 | ||
| #include <QSqlQuery>
 | ||
| namespace CuteEntityManager {
 | ||
|  | ||
| enum class MsgType { DEBUG, INFO, WARNING, CRITICAL, FATAL};
 | ||
|  | ||
| class Logger {
 | ||
| #ifdef QT_DEBUG
 | ||
| #define DEFAULTMSGTYPE MsgType::DEBUG
 | ||
| #else
 | ||
| #define DEFAULTMSGTYPE MsgType::CRITICAL
 | ||
| #endif
 | ||
|  | ||
|   public:
 | ||
|     Logger(QString path = "");
 | ||
|     Logger(QString path = "", MsgType min = DEFAULTMSGTYPE);
 | ||
|     ~Logger();
 | ||
|     QString defaultPath() const;
 | ||
|  | ||
| ... | ... | |
|     void lastError(const QSqlQuery &q, bool logQuery = false);
 | ||
|     QString getPath();
 | ||
|     void setPath(const QString &value);
 | ||
|     void logMsg(const QString &value);
 | ||
|     void logMsg(const QString &value, const MsgType type = MsgType::DEBUG);
 | ||
|  | ||
|     MsgType getMinimum() const;
 | ||
|     void setMinimum(const MsgType &value);
 | ||
|  | ||
|   protected:
 | ||
|     QString generateLogMsg(const QSqlError &e) const;
 | ||
|     QString generateLogMsg(const QSqlQuery &q, bool withValues = true) const;
 | ||
|     bool shouldBeLogged(const MsgType &type) const;
 | ||
|     void outputToConsole(const MsgType &type, const QString &msg) const;
 | ||
|  | ||
|  | ||
|   private:
 | ||
|     QString path;
 | ||
|     MsgType minimum;
 | ||
| };
 | ||
| }
 | ||
| #endif // LOGGER_H
 | ||
Auch abrufbar als: Unified diff
some logger stuff