# HG changeset patch # User Sebastien Jodogne # Date 1715259557 -7200 # Node ID 8905ffa45fc24a729d601d205ca87a1be40d8e6e # Parent 1e92fb051fd798aa474e86370fbd534ba9469dab started listing of children resources diff -r 1e92fb051fd7 -r 8905ffa45fc2 OrthancServer/Sources/Database/Compatibility/GenericFind.cpp --- 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& target, + IDatabaseWrapper::ITransaction& transaction, + const std::list& resources) + { + target.clear(); + + for (std::list::const_iterator it = resources.begin(); it != resources.end(); ++it) + { + std::list tmp; + transaction.GetChildrenInternalId(tmp, *it); + target.splice(target.begin(), tmp); + } + } + + static void GetChildren(std::list& target, + IDatabaseWrapper::ITransaction& transaction, + const std::list& resources) + { + target.clear(); + + for (std::list::const_iterator it = resources.begin(); it != resources.end(); ++it) + { + std::list tmp; + transaction.GetChildrenPublicId(tmp, *it); + target.splice(target.begin(), tmp); + } + } + + static void GetChildrenIdentifiers(std::list& children, + IDatabaseWrapper::ITransaction& transaction, + const OrthancIdentifiers& identifiers, + ResourceType topLevel, + ResourceType bottomLevel) + { + if (!IsResourceLevelAboveOrEqual(topLevel, bottomLevel) || + topLevel == bottomLevel) + { + throw OrthancException(ErrorCode_InternalError); + } + + std::list 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 nextResources; + GetChildren(nextResources, transaction, currentResources); + currentResources.swap(nextResources); + } + + currentLevel = nextLevel; + } + } + void GenericFind::ExecuteFind(std::list& 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 diff -r 1e92fb051fd7 -r 8905ffa45fc2 OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- 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 requestedTags; OrthancRestApi::GetRequestedTags(requestedTags, call); - std::list a, b, c; - a.push_back(call.GetUriComponent("id", "")); - - ResourceType type = start; - while (type != end) + if (false) { - b.clear(); - - for (std::list::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 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::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 */); } diff -r 1e92fb051fd7 -r 8905ffa45fc2 OrthancServer/Sources/ResourceFinder.cpp --- 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)) { diff -r 1e92fb051fd7 -r 8905ffa45fc2 OrthancServer/Sources/ResourceFinder.h --- 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 requestedPatientTags_; std::set 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) {