From 8085fcc792a72087d9402ae570623d2842d16b1b Mon Sep 17 00:00:00 2001
From: Marek Kochanowicz <sirherrbatka@gmail.com>
Date: Fri, 20 Dec 2013 20:02:42 +0100
Subject: [PATCH] Added Referencable checks class, added method to get
 refidcontainer, added method to get mBooks.

Currently only books are checked, and only if name is present.
---
 apps/opencs/CMakeLists.txt                    |  2 +-
 .../opencs/model/tools/referenceablecheck.cpp | 63 +++++++++++++++++++
 .../opencs/model/tools/referenceablecheck.hpp | 26 ++++++++
 apps/opencs/model/tools/tools.cpp             |  5 +-
 apps/opencs/model/world/refidcollection.cpp   |  6 ++
 apps/opencs/model/world/refidcollection.hpp   |  2 +
 apps/opencs/model/world/refiddata.cpp         |  7 ++-
 apps/opencs/model/world/refiddata.hpp         |  3 +
 8 files changed, 111 insertions(+), 3 deletions(-)
 create mode 100644 apps/opencs/model/tools/referenceablecheck.cpp
 create mode 100644 apps/opencs/model/tools/referenceablecheck.hpp

diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt
index 1197e20140..baf677f8dd 100644
--- a/apps/opencs/CMakeLists.txt
+++ b/apps/opencs/CMakeLists.txt
@@ -38,7 +38,7 @@ opencs_units (model/tools
 
 opencs_units_noqt (model/tools
     mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
-    birthsigncheck spellcheck
+    birthsigncheck spellcheck referenceablecheck
     )
 
 
diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp
new file mode 100644
index 0000000000..01c8d30a72
--- /dev/null
+++ b/apps/opencs/model/tools/referenceablecheck.cpp
@@ -0,0 +1,63 @@
+#include "referenceablecheck.hpp"
+
+#include <sstream>
+#include <map>
+#include <cassert>
+
+#include <components/esm/loadbook.hpp>
+#include "../world/record.hpp"
+
+#include "../world/universalid.hpp"
+
+CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(const CSMWorld::RefIdData& referenceable) :
+    mReferencables(referenceable),
+    mBooksSize(0)
+{
+    setSizeVariables();
+}
+
+void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::string >& messages)
+{
+    //Checks for books, than, when stage is above mBooksSize goes to other checks, with stage - minus prev sizes as stage.
+    bool CheckPerformed = false;
+    
+    if (stage <= mBooksSize)
+    {	
+	bookCheck(stage, mReferencables.getBooks(), messages);
+        CheckPerformed = true;
+    }
+
+    if (CheckPerformed)
+    {
+        return;
+    }
+}
+
+int CSMTools::ReferenceableCheckStage::setup()
+{
+    return mReferencables.getSize();
+}
+
+void CSMTools::ReferenceableCheckStage::bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, std::vector< std::string >& messages)
+{
+    const CSMWorld::RecordBase& baserecord = records.getRecord(stage);
+
+    if (baserecord.isDeleted())
+    {
+        return;
+    }
+
+    const ESM::Book& Book = (static_cast<const CSMWorld::Record<ESM::Book>& >(baserecord)).get();
+    CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Book, Book.mId);
+
+    //Checking for name
+    if (Book.mName.empty())
+    {
+        messages.push_back(id.toString() + "|" + Book.mId + " has an empty name");
+    }
+}
+
+void CSMTools::ReferenceableCheckStage::setSizeVariables()
+{
+    mBooksSize = mReferencables.getBooks().getSize();
+}
diff --git a/apps/opencs/model/tools/referenceablecheck.hpp b/apps/opencs/model/tools/referenceablecheck.hpp
new file mode 100644
index 0000000000..509e8d8c0f
--- /dev/null
+++ b/apps/opencs/model/tools/referenceablecheck.hpp
@@ -0,0 +1,26 @@
+#ifndef REFERENCEABLECHECKSTAGE_H
+#define REFERENCEABLECHECKSTAGE_H
+
+#include "../world/universalid.hpp"
+#include "../doc/stage.hpp"
+#include "../world/data.hpp"
+#include "../world/refiddata.hpp"
+
+namespace CSMTools
+{
+    class ReferenceableCheckStage : public CSMDoc::Stage
+    {
+        public:
+            ReferenceableCheckStage(const CSMWorld::RefIdData& referenceable);
+            virtual void perform(int stage, std::vector< std::string >& messages);
+            virtual int setup();
+
+        private:
+            void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, std::vector< std::string >& messages);
+	    void setSizeVariables();
+
+            const CSMWorld::RefIdData mReferencables;
+	    int mBooksSize;
+    };
+}
+#endif // REFERENCEABLECHECKSTAGE_H
diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp
index cd4653280e..bca9f6fb7d 100644
--- a/apps/opencs/model/tools/tools.cpp
+++ b/apps/opencs/model/tools/tools.cpp
@@ -19,6 +19,7 @@
 #include "regioncheck.hpp"
 #include "birthsigncheck.hpp"
 #include "spellcheck.hpp"
