changeset 5617:8905ffa45fc2 find-refactoring

started listing of children resources
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 09 May 2024 14:59:17 +0200
parents 1e92fb051fd7
children 824a5fb0774e
files OrthancServer/Sources/Database/Compatibility/GenericFind.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp OrthancServer/Sources/ResourceFinder.cpp OrthancServer/Sources/ResourceFinder.h
diffstat 4 files changed, 167 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp	Thu May 09 13:02:51 2024 +0200
+++ b/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp	Thu May 09 14:59:17 2024 +0200
@@ -40,6 +40,78 @@
               request.GetOrdering().empty());
     }
 
+    static void GetChildren(std::list<int64_t>& target,
+                            IDatabaseWrapper::ITransaction& transaction,
+                            const std::list<int64_t>& resources)
+    {
+      target.clear();
+
+      for (std::list<int64_t>::const_iterator it = resources.begin(); it != resources.end(); ++it)
+      {
+        std::list<int64_t> tmp;
+        transaction.GetChildrenInternalId(tmp, *it);
+        target.splice(target.begin(), tmp);
+      }
+    }
+
+    static void GetChildren(std::list<std::string>& target,
+                            IDatabaseWrapper::ITransaction& transaction,
+                            const std::list<int64_t>& resources)
+    {
+      target.clear();
+
+      for (std::list<int64_t>::const_iterator it = resources.begin(); it != resources.end(); ++it)
+      {
+        std::list<std::string> tmp;
+        transaction.GetChildrenPublicId(tmp, *it);
+        target.splice(target.begin(), tmp);
+      }
+    }
+
+    static void GetChildrenIdentifiers(std::list<std::string>& children,
+                                       IDatabaseWrapper::ITransaction& transaction,
+                                       const OrthancIdentifiers& identifiers,
+                                       ResourceType topLevel,
+                                       ResourceType bottomLevel)
+    {
+      if (!IsResourceLevelAboveOrEqual(topLevel, bottomLevel) ||
+          topLevel == bottomLevel)
+      {
+        throw OrthancException(ErrorCode_InternalError);
+      }
+
+      std::list<int64_t> currentResources;
+      ResourceType currentLevel;
+
+      {
+        int64_t id;
+        if (!transaction.LookupResource(id, currentLevel, identifiers.GetLevel(topLevel)) ||
+            currentLevel != topLevel)
+        {
+          throw OrthancException(ErrorCode_InexistentItem);
+        }
+
+        currentResources.push_back(id);
+      }
+
+      while (currentLevel != bottomLevel)
+      {
+        ResourceType nextLevel = GetChildResourceType(currentLevel);
+        if (nextLevel == bottomLevel)
+        {
+          GetChildren(children, transaction, currentResources);
+        }
+        else
+        {
+          std::list<int64_t> nextResources;
+          GetChildren(nextResources, transaction, currentResources);
+          currentResources.swap(nextResources);
+        }
+
+        currentLevel = nextLevel;
+      }
+    }
+
     void GenericFind::ExecuteFind(std::list<std::string>& identifiers,
                                   const FindRequest& request)
     {
@@ -65,6 +137,7 @@
                !request.GetOrthancIdentifiers().HasSeriesId() &&
                !request.GetOrthancIdentifiers().HasInstanceId())
       {
+        // TODO-FIND: This is a trivial case for which no transaction is needed
         identifiers.push_back(request.GetOrthancIdentifiers().GetPatientId());
       }
       else if (IsRequestWithoutContraint(request) &&
@@ -74,6 +147,7 @@
                !request.GetOrthancIdentifiers().HasSeriesId() &&
                !request.GetOrthancIdentifiers().HasInstanceId())
       {
+        // TODO-FIND: This is a trivial case for which no transaction is needed
         identifiers.push_back(request.GetOrthancIdentifiers().GetStudyId());
       }
       else if (IsRequestWithoutContraint(request) &&
@@ -83,6 +157,7 @@
                request.GetOrthancIdentifiers().HasSeriesId() &&
                !request.GetOrthancIdentifiers().HasInstanceId())
       {
+        // TODO-FIND: This is a trivial case for which no transaction is needed
         identifiers.push_back(request.GetOrthancIdentifiers().GetSeriesId());
       }
       else if (IsRequestWithoutContraint(request) &&
@@ -92,8 +167,39 @@
                !request.GetOrthancIdentifiers().HasSeriesId() &&
                request.GetOrthancIdentifiers().HasInstanceId())
       {
+        // TODO-FIND: This is a trivial case for which no transaction is needed
         identifiers.push_back(request.GetOrthancIdentifiers().GetInstanceId());
       }
+      else if (IsRequestWithoutContraint(request) &&
+               (request.GetLevel() == ResourceType_Study ||
+                request.GetLevel() == ResourceType_Series ||
+                request.GetLevel() == ResourceType_Instance) &&
+               request.GetOrthancIdentifiers().HasPatientId() &&
+               !request.GetOrthancIdentifiers().HasStudyId() &&
+               !request.GetOrthancIdentifiers().HasSeriesId() &&
+               !request.GetOrthancIdentifiers().HasInstanceId())
+      {
+        GetChildrenIdentifiers(identifiers, transaction_, request.GetOrthancIdentifiers(), ResourceType_Patient, request.GetLevel());
+      }
+      else if (IsRequestWithoutContraint(request) &&
+               (request.GetLevel() == ResourceType_Series ||
+                request.GetLevel() == ResourceType_Instance) &&
+               !request.GetOrthancIdentifiers().HasPatientId() &&
+               request.GetOrthancIdentifiers().HasStudyId() &&
+               !request.GetOrthancIdentifiers().HasSeriesId() &&
+               !request.GetOrthancIdentifiers().HasInstanceId())
+      {
+        GetChildrenIdentifiers(identifiers, transaction_, request.GetOrthancIdentifiers(), ResourceType_Study, request.GetLevel());
+      }
+      else if (IsRequestWithoutContraint(request) &&
+               request.GetLevel() == ResourceType_Instance &&
+               !request.GetOrthancIdentifiers().HasPatientId() &&
+               !request.GetOrthancIdentifiers().HasStudyId() &&
+               request.GetOrthancIdentifiers().HasSeriesId() &&
+               !request.GetOrthancIdentifiers().HasInstanceId())
+      {
+        GetChildrenIdentifiers(identifiers, transaction_, request.GetOrthancIdentifiers(), ResourceType_Series, request.GetLevel());
+      }
       else
       {
         throw OrthancException(ErrorCode_NotImplemented);  // Not supported
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Thu May 09 13:02:51 2024 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Thu May 09 14:59:17 2024 +0200
@@ -3440,34 +3440,57 @@
     ServerIndex& index = OrthancRestApi::GetIndex(call);
     ServerContext& context = OrthancRestApi::GetContext(call);
 
+    const bool expand = (!call.HasArgument("expand") ||
+                         // this "expand" is the only one to have a false default value to keep backward compatibility
+                         call.GetBooleanArgument("expand", false));
+    const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
+
     std::set<DicomTag> requestedTags;
     OrthancRestApi::GetRequestedTags(requestedTags, call);
 
-    std::list<std::string> a, b, c;
-    a.push_back(call.GetUriComponent("id", ""));
-
-    ResourceType type = start;
-    while (type != end)
+    if (false)
     {
-      b.clear();
-
-      for (std::list<std::string>::const_iterator
-             it = a.begin(); it != a.end(); ++it)
+      /**
+       * EXPERIMENTAL VERSION
+       **/
+
+      ResourceFinder finder(end, expand);
+      finder.SetOrthancId(start, call.GetUriComponent("id", ""));
+      finder.AddRequestedTags(requestedTags);
+      finder.SetFormat(format);
+
+      Json::Value answer;
+      finder.Execute(answer, context);
+      call.GetOutput().AnswerJson(answer);
+    }
+    else
+    {
+      /**
+       * VERSION IN ORTHANC <= 1.12.3
+       **/
+      std::list<std::string> a, b, c;
+      a.push_back(call.GetUriComponent("id", ""));
+
+      ResourceType type = start;
+      while (type != end)
       {
-        index.GetChildren(c, *it);
-        b.splice(b.begin(), c);
+        b.clear();
+
+        for (std::list<std::string>::const_iterator
+               it = a.begin(); it != a.end(); ++it)
+        {
+          index.GetChildren(c, *it);
+          b.splice(b.begin(), c);
+        }
+
+        type = GetChildResourceType(type);
+
+        a.clear();
+        a.splice(a.begin(), b);
       }
 
-      type = GetChildResourceType(type);
-
-      a.clear();
-      a.splice(a.begin(), b);
+      AnswerListOfResources2(call.GetOutput(), context, a, type, expand, format, requestedTags, true /* allowStorageAccess */);
     }
-
-    AnswerListOfResources2(call.GetOutput(), context, a, type, !call.HasArgument("expand") || call.GetBooleanArgument("expand", false),  // this "expand" is the only one to have a false default value to keep backward compatibility
-                          OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human),
-                          requestedTags,
-                          true /* allowStorageAccess */);
   }
 
 
--- a/OrthancServer/Sources/ResourceFinder.cpp	Thu May 09 13:02:51 2024 +0200
+++ b/OrthancServer/Sources/ResourceFinder.cpp	Thu May 09 14:59:17 2024 +0200
@@ -361,6 +361,7 @@
     request_(level),
     expand_(expand),
     format_(DicomToJsonFormat_Human),
+    allowStorageAccess_(true),
     hasRequestedTags_(false),
     includeAllMetadata_(false)
   {
@@ -503,6 +504,12 @@
 
         if (!missingTags.empty())
         {
+          if (!allowStorageAccess_)
+          {
+            throw OrthancException(ErrorCode_BadSequenceOfCalls,
+                                   "Cannot add missing requested tags, as access to file storage is disallowed");
+          }
+
           OrthancConfiguration::ReaderLock lock;
           if (lock.GetConfiguration().IsWarningEnabled(Warnings_001_TagsBeingReadFromStorage))
           {
--- a/OrthancServer/Sources/ResourceFinder.h	Thu May 09 13:02:51 2024 +0200
+++ b/OrthancServer/Sources/ResourceFinder.h	Thu May 09 14:59:17 2024 +0200
@@ -36,6 +36,7 @@
     FindRequest        request_;
     bool               expand_;
     DicomToJsonFormat  format_;
+    bool               allowStorageAccess_;
     bool               hasRequestedTags_;
     std::set<DicomTag> requestedPatientTags_;
     std::set<DicomTag> requestedStudyTags_;
@@ -55,6 +56,16 @@
     ResourceFinder(ResourceType level,
                    bool expand);
 
+    bool IsAllowStorageAccess() const
+    {
+      return allowStorageAccess_;
+    }
+
+    void SetAllowStorageAccess(bool allow)
+    {
+      allowStorageAccess_ = allow;
+    }
+
     void SetOrthancId(ResourceType level,
                       const std::string& id)
     {