commit 43457c847392bca6be2d6378961c0c81be9b09d9
Author: Christian Ehringfeld <c.ehringfeld@t-online.de>
Date:   Sun Sep 27 01:14:40 2015 +0200

    entity inspector improvements

diff --git a/src/entityinspector.cpp b/src/entityinspector.cpp
index 002653e..5e94a61 100644
--- a/src/entityinspector.cpp
+++ b/src/entityinspector.cpp
@@ -48,7 +48,7 @@ bool EntityInspector::checkRegisteredEntities() {
             qWarning() << msg;
             ok = false;
         } else {
-            msg = "Entity class " + classes.at(i) + " seems ok!\n";
+            msg = "Entity class " + classes.at(i) + " seems ok.\n";
             qInfo() << msg;
         }
         this->logger->logMsg(msg);
@@ -62,7 +62,7 @@ bool EntityInspector::checkRegisteredEntities() {
 
 bool EntityInspector::checkEntity(QString name) {
     QString msg = "--------------------\n";
-    msg += "Checking " + name + " now!\n";
+    msg += "Checking " + name + " now.\n";
     qDebug() << msg;
     auto entity = this->instantiateEntity(name, msg);
     bool ok = true;
@@ -81,10 +81,10 @@ Entity *EntityInspector::instantiateEntity(const QString name, QString &msg) {
     auto entity = EntityInstanceFactory::createInstance(name);
     QString internMsg = "";
     if (entity) {
-        internMsg = name + " is instanceable!";
+        internMsg = name + " is instantiable.";
         qInfo() << internMsg;
     } else {
-        internMsg = name + " is NOT instanceable!";
+        internMsg = name + " is NOT instantiable!";
         qCritical() << internMsg;
     }
     msg += internMsg + "\n";
@@ -123,18 +123,20 @@ bool EntityInspector::verifyRelations(Entity *&entity, QString &msg) {
     for (auto i = relations.constBegin(); i != relations.constEnd(); ++i) {
         this->checkRelationTypos(i.key(), i.value(), iMsg, ok);
         if (!metaProperties.contains(i.key())) {
-            iMsg += "For relation " + i.key() + " no property exists.";
+            iMsg += "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>";
+                        " 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);
                 if (!rel) {
                     ok = false;
+                } else {
+                    this->checkRelationMappings(metaProperty, i.value(), msg, ok);
                 }
             }
         }
@@ -212,6 +214,52 @@ void EntityInspector::checkRelationTypos(const QString &name, const Relation &r,
     }
 }
 
+void EntityInspector::checkRelationMappings(QMetaProperty &property,
+        const Relation &r, QString &msg, bool &ok) {
+    QString foreignEntityName = EntityInstanceFactory::extractEntityType(
+                                    property.typeName());
+    auto foreignInstance = EntityInstanceFactory::createInstance(foreignEntityName);
+    if (foreignInstance) {
+        auto foreignRelations = EntityHelper::getRelationProperties(foreignInstance);
+        int foundMappedBy = 0;
+        bool foundForeignMappedRelation = false;
+        for (auto i = foreignRelations.constBegin(); i != foreignRelations.constEnd();
+                ++i) {
+            if (r.getMappedBy().isEmpty()
+                    && i.key().getPropertyName() == r.getPropertyName()) {
+                ++foundMappedBy;
+            } else if (!r.getMappedBy().isEmpty()
+                       && r.getMappedBy() == i.key().getPropertyName()) {
+                foundForeignMappedRelation = true;
+                break;
+            }
+        }
+        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";
+            } 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";
+                ok = false;
+            }
+        } else if (!foundForeignMappedRelation) {
+            msg += "Relation " + r.getPropertyName() + " with mappedBy attribute " +
+                   r.getMappedBy() + " has no mapped relation in " + foreignEntityName +
+                   " class!\n";
+            ok = false;
+        }
+    } else {
+        msg += "Can't create object for property/relation " + r.getPropertyName() +
+               "!\n";
+        msg += "Classname: " + foreignEntityName + "\n";
+        msg += "Is the class registered?\n";
+        ok = false;
+    }
+}
+
 bool EntityInspector::checkPrimaryKey(Entity *&entity, QString &msg) {
     QString pk = entity->getPrimaryKey();
     auto metaprops = EntityHelper::getMetaProperties(entity);
diff --git a/src/entityinspector.h b/src/entityinspector.h
index 0e36482..72e6cda 100644
--- a/src/entityinspector.h
+++ b/src/entityinspector.h
@@ -26,7 +26,7 @@ namespace CuteEntityManager {
 
 /**
  * @brief The EntityInspector class
- * @todo verify Mappings
+ * This class can check entities for errors.
  */
 class EntityInspector {
   public:
@@ -41,7 +41,10 @@ class EntityInspector {
     void verifyTransientAttributes(Entity *&entity, QString &msg);
     bool checkRelation(const QVariant &entity, const Relation &r, QString &msg,
                        const QMetaProperty &property) const;
-    void checkRelationTypos(const QString &name, const Relation &r, QString &msg, bool &ok);
+    void checkRelationTypos(const QString &name, const Relation &r, QString &msg,
+                            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);
     void checkMetaProperties(QHash<QString, QMetaProperty> &metaProperties,