+#include "referenceablecheck.hpp"
 
 CSMDoc::Operation *CSMTools::Tools::get (int type)
 {
@@ -74,6 +75,8 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
         mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
 
         mVerifier->appendStage (new SpellCheckStage (mData.getSpells()));
+	
+	mVerifier->appendStage( new ReferenceableCheckStage (mData.getReferenceables().getDataSet()));
     }
 
     return mVerifier;
@@ -138,4 +141,4 @@ void CSMTools::Tools::verifierMessage (const QString& message, int type)
 
     if (iter!=mActiveReports.end())
         mReports[iter->second]->add (message.toStdString());
-}
\ No newline at end of file
+}
diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp
index 86a542c5c3..9ed5268183 100644
--- a/apps/opencs/model/world/refidcollection.cpp
+++ b/apps/opencs/model/world/refidcollection.cpp
@@ -549,3 +549,9 @@ void CSMWorld::RefIdCollection::save (int index, ESM::ESMWriter& writer) const
 {
     mData.save (index, writer);
 }
+
+const CSMWorld::RefIdData& CSMWorld::RefIdCollection::getDataSet() const
+{
+    return mData;
+}
+
diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp
index 5ff4a70bf2..70cae53c84 100644
--- a/apps/opencs/model/world/refidcollection.hpp
+++ b/apps/opencs/model/world/refidcollection.hpp
@@ -107,6 +107,8 @@ namespace CSMWorld
             /// \return Success?
 
             void save (int index, ESM::ESMWriter& writer) const;
+	    
+	    const RefIdData& getDataSet() const; //I can't figure out a better name for this one :(
     };
 }
 
diff --git a/apps/opencs/model/world/refiddata.cpp b/apps/opencs/model/world/refiddata.cpp
index 8f59b0fe74..0fbfef4f10 100644
--- a/apps/opencs/model/world/refiddata.cpp
+++ b/apps/opencs/model/world/refiddata.cpp
@@ -230,4 +230,9 @@ void CSMWorld::RefIdData::save (int index, ESM::ESMWriter& writer) const
         throw std::logic_error ("invalid local index type");
 
     iter->second->save (localIndex.first, writer);
-}
\ No newline at end of file
+}
+
+const CSMWorld::RefIdDataContainer< ESM::Book >& CSMWorld::RefIdData::getBooks() const
+{
+    return mBooks;
+}
diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp
index 9595ab23b5..1590b58df3 100644
--- a/apps/opencs/model/world/refiddata.hpp
+++ b/apps/opencs/model/world/refiddata.hpp
@@ -219,6 +219,9 @@ namespace CSMWorld
             /// \param listDeleted include deleted record in the list
 
             void save (int index, ESM::ESMWriter& writer) const;
+	    
+	    //RECORD CONTAINERS ACCESS METHODS
+	    const RefIdDataContainer<ESM::Book>& getBooks() const;
     };
 }