changeset 1172:059391d3f8df db-changes

integration mainline->db-changes
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 22 Sep 2014 13:44:08 +0200
parents 1ea4094d077c (diff) fd3128b2cf45 (current diff)
children 3b372ab992ec
files CMakeLists.txt OrthancServer/OrthancRestApi/OrthancRestResources.cpp
diffstat 16 files changed, 262 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Sep 22 13:26:24 2014 +0200
+++ b/CMakeLists.txt	Mon Sep 22 13:44:08 2014 +0200
@@ -264,6 +264,7 @@
 set(EMBEDDED_FILES
   PREPARE_DATABASE ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/PrepareDatabase.sql
   UPGRADE_DATABASE_3_TO_4 ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/Upgrade3To4.sql
+  UPGRADE_DATABASE_4_TO_5 ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/Upgrade4To5.sql
   CONFIGURATION_SAMPLE ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Configuration.json
   DICOM_CONFORMANCE_STATEMENT ${CMAKE_CURRENT_SOURCE_DIR}/Resources/DicomConformanceStatement.txt
   LUA_TOOLBOX ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Toolbox.lua
--- a/Core/DicomFormat/DicomTag.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/Core/DicomFormat/DicomTag.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -244,4 +244,14 @@
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
   }
+
+
+  bool DicomTag::IsIdentifier() const
+  {
+    return (*this == DICOM_TAG_PATIENT_ID ||
+            *this == DICOM_TAG_STUDY_INSTANCE_UID ||
+            *this == DICOM_TAG_ACCESSION_NUMBER ||
+            *this == DICOM_TAG_SERIES_INSTANCE_UID ||
+            *this == DICOM_TAG_SOP_INSTANCE_UID);
+  }
 }
--- a/Core/DicomFormat/DicomTag.h	Mon Sep 22 13:26:24 2014 +0200
+++ b/Core/DicomFormat/DicomTag.h	Mon Sep 22 13:44:08 2014 +0200
@@ -86,6 +86,8 @@
 
     static void GetTagsForModule(std::set<DicomTag>& target,
                                  ResourceType module);
+
+    bool IsIdentifier() const;
   };
 
   // Aliases for the most useful tags
--- a/OrthancServer/DatabaseWrapper.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/DatabaseWrapper.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -92,6 +92,34 @@
       }
     };
 
+    class SignalResourceDeleted : public SQLite::IScalarFunction
+    {
+    private:
+      IServerIndexListener& listener_;
+
+    public:
+      SignalResourceDeleted(IServerIndexListener& listener) :
+        listener_(listener)
+      {
+      }
+
+      virtual const char* GetName() const
+      {
+        return "SignalResourceDeleted";
+      }
+
+      virtual unsigned int GetCardinality() const
+      {
+        return 2;
+      }
+
+      virtual void Compute(SQLite::FunctionContext& context)
+      {
+        ResourceType type = static_cast<ResourceType>(context.GetIntValue(1));
+        listener_.SignalResourceDeleted(type, context.GetStringValue(0));
+      }
+    };
+
     class SignalRemainingAncestor : public SQLite::IScalarFunction
     {
     private:
@@ -511,18 +539,35 @@
     }
   }
 
+
+  static void SetMainDicomTagsInternal(SQLite::Statement& s,
+                                       int64_t id,
+                                       const DicomElement& element)
+  {
+    s.BindInt64(0, id);
+    s.BindInt(1, element.GetTag().GetGroup());
+    s.BindInt(2, element.GetTag().GetElement());
+    s.BindString(3, element.GetValue().AsString());
+    s.Run();
+  }
+
+
   void DatabaseWrapper::SetMainDicomTags(int64_t id,
                                          const DicomMap& tags)
   {
     DicomArray flattened(tags);
     for (size_t i = 0; i < flattened.GetSize(); i++)
     {
-      SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)");
-      s.BindInt64(0, id);
-      s.BindInt(1, flattened.GetElement(i).GetTag().GetGroup());
-      s.BindInt(2, flattened.GetElement(i).GetTag().GetElement());
-      s.BindString(3, flattened.GetElement(i).GetValue().AsString());
-      s.Run();
+      if (flattened.GetElement(i).GetTag().IsIdentifier())
+      {
+        SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)");
+        SetMainDicomTagsInternal(s, id, flattened.GetElement(i));
+      }
+      else
+      {
+        SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifier VALUES(?, ?, ?, ?)");
+        SetMainDicomTagsInternal(s, id, flattened.GetElement(i));
+      }
     }
   }
 
@@ -539,6 +584,15 @@
                    s.ColumnInt(2),
                    s.ColumnString(3));
     }
+
+    SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT * FROM DicomIdentifiers WHERE id=?");
+    s2.BindInt64(0, id);
+    while (s2.Step())
+    {
+      map.SetValue(s2.ColumnInt(1),
+                   s2.ColumnInt(2),
+                   s2.ColumnString(3));
+    }
   }
 
 
@@ -852,11 +906,12 @@
       /**
        * History of the database versions:
        *  - Version 3: from Orthanc 0.3.2 to Orthanc 0.7.2 (inclusive)
-       *  - Version 4: from Orthanc 0.7.3 (inclusive)
+       *  - Version 4: from Orthanc 0.7.3 to Orthanc 0.8.3 (inclusive)
+       *  - Version 5: from Orthanc 0.8.4 (inclusive)
        **/
 
-      // This version of Orthanc is only compatible with versions 3 of 4 of the DB schema
-      ok = (v == 3 || v == 4);
+      // This version of Orthanc is only compatible with versions 3, 4 and 5 of the DB schema
+      ok = (v == 3 || v == 4 || v == 5);
 
       if (v == 3)
       {
@@ -866,6 +921,18 @@
         db_.BeginTransaction();
         db_.Execute(upgrade);
         db_.CommitTransaction();
+        v = 4;
+      }
+
+      if (v == 4)
+      {
+        LOG(WARNING) << "Upgrading database version from 4 to 5";
+        std::string upgrade;
+        EmbeddedResources::GetFileResource(upgrade, EmbeddedResources::UPGRADE_DATABASE_4_TO_5);
+        db_.BeginTransaction();
+        db_.Execute(upgrade);
+        db_.CommitTransaction();
+        v = 5;
       }
     }
     catch (boost::bad_lexical_cast&)
@@ -881,6 +948,7 @@
     signalRemainingAncestor_ = new Internals::SignalRemainingAncestor;
     db_.Register(signalRemainingAncestor_);
     db_.Register(new Internals::SignalFileDeleted(listener_));
+    db_.Register(new Internals::SignalResourceDeleted(listener_));
   }
 
   uint64_t DatabaseWrapper::GetResourceCount(ResourceType resourceType)
@@ -1010,12 +1078,17 @@
   }
 
 
-  void  DatabaseWrapper::LookupTagValue(std::list<int64_t>& result,
-                                        DicomTag tag,
-                                        const std::string& value)
+  void  DatabaseWrapper::LookupIdentifier(std::list<int64_t>& result,
+                                          const DicomTag& tag,
+                                          const std::string& value)
   {
+    if (!tag.IsIdentifier())
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+
     SQLite::Statement s(db_, SQLITE_FROM_HERE, 
-                        "SELECT id FROM MainDicomTags WHERE tagGroup=? AND tagElement=? and value=?");
+                        "SELECT id FROM DicomIdentifiers WHERE tagGroup=? AND tagElement=? and value=?");
 
     s.BindInt(0, tag.GetGroup());
     s.BindInt(1, tag.GetElement());
@@ -1030,11 +1103,11 @@
   }
 
 
-  void  DatabaseWrapper::LookupTagValue(std::list<int64_t>& result,
-                                        const std::string& value)
+  void  DatabaseWrapper::LookupIdentifier(std::list<int64_t>& result,
+                                          const std::string& value)
   {
     SQLite::Statement s(db_, SQLITE_FROM_HERE, 
-                        "SELECT id FROM MainDicomTags WHERE value=?");
+                        "SELECT id FROM DicomIdentifiers WHERE value=?");
 
     s.BindString(0, value);
 
--- a/OrthancServer/DatabaseWrapper.h	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/DatabaseWrapper.h	Mon Sep 22 13:44:08 2014 +0200
@@ -229,12 +229,12 @@
 
     bool IsExistingResource(int64_t internalId);
 
-    void LookupTagValue(std::list<int64_t>& result,
-                        DicomTag tag,
-                        const std::string& value);
+    void LookupIdentifier(std::list<int64_t>& result,
+                          const DicomTag& tag,
+                          const std::string& value);
 
-    void LookupTagValue(std::list<int64_t>& result,
-                        const std::string& value);
+    void LookupIdentifier(std::list<int64_t>& result,
+                          const std::string& value);
 
     void GetAllMetadata(std::map<MetadataType, std::string>& result,
                         int64_t id);
--- a/OrthancServer/IServerIndexListener.h	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/IServerIndexListener.h	Mon Sep 22 13:44:08 2014 +0200
@@ -47,6 +47,9 @@
     virtual void SignalRemainingAncestor(ResourceType parentType,
                                          const std::string& publicId) = 0;
 
+    virtual void SignalResourceDeleted(ResourceType type,
+                                       const std::string& publicId) = 0;
+
     virtual void SignalFileDeleted(const FileInfo& info) = 0;
   };
 }
--- a/OrthancServer/OrthancFindRequestHandler.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/OrthancFindRequestHandler.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -320,7 +320,7 @@
                   << FromDcmtkBridge::GetName(tag) << " (value: " << value << ")";
 
         std::list<std::string> resources;
-        index_.LookupTagValue(resources, tag, value, level_);
+        index_.LookupIdentifier(resources, tag, value, level_);
 
         if (isFilterApplied_)
         {
--- a/OrthancServer/OrthancMoveRequestHandler.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/OrthancMoveRequestHandler.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -101,7 +101,7 @@
   }
 
 
-  bool OrthancMoveRequestHandler::LookupResource(std::string& publicId,
+  bool OrthancMoveRequestHandler::LookupIdentifier(std::string& publicId,
                                                  DicomTag tag,
                                                  const DicomMap& input)
   {
@@ -113,7 +113,7 @@
     std::string value = input.GetValue(tag).AsString();
 
     std::list<std::string> ids;
-    context_.GetIndex().LookupTagValue(ids, tag, value);
+    context_.GetIndex().LookupIdentifier(ids, tag, value);
 
     if (ids.size() != 1)
     {
@@ -155,19 +155,19 @@
     switch (level)
     {
       case ResourceType_Patient:
-        ok = LookupResource(publicId, DICOM_TAG_PATIENT_ID, input);
+        ok = LookupIdentifier(publicId, DICOM_TAG_PATIENT_ID, input);
         break;
 
       case ResourceType_Study:
-        ok = LookupResource(publicId, DICOM_TAG_STUDY_INSTANCE_UID, input);
+        ok = LookupIdentifier(publicId, DICOM_TAG_STUDY_INSTANCE_UID, input);
         break;
 
       case ResourceType_Series:
-        ok = LookupResource(publicId, DICOM_TAG_SERIES_INSTANCE_UID, input);
+        ok = LookupIdentifier(publicId, DICOM_TAG_SERIES_INSTANCE_UID, input);
         break;
 
       case ResourceType_Instance:
-        ok = LookupResource(publicId, DICOM_TAG_SOP_INSTANCE_UID, input);
+        ok = LookupIdentifier(publicId, DICOM_TAG_SOP_INSTANCE_UID, input);
         break;
 
       default:
--- a/OrthancServer/OrthancMoveRequestHandler.h	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/OrthancMoveRequestHandler.h	Mon Sep 22 13:44:08 2014 +0200
@@ -41,9 +41,9 @@
   private:
     ServerContext& context_;
 
-    bool LookupResource(std::string& publicId,
-                        DicomTag tag,
-                        const DicomMap& input);
+    bool LookupIdentifier(std::string& publicId,
+                          DicomTag tag,
+                          const DicomMap& input);
 
   public:
     OrthancMoveRequestHandler(ServerContext& context) :
--- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -794,7 +794,7 @@
     std::string tag = call.GetPostBody();
     Resources resources;
 
-    OrthancRestApi::GetIndex(call).LookupTagValue(resources, tag);
+    OrthancRestApi::GetIndex(call).LookupIdentifier(resources, tag);
 
     Json::Value result = Json::arrayValue;
     
--- a/OrthancServer/PrepareDatabase.sql	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/PrepareDatabase.sql	Mon Sep 22 13:44:08 2014 +0200
@@ -18,6 +18,15 @@
        PRIMARY KEY(id, tagGroup, tagElement)
        );
 
+-- The following table was added in Orthanc 0.8.4 (database v5)
+CREATE TABLE DicomIdentifiers(
+       id INTEGER REFERENCES Resources(internalId) ON DELETE CASCADE,
+       tagGroup INTEGER,
+       tagElement INTEGER,
+       value TEXT,
+       PRIMARY KEY(id, tagGroup, tagElement)
+       );
+
 CREATE TABLE Metadata(
        id INTEGER REFERENCES Resources(internalId) ON DELETE CASCADE,
        type INTEGER,
@@ -68,8 +77,14 @@
 CREATE INDEX PatientRecyclingIndex ON PatientRecyclingOrder(patientId);
 
 CREATE INDEX MainDicomTagsIndex1 ON MainDicomTags(id);
-CREATE INDEX MainDicomTagsIndex2 ON MainDicomTags(tagGroup, tagElement);
-CREATE INDEX MainDicomTagsIndexValues ON MainDicomTags(value COLLATE BINARY);
+-- The 2 following indexes were removed in Orthanc 0.8.4 (database v5), to speed up
+-- CREATE INDEX MainDicomTagsIndex2 ON MainDicomTags(tagGroup, tagElement);
+-- CREATE INDEX MainDicomTagsIndexValues ON MainDicomTags(value COLLATE BINARY);
+
+-- The 3 following indexes were added in Orthanc 0.8.4 (database v5)
+CREATE INDEX DicomIdentifiersIndex1 ON DicomIdentifiers(id);
+CREATE INDEX DicomIdentifiersIndex2 ON DicomIdentifiers(tagGroup, tagElement);
+CREATE INDEX DicomIdentifiersIndexValues ON DicomIdentifiers(value COLLATE BINARY);
 
 CREATE INDEX ChangesIndex ON Changes(internalId);
 
@@ -85,6 +100,7 @@
 CREATE TRIGGER ResourceDeleted
 AFTER DELETE ON Resources
 BEGIN
+  SELECT SignalResourceDeleted(old.publicId, old.resourceType);  -- New in Orthanc 0.8.4 (db v5)
   SELECT SignalRemainingAncestor(parent.publicId, parent.resourceType) 
     FROM Resources AS parent WHERE internalId = old.parentId;
 END;
@@ -107,4 +123,4 @@
 
 -- Set the version of the database schema
 -- The "1" corresponds to the "GlobalProperty_DatabaseSchemaVersion" enumeration
-INSERT INTO GlobalProperties VALUES (1, "4");
+INSERT INTO GlobalProperties VALUES (1, "5");
--- a/OrthancServer/ServerIndex.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/ServerIndex.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -137,6 +137,13 @@
         sizeOfFilesToRemove_ += info.GetCompressedSize();
       }
 
+      virtual void SignalResourceDeleted(ResourceType type,
+                                         const std::string& publicId)
+      {
+        LOG(INFO) << "Resource " << publicId << " of type " << EnumerationToString(type) << " is deleted";
+      }
+
+
       bool HasRemainingLevel() const
       {
         return hasRemainingLevel_;
@@ -1625,17 +1632,17 @@
 
 
 
-  void ServerIndex::LookupTagValue(std::list<std::string>& result,
-                                   DicomTag tag,
-                                   const std::string& value,
-                                   ResourceType type)
+  void ServerIndex::LookupIdentifier(std::list<std::string>& result,
+                                     const DicomTag& tag,
+                                     const std::string& value,
+                                     ResourceType type)
   {
     result.clear();
 
     boost::mutex::scoped_lock lock(mutex_);
 
     std::list<int64_t> id;
-    db_->LookupTagValue(id, tag, value);
+    db_->LookupIdentifier(id, tag, value);
 
     for (std::list<int64_t>::const_iterator 
            it = id.begin(); it != id.end(); ++it)
@@ -1648,16 +1655,16 @@
   }
 
 
-  void ServerIndex::LookupTagValue(std::list<std::string>& result,
-                                   DicomTag tag,
-                                   const std::string& value)
+  void ServerIndex::LookupIdentifier(std::list<std::string>& result,
+                                     const DicomTag& tag,
+                                     const std::string& value)
   {
     result.clear();
 
     boost::mutex::scoped_lock lock(mutex_);
 
     std::list<int64_t> id;
-    db_->LookupTagValue(id, tag, value);
+    db_->LookupIdentifier(id, tag, value);
 
     for (std::list<int64_t>::const_iterator 
            it = id.begin(); it != id.end(); ++it)
@@ -1667,15 +1674,15 @@
   }
 
 
-  void ServerIndex::LookupTagValue(std::list< std::pair<ResourceType, std::string> >& result,
-                                   const std::string& value)
+  void ServerIndex::LookupIdentifier(std::list< std::pair<ResourceType, std::string> >& result,
+                                     const std::string& value)
   {
     result.clear();
 
     boost::mutex::scoped_lock lock(mutex_);
 
     std::list<int64_t> id;
-    db_->LookupTagValue(id, value);
+    db_->LookupIdentifier(id, value);
 
     for (std::list<int64_t>::const_iterator 
            it = id.begin(); it != id.end(); ++it)
--- a/OrthancServer/ServerIndex.h	Mon Sep 22 13:26:24 2014 +0200
+++ b/OrthancServer/ServerIndex.h	Mon Sep 22 13:44:08 2014 +0200
@@ -216,17 +216,17 @@
                        /* out */ unsigned int& countInstances, 
                        const std::string& publicId);
 
-    void LookupTagValue(std::list<std::string>& result,
-                        DicomTag tag,
-                        const std::string& value,
-                        ResourceType type);
+    void LookupIdentifier(std::list<std::string>& result,
+                          const DicomTag& tag,
+                          const std::string& value,
+                          ResourceType type);
 
-    void LookupTagValue(std::list<std::string>& result,
-                        DicomTag tag,
-                        const std::string& value);
+    void LookupIdentifier(std::list<std::string>& result,
+                          const DicomTag& tag,
+                          const std::string& value);
 
-    void LookupTagValue(std::list< std::pair<ResourceType, std::string> >& result,
-                        const std::string& value);
+    void LookupIdentifier(std::list< std::pair<ResourceType, std::string> >& result,
+                          const std::string& value);
 
     StoreStatus AddAttachment(const FileInfo& attachment,
                               const std::string& publicId);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancServer/Upgrade4To5.sql	Mon Sep 22 13:44:08 2014 +0200
@@ -0,0 +1,58 @@
+-- This SQLite script updates the version of the Orthanc database from 4 to 5.
+
+
+-- Remove 2 indexes to speed up
+
+DROP INDEX MainDicomTagsIndex2;
+DROP INDEX MainDicomTagsIndexValues;
+
+
+-- Add a new table to index the DICOM identifiers
+
+CREATE TABLE DicomIdentifiers(
+       id INTEGER REFERENCES Resources(internalId) ON DELETE CASCADE,
+       tagGroup INTEGER,
+       tagElement INTEGER,
+       value TEXT,
+       PRIMARY KEY(id, tagGroup, tagElement)
+       );
+
+CREATE INDEX DicomIdentifiersIndex1 ON DicomIdentifiers(id);
+CREATE INDEX DicomIdentifiersIndex2 ON DicomIdentifiers(tagGroup, tagElement);
+CREATE INDEX DicomIdentifiersIndexValues ON DicomIdentifiers(value COLLATE BINARY);
+
+
+-- Migrate data from MainDicomTags to MainResourcesTags and MainInstancesTags
+
+INSERT INTO DicomIdentifiers SELECT * FROM MainDicomTags
+       WHERE ((tagGroup = 16 AND tagElement = 32) OR  -- PatientID (0x0010, 0x0020)
+              (tagGroup = 32 AND tagElement = 13) OR  -- StudyInstanceUID (0x0020, 0x000d)
+              (tagGroup = 8  AND tagElement = 80) OR  -- AccessionNumber (0x0008, 0x0050)
+              (tagGroup = 32 AND tagElement = 14) OR  -- SeriesInstanceUID (0x0020, 0x000e)
+              (tagGroup = 8  AND tagElement = 24));   -- SOPInstanceUID (0x0008, 0x0018)
+
+DELETE FROM MainDicomTags
+       WHERE ((tagGroup = 16 AND tagElement = 32) OR  -- PatientID (0x0010, 0x0020)
+              (tagGroup = 32 AND tagElement = 13) OR  -- StudyInstanceUID (0x0020, 0x000d)
+              (tagGroup = 8  AND tagElement = 80) OR  -- AccessionNumber (0x0008, 0x0050)
+              (tagGroup = 32 AND tagElement = 14) OR  -- SeriesInstanceUID (0x0020, 0x000e)
+              (tagGroup = 8  AND tagElement = 24));   -- SOPInstanceUID (0x0008, 0x0018)
+
+
+-- Upgrade the "ResourceDeleted" trigger
+
+DROP TRIGGER ResourceDeleted;
+
+CREATE TRIGGER ResourceDeleted
+AFTER DELETE ON Resources
+BEGIN
+  SELECT SignalResourceDeleted(old.publicId, old.resourceType);
+  SELECT SignalRemainingAncestor(parent.publicId, parent.resourceType) 
+    FROM Resources AS parent WHERE internalId = old.parentId;
+END;
+
+
+-- Change the database version
+-- The "1" corresponds to the "GlobalProperty_DatabaseSchemaVersion" enumeration
+
+UPDATE GlobalProperties SET value="5" WHERE property=1;
--- a/Plugins/Engine/OrthancPlugins.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -618,7 +618,7 @@
     }
 
     std::list<std::string> result;
-    pimpl_->context_.GetIndex().LookupTagValue(result, tag, p.argument, level);
+    pimpl_->context_.GetIndex().LookupIdentifier(result, tag, p.argument, level);
 
     if (result.size() == 1)
     {
--- a/UnitTestsSources/ServerIndexTests.cpp	Mon Sep 22 13:26:24 2014 +0200
+++ b/UnitTestsSources/ServerIndexTests.cpp	Mon Sep 22 13:44:08 2014 +0200
@@ -58,6 +58,7 @@
   {
   public:
     std::vector<std::string> deletedFiles_;
+    std::vector<std::string> deletedResources_;
     std::string ancestorId_;
     ResourceType ancestorType_;
 
@@ -79,7 +80,15 @@
       const std::string fileUuid = info.GetUuid();
       deletedFiles_.push_back(fileUuid);
       LOG(INFO) << "A file must be removed: " << fileUuid;
-    }                                
+    }       
+
+    virtual void SignalResourceDeleted(ResourceType type,
+                                       const std::string& publicId)
+    {
+      deletedResources_.push_back(publicId);
+      LOG(INFO) << "A resource was removed: " << publicId;
+    }
+                         
   };
 
 
@@ -281,12 +290,14 @@
   ASSERT_EQ(CompressionType_None, att.GetCompressionType());
 
   ASSERT_EQ(0u, listener_->deletedFiles_.size());
+  ASSERT_EQ(0u, listener_->deletedResources_.size());
   ASSERT_EQ(7u, index_->GetTableRecordCount("Resources")); 
   ASSERT_EQ(3u, index_->GetTableRecordCount("AttachedFiles"));
   ASSERT_EQ(1u, index_->GetTableRecordCount("Metadata"));
   ASSERT_EQ(1u, index_->GetTableRecordCount("MainDicomTags"));
+
   index_->DeleteResource(a[0]);
-
+  ASSERT_EQ(5u, listener_->deletedResources_.size());
   ASSERT_EQ(2u, listener_->deletedFiles_.size());
   ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), 
                          listener_->deletedFiles_.end(),
@@ -300,6 +311,7 @@
   ASSERT_EQ(1u, index_->GetTableRecordCount("AttachedFiles"));
   ASSERT_EQ(0u, index_->GetTableRecordCount("MainDicomTags"));
   index_->DeleteResource(a[5]);
+  ASSERT_EQ(7u, listener_->deletedResources_.size());
   ASSERT_EQ(0u, index_->GetTableRecordCount("Resources"));
   ASSERT_EQ(0u, index_->GetTableRecordCount("AttachedFiles"));
   ASSERT_EQ(2u, index_->GetTableRecordCount("GlobalProperties"));
@@ -395,9 +407,11 @@
   ASSERT_EQ(10u, index_->GetTableRecordCount("PatientRecyclingOrder")); 
 
   listener_->Reset();
+  ASSERT_EQ(0u, listener_->deletedResources_.size());
 
   index_->DeleteResource(patients[5]);
   index_->DeleteResource(patients[0]);
+  ASSERT_EQ(2u, listener_->deletedResources_.size());
   ASSERT_EQ(8u, index_->GetTableRecordCount("Resources")); 
   ASSERT_EQ(8u, index_->GetTableRecordCount("PatientRecyclingOrder"));
 
@@ -408,20 +422,27 @@
   int64_t p;
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]);
   index_->DeleteResource(p);
+  ASSERT_EQ(3u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]);
   index_->DeleteResource(p);
+  ASSERT_EQ(4u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]);
   index_->DeleteResource(p);
+  ASSERT_EQ(5u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]);
   index_->DeleteResource(p);
+  ASSERT_EQ(6u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[6]);
   index_->DeleteResource(p);
   index_->DeleteResource(patients[8]);
+  ASSERT_EQ(8u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[7]);
   index_->DeleteResource(p);
+  ASSERT_EQ(9u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[9]);
   index_->DeleteResource(p);
   ASSERT_FALSE(index_->SelectPatientToRecycle(p));
+  ASSERT_EQ(10u, listener_->deletedResources_.size());
 
   ASSERT_EQ(10u, listener_->deletedFiles_.size());
   ASSERT_EQ(0u, index_->GetTableRecordCount("Resources")); 
@@ -477,16 +498,21 @@
 
   // Unprotecting a patient puts it at the last position in the recycling queue
   int64_t p;
+  ASSERT_EQ(0u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[0]);
   index_->DeleteResource(p);
+  ASSERT_EQ(1u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p, patients[1])); ASSERT_EQ(p, patients[4]);
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]);
   index_->DeleteResource(p);
+  ASSERT_EQ(2u, listener_->deletedResources_.size());
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]);
   index_->DeleteResource(p);
+  ASSERT_EQ(3u, listener_->deletedResources_.size());
   ASSERT_FALSE(index_->SelectPatientToRecycle(p, patients[2]));
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]);
   index_->DeleteResource(p);
+  ASSERT_EQ(4u, listener_->deletedResources_.size());
   // "patients[3]" is still protected
   ASSERT_FALSE(index_->SelectPatientToRecycle(p));
 
@@ -500,6 +526,7 @@
   ASSERT_TRUE(index_->SelectPatientToRecycle(p, patients[2]));
   ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]);
   index_->DeleteResource(p);
+  ASSERT_EQ(5u, listener_->deletedResources_.size());
 
   ASSERT_EQ(5u, listener_->deletedFiles_.size());
   ASSERT_EQ(0u, index_->GetTableRecordCount("Resources")); 
@@ -518,7 +545,7 @@
 
 
 
-TEST_P(DatabaseWrapperTest, LookupTagValue)
+TEST_P(DatabaseWrapperTest, LookupIdentifier)
 {
   int64_t a[] = {
     index_->CreateResource("a", ResourceType_Study),   // 0
@@ -535,29 +562,29 @@
 
   std::list<int64_t> s;
 
-  index_->LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "0");
+  index_->LookupIdentifier(s, DICOM_TAG_STUDY_INSTANCE_UID, "0");
   ASSERT_EQ(2u, s.size());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end());
 
-  index_->LookupTagValue(s, "0");
+  index_->LookupIdentifier(s, "0");
   ASSERT_EQ(3u, s.size());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[3]) != s.end());
 
-  index_->LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "1");
+  index_->LookupIdentifier(s, DICOM_TAG_STUDY_INSTANCE_UID, "1");
   ASSERT_EQ(1u, s.size());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end());
 
-  index_->LookupTagValue(s, "1");
+  index_->LookupIdentifier(s, "1");
   ASSERT_EQ(1u, s.size());
   ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end());
 
 
   /*{
       std::list<std::string> s;
-      context.GetIndex().LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "1.2.250.1.74.20130819132500.29000036381059");
+      context.GetIndex().LookupIdentifier(s, DICOM_TAG_STUDY_INSTANCE_UID, "1.2.250.1.74.20130819132500.29000036381059");
       for (std::list<std::string>::iterator i = s.begin(); i != s.end(); i++)
       {
         std::cout << "*** " << *i << std::endl;;