changeset 5592:1e2631b8b9af find-refactoring

GenericFind::Execute() is working for a basic request
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 03 May 2024 21:26:06 +0200
parents 043c8016ed6a
children 862b54b4cfe2
files OrthancServer/Sources/Database/Compatibility/GenericFind.cpp OrthancServer/Sources/Database/FindRequest.cpp OrthancServer/Sources/Database/FindRequest.h OrthancServer/Sources/Database/FindResponse.cpp OrthancServer/Sources/Database/FindResponse.h OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp OrthancServer/Sources/ServerContext.cpp
diffstat 9 files changed, 105 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp	Fri May 03 21:26:06 2024 +0200
@@ -22,6 +22,7 @@
 
 #include "GenericFind.h"
 
+#include "../../../../OrthancFramework/Sources/DicomFormat/DicomArray.h"
 #include "../../../../OrthancFramework/Sources/OrthancException.h"
 
 
@@ -38,10 +39,6 @@
           !request.GetOrthancIdentifiers().HasInstanceId() &&
           request.GetDicomTagConstraintsCount() == 0 &&
           request.GetMetadataConstraintsCount() == 0 &&
-          !request.IsRetrieveTagsAtLevel(ResourceType_Patient) &&
-          !request.IsRetrieveTagsAtLevel(ResourceType_Study) &&
-          !request.IsRetrieveTagsAtLevel(ResourceType_Series) &&
-          !request.IsRetrieveTagsAtLevel(ResourceType_Instance) &&
           request.GetOrdering().empty() &&
           request.GetLabels().empty())
       {
@@ -58,7 +55,53 @@
 
         for (std::list<std::string>::const_iterator it = ids.begin(); it != ids.end(); ++it)
         {
-          response.Add(new FindResponse::Resource(request.GetLevel(), *it));
+          int64_t internalId;
+          ResourceType t;
+          if (!transaction_.LookupResource(internalId, t, *it) ||
+              t != request.GetLevel())
+          {
+            throw OrthancException(ErrorCode_InternalError);
+          }
+
+          std::unique_ptr<FindResponse::Resource> resource(new FindResponse::Resource(request.GetLevel(), *it));
+
+          if (request.IsRetrieveMainDicomTags())
+          {
+            DicomMap m;
+            transaction_.GetMainDicomTags(m, internalId);
+
+            DicomArray a(m);
+            for (size_t i = 0; i < a.GetSize(); i++)
+            {
+              const DicomElement& element = a.GetElement(i);
+              if (element.GetValue().IsString())
+              {
+                resource->AddStringDicomTag(element.GetTag().GetGroup(), element.GetTag().GetElement(),
+                                            element.GetValue().GetContent());
+              }
+              else
+              {
+                throw OrthancException(ErrorCode_BadParameterType);
+              }
+            }
+          }
+
+          if (request.IsRetrieveParentIdentifier())
+          {
+            int64_t parentId;
+            if (transaction_.LookupParent(parentId, internalId))
+            {
+              resource->SetParentIdentifier(transaction_.GetPublicId(parentId));
+            }
+            else
+            {
+              throw OrthancException(ErrorCode_InternalError);
+            }
+          }
+
+          // TODO-FIND: Continue
+
+          response.Add(resource.release());
         }
       }
       else
@@ -75,10 +118,10 @@
       {
         const FindResponse::Resource& resource = response.GetResource(i);
 
-        if (request.IsRetrieveTagsAtLevel(request.GetLevel()))
+        if (request.IsRetrieveMainDicomTags())
         {
           DicomMap tmp;
-          resource.GetDicomTagsAtLevel(tmp, request.GetLevel());
+          resource.GetMainDicomTags(tmp);
           if (tmp.GetSize() == 0)
           {
             throw OrthancException(ErrorCode_InternalError);
--- a/OrthancServer/Sources/Database/FindRequest.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/FindRequest.cpp	Fri May 03 21:26:06 2024 +0200
@@ -29,43 +29,12 @@
 
 namespace Orthanc
 {
-  bool FindRequest::IsCompatibleLevel(ResourceType levelOfInterest) const
-  {
-    switch (level_)
-    {
-      case ResourceType_Patient:
-        return (levelOfInterest == ResourceType_Patient);
-
-      case ResourceType_Study:
-        return (levelOfInterest == ResourceType_Patient ||
-                levelOfInterest == ResourceType_Study);
-
-      case ResourceType_Series:
-        return (levelOfInterest == ResourceType_Patient ||
-                levelOfInterest == ResourceType_Study ||
-                levelOfInterest == ResourceType_Series);
-
-      case ResourceType_Instance:
-        return (levelOfInterest == ResourceType_Patient ||
-                levelOfInterest == ResourceType_Study ||
-                levelOfInterest == ResourceType_Series ||
-                levelOfInterest == ResourceType_Instance);
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
   FindRequest::FindRequest(ResourceType level) :
     level_(level),
     hasLimits_(false),
     limitsSince_(0),
     limitsCount_(0),
-    retrievePatientTags_(false),
-    retrieveStudyTags_(false),
-    retrieveSeriesTags_(false),
-    retrieveInstanceTags_(false),
+    retrieveMainDicomTags_(false),
     retrieveMetadata_(false),
     retrieveLabels_(false),
     retrieveAttachments_(false),
@@ -146,66 +115,13 @@
   }
 
 
-  void FindRequest::SetRetrieveTagsAtLevel(ResourceType levelOfInterest,
-                                           bool retrieve)
-  {
-    if (!IsCompatibleLevel(levelOfInterest))
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    switch (levelOfInterest)
-    {
-      case ResourceType_Patient:
-        retrievePatientTags_ = true;
-        break;
-
-      case ResourceType_Study:
-        retrieveStudyTags_ = true;
-        break;
-
-      case ResourceType_Series:
-        retrieveSeriesTags_ = true;
-        break;
-
-      case ResourceType_Instance:
-        retrieveInstanceTags_ = true;
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  bool FindRequest::IsRetrieveTagsAtLevel(ResourceType levelOfInterest) const
-  {
-    switch (levelOfInterest)
-    {
-      case ResourceType_Patient:
-        return retrievePatientTags_;
-
-      case ResourceType_Study:
-        return retrieveStudyTags_;
-
-      case ResourceType_Series:
-        return retrieveSeriesTags_;
-
-      case ResourceType_Instance:
-        return retrieveInstanceTags_;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
   void FindRequest::AddOrdering(const DicomTag& tag,
                                 OrderingDirection direction)
   {
     ordering_.push_back(new Ordering(Key(tag), direction));
   }
 
+
   void FindRequest::AddOrdering(MetadataType metadataType, 
                                 OrderingDirection direction)
   {
--- a/OrthancServer/Sources/Database/FindRequest.h	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/FindRequest.h	Fri May 03 21:26:06 2024 +0200
@@ -165,11 +165,7 @@
     LabelsConstraint                     labelsContraint_;
     std::deque<Ordering*>                ordering_;             // The ordering criteria (note: the order is important !)
 
-    bool                                 retrievePatientTags_;
-    bool                                 retrieveStudyTags_;
-    bool                                 retrieveSeriesTags_;
-    bool                                 retrieveInstanceTags_;
-
+    bool                                 retrieveMainDicomTags_;
     bool                                 retrieveMetadata_;
     bool                                 retrieveLabels_;
     bool                                 retrieveAttachments_;
@@ -177,8 +173,6 @@
     bool                                 retrieveChildrenIdentifiers_;
     bool                                 retrieveChildrenMetadata_;
 
-    bool IsCompatibleLevel(ResourceType levelOfInterest) const;
-
   public:
     explicit FindRequest(ResourceType level);
 
@@ -240,11 +234,6 @@
 
     uint64_t GetLimitsCount() const;
 
-    void SetRetrieveTagsAtLevel(ResourceType levelOfInterest,
-                                bool retrieve);
-
-    bool IsRetrieveTagsAtLevel(ResourceType levelOfInterest) const;
-
     void AddOrdering(const DicomTag& tag, OrderingDirection direction);
 
     void AddOrdering(MetadataType metadataType, OrderingDirection direction);
@@ -274,6 +263,16 @@
       retrieveMetadata_ = retrieve;
     }
 
+    bool IsRetrieveMainDicomTags() const
+    {
+      return retrieveMainDicomTags_;
+    }
+
+    void SetRetrieveMainDicomTags(bool retrieve)
+    {
+      retrieveMainDicomTags_ = retrieve;
+    }
+
     bool IsRetrieveMetadata() const
     {
       return retrieveMetadata_;
--- a/OrthancServer/Sources/Database/FindResponse.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/FindResponse.cpp	Fri May 03 21:26:06 2024 +0200
@@ -30,7 +30,7 @@
 
 namespace Orthanc
 {
-  class FindResponse::DicomTagsAtLevel::DicomValue : public boost::noncopyable
+  class FindResponse::Resource::DicomValue : public boost::noncopyable
   {
   public:
     enum ValueType
@@ -73,24 +73,14 @@
   };
 
 
-  FindResponse::DicomTagsAtLevel::~DicomTagsAtLevel()
-  {
-    for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
-    {
-      assert(it->second != NULL);
-      delete it->second;
-    }
-  }
-
-
-  void FindResponse::DicomTagsAtLevel::AddNullValue(uint16_t group,
-                                                    uint16_t element)
+  void FindResponse::Resource::AddNullDicomTag(uint16_t group,
+                                               uint16_t element)
   {
     const DicomTag tag(group, element);
 
-    if (content_.find(tag) == content_.end())
+    if (mainDicomTags_.find(tag) == mainDicomTags_.end())
     {
-      content_[tag] = new DicomValue(DicomValue::ValueType_Null, "");
+      mainDicomTags_[tag] = new DicomValue(DicomValue::ValueType_Null, "");
     }
     else
     {
@@ -99,15 +89,15 @@
   }
 
 
-  void FindResponse::DicomTagsAtLevel::AddStringValue(uint16_t group,
-                                                      uint16_t element,
-                                                      const std::string& value)
+  void FindResponse::Resource::AddStringDicomTag(uint16_t group,
+                                                 uint16_t element,
+                                                 const std::string& value)
   {
     const DicomTag tag(group, element);
 
-    if (content_.find(tag) == content_.end())
+    if (mainDicomTags_.find(tag) == mainDicomTags_.end())
     {
-      content_[tag] = new DicomValue(DicomValue::ValueType_String, value);
+      mainDicomTags_[tag] = new DicomValue(DicomValue::ValueType_String, value);
     }
     else
     {
@@ -116,9 +106,9 @@
   }
 
 
-  void FindResponse::DicomTagsAtLevel::Fill(DicomMap& target) const
+  void FindResponse::Resource::GetMainDicomTags(DicomMap& target) const
   {
-    for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
+    for (MainDicomTags::const_iterator it = mainDicomTags_.begin(); it != mainDicomTags_.end(); ++it)
     {
       assert(it->second != NULL);
 
@@ -152,28 +142,6 @@
   }
 
 
-  FindResponse::DicomTagsAtLevel& FindResponse::Resource::GetDicomTagsAtLevel(ResourceType level)
-  {
-    switch (level)
-    {
-      case ResourceType_Patient:
-        return patientTags_;
-
-      case ResourceType_Study:
-        return studyTags_;
-
-      case ResourceType_Series:
-        return seriesTags_;
-
-      case ResourceType_Instance:
-        return instanceTags_;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
   FindResponse::ChildrenAtLevel& FindResponse::Resource::GetChildrenAtLevel(ResourceType level)
   {
     switch (level)
@@ -275,6 +243,16 @@
   }
 
 
+  FindResponse::Resource::~Resource()
+  {
+    for (MainDicomTags::iterator it = mainDicomTags_.begin(); it != mainDicomTags_.end(); ++it)
+    {
+      assert(it->second != NULL);
+      delete it->second;
+    }
+  }
+
+
   void FindResponse::Resource::SetParentIdentifier(const std::string& id)
   {
     if (level_ == ResourceType_Patient)
--- a/OrthancServer/Sources/Database/FindResponse.h	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/FindResponse.h	Fri May 03 21:26:06 2024 +0200
@@ -41,29 +41,6 @@
   class FindResponse : public boost::noncopyable
   {
   private:
-    class DicomTagsAtLevel : public boost::noncopyable
-    {
-    private:
-      class DicomValue;
-
-      typedef std::map<DicomTag, DicomValue*>  Content;
-
-      Content  content_;
-
-    public:
-      ~DicomTagsAtLevel();
-
-      void AddNullValue(uint16_t group,
-                        uint16_t element);
-
-      void AddStringValue(uint16_t group,
-                          uint16_t element,
-                          const std::string& value);
-
-      void Fill(DicomMap& target) const;
-    };
-
-
     class ChildrenAtLevel : public boost::noncopyable
     {
     private:
@@ -83,13 +60,14 @@
     class Resource : public boost::noncopyable
     {
     private:
+      class DicomValue;
+
+      typedef std::map<DicomTag, DicomValue*>  MainDicomTags;
+
       ResourceType                          level_;
       std::string                           identifier_;
       std::unique_ptr<std::string>          parentIdentifier_;
-      DicomTagsAtLevel                      patientTags_;
-      DicomTagsAtLevel                      studyTags_;
-      DicomTagsAtLevel                      seriesTags_;
-      DicomTagsAtLevel                      instanceTags_;
+      MainDicomTags                         mainDicomTags_;
       ChildrenAtLevel                       childrenStudies_;
       ChildrenAtLevel                       childrenSeries_;
       ChildrenAtLevel                       childrenInstances_;
@@ -97,18 +75,18 @@
       std::map<MetadataType, std::string>   metadata_;
       std::map<FileContentType, FileInfo>   attachments_;
 
-      DicomTagsAtLevel& GetDicomTagsAtLevel(ResourceType level);
-
       ChildrenAtLevel& GetChildrenAtLevel(ResourceType level);
 
     public:
-      explicit Resource(ResourceType level,
-                        const std::string& identifier) :
+      Resource(ResourceType level,
+               const std::string& identifier) :
         level_(level),
         identifier_(identifier)
       {
       }
 
+      ~Resource();
+
       ResourceType GetLevel() const
       {
         return level_;
@@ -125,29 +103,16 @@
 
       bool HasParentIdentifier() const;
 
-      void AddStringDicomTag(ResourceType level,
-                             uint16_t group,
+      void AddStringDicomTag(uint16_t group,
                              uint16_t element,
-                             const std::string& value)
-      {
-        GetDicomTagsAtLevel(level).AddStringValue(group, element, value);
-      }
+                             const std::string& value);
 
       // The "Null" value could be used in the future to indicate a
       // value that is not available, typically a new "ExtraMainDicomTag"
-      void AddNullDicomTag(ResourceType level,
-                           uint16_t group,
-                           uint16_t element,
-                           const std::string& value)
-      {
-        GetDicomTagsAtLevel(level).AddNullValue(group, element);
-      }
+      void AddNullDicomTag(uint16_t group,
+                           uint16_t element);
 
-      void GetDicomTagsAtLevel(DicomMap& target,
-                               ResourceType level) const
-      {
-        const_cast<Resource&>(*this).GetDicomTagsAtLevel(level).Fill(target);
-      }
+      void GetMainDicomTags(DicomMap& target) const;
 
       void AddChildIdentifier(ResourceType level,
                               const std::string& childId)
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Fri May 03 21:26:06 2024 +0200
@@ -1188,7 +1188,7 @@
         }
 
         // request Each response content through INNER JOIN with the temporary table
-        if (request.IsRetrieveTagsAtLevel(request.GetLevel()))
+        if (request.IsRetrieveMainDicomTags())
         {
           // TODO-FIND: handle the case where we request tags from multiple levels
           SQLite::Statement statement(db_, SQLITE_FROM_HERE, 
@@ -1200,8 +1200,7 @@
           {
             const std::string& resourceId = statement.ColumnString(0);
             assert(response.HasResource(resourceId));
-            response.GetResource(resourceId).AddStringDicomTag(request.GetLevel(),
-                                                               statement.ColumnInt(1),
+            response.GetResource(resourceId).AddStringDicomTag(statement.ColumnInt(1),
                                                                statement.ColumnInt(2),
                                                                statement.ColumnString(3));
           }
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Fri May 03 21:26:06 2024 +0200
@@ -3877,9 +3877,9 @@
       throw OrthancException(ErrorCode_InternalError);
     }
 
-    if (request.IsRetrieveTagsAtLevel(request.GetLevel()))
+    if (request.IsRetrieveMainDicomTags())
     {
-      resource.GetDicomTagsAtLevel(tags_, request.GetLevel());
+      resource.GetMainDicomTags(tags_);
     }
 
     if (request.IsRetrieveChildrenIdentifiers())
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Fri May 03 21:26:06 2024 +0200
@@ -245,7 +245,7 @@
       if (expand)
       {
         // compatibility with default expand option
-        request.SetRetrieveTagsAtLevel(resourceType, true);
+        request.SetRetrieveMainDicomTags(true);
         request.SetRetrieveMetadata(true);
         request.SetRetrieveLabels(true);
 
@@ -267,11 +267,6 @@
         {
           request.SetRetrieveParentIdentifier(true);
         }
-
-        if (resourceType == ResourceType_Study)
-        {
-          request.SetRetrieveTagsAtLevel(ResourceType_Patient, true);
-        }
       }
 
       if (call.HasArgument("limit") ||
--- a/OrthancServer/Sources/ServerContext.cpp	Fri May 03 18:30:29 2024 +0200
+++ b/OrthancServer/Sources/ServerContext.cpp	Fri May 03 21:26:06 2024 +0200
@@ -2736,7 +2736,7 @@
     {
       expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeAllMetadata | ExpandResourceFlags_IncludeMetadata );
     }
-    if (request.IsRetrieveTagsAtLevel(request.GetLevel()))
+    if (request.IsRetrieveMainDicomTags())
     {
       expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeMainDicomTags);
     }