# HG changeset patch # User Alain Mazy # Date 1647260009 -3600 # Node ID 3f9b9865c8cc9dde2a461d883f65f15dee8a17c1 # Parent 8422e4f99a18979bedb8e4d6a0c2f983381fb9b8 include requested tags from storage if needed diff -r 8422e4f99a18 -r 3f9b9865c8cc OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri Mar 11 17:38:16 2022 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Mon Mar 14 13:13:29 2022 +0100 @@ -44,7 +44,7 @@ // This "include" is mandatory for Release builds using Linux Standard Base #include - +#include /** * This semaphore is used to limit the number of concurrent HTTP @@ -128,6 +128,9 @@ static void AnswerListOfResources(RestApiOutput& output, ServerContext& context, const std::list& resources, + const std::map& instancesIds, // optional: the id of an instance for each found resource. + const std::map >& resourcesMainDicomTags, // optional: all tags read from DB for a resource (current level and upper levels) + const std::map& resourcesDicomAsJson, // optional: the dicom-as-json for each resource ResourceType level, bool expand, DicomToJsonFormat format, @@ -156,6 +159,22 @@ } + static void AnswerListOfResources(RestApiOutput& output, + ServerContext& context, + const std::list& resources, + ResourceType level, + bool expand, + DicomToJsonFormat format, + const std::set& requestedTags) + { + std::map unusedInstancesIds; + std::map > unusedResourcesMainDicomTags; + std::map unusedResourcesDicomAsJson; + + AnswerListOfResources(output, context, resources, unusedInstancesIds, unusedResourcesMainDicomTags, unusedResourcesDicomAsJson, level, expand, format, requestedTags); + } + + template static void ListResources(RestApiGetCall& call) { @@ -2828,6 +2847,12 @@ private: bool isComplete_; std::list resources_; + + // cache the data we used during lookup and that we could reuse when building the answers + std::map instancesIds_; // the id of an instance for each found resource. + std::map > resourcesMainDicomTags_; // all tags read from DB for a resource (current level and upper levels) + std::map resourcesDicomAsJson_; // the dicom-as-json for a resource + DicomToJsonFormat format_; public: @@ -2848,11 +2873,14 @@ } virtual void Visit(const std::string& publicId, - const std::string& instanceId /* unused */, - const DicomMap& mainDicomTags /* unused */, - const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE + const std::string& instanceId, + const DicomMap& mainDicomTags, + const Json::Value* dicomAsJson) ORTHANC_OVERRIDE { resources_.push_back(publicId); + instancesIds_[publicId] = instanceId; + resourcesMainDicomTags_[publicId].reset(mainDicomTags.Clone()); + resourcesDicomAsJson_[publicId] = dicomAsJson; } void Answer(RestApiOutput& output, diff -r 8422e4f99a18 -r 3f9b9865c8cc OrthancServer/Sources/ServerContext.cpp --- a/OrthancServer/Sources/ServerContext.cpp Fri Mar 11 17:38:16 2022 +0100 +++ b/OrthancServer/Sources/ServerContext.cpp Mon Mar 14 13:13:29 2022 +0100 @@ -1396,6 +1396,7 @@ bool hasOnlyMainDicomTags; DicomMap dicom; + DicomMap allMainDicomTagsFromDB; if (findStorageAccessMode_ == FindStorageAccessMode_DatabaseOnly || findStorageAccessMode_ == FindStorageAccessMode_DiskOnAnswer || @@ -1404,8 +1405,7 @@ // Case (1): The main DICOM tags, as stored in the database, // are sufficient to look for match - DicomMap tmp; - if (!GetIndex().GetAllMainDicomTags(tmp, instances[i])) + if (!GetIndex().GetAllMainDicomTags(allMainDicomTagsFromDB, instances[i])) // MORE_TAGS: TODO: we could read only the current and upper level to reduce the number of SQL queries { // The instance has been removed during the execution of the // lookup, ignore it @@ -1418,16 +1418,16 @@ { // WARNING: Don't reorder cases below, and don't add "break" case ResourceType_Instance: - dicom.MergeMainDicomTags(tmp, ResourceType_Instance); + dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Instance); case ResourceType_Series: - dicom.MergeMainDicomTags(tmp, ResourceType_Series); + dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Series); case ResourceType_Study: - dicom.MergeMainDicomTags(tmp, ResourceType_Study); + dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Study); case ResourceType_Patient: - dicom.MergeMainDicomTags(tmp, ResourceType_Patient); + dicom.MergeMainDicomTags(allMainDicomTagsFromDB, ResourceType_Patient); break; default: @@ -1476,7 +1476,7 @@ if (hasOnlyMainDicomTags) { // This is Case (1): The variable "dicom" only contains the main DICOM tags - visitor.Visit(resources[i], instances[i], dicom, dicomAsJson.get()); + visitor.Visit(resources[i], instances[i], allMainDicomTagsFromDB, dicomAsJson.get()); } else { @@ -2262,12 +2262,25 @@ DicomToJsonFormat format, const std::set& requestedTags) { + std::string unusedInstanceId; + Json::Value unusedValue; + + return ExpandResource(target, publicId, unusedInstanceId, unusedValue, level, format, requestedTags); + } + + bool ServerContext::ExpandResource(Json::Value& target, + const std::string& publicId, + const std::string& instanceId, // optional: the id of an instance for the resource + const Json::Value& dicomAsJson, // optional: the dicom-as-json for the resource + ResourceType level, + DicomToJsonFormat format, + const std::set& requestedTags) + { ExpandedResource resource; if (GetIndex().ExpandResource(resource, publicId, level, format, requestedTags)) { // check the main dicom tags list has not changed since the resource was stored - if (resource.mainDicomTagsSignature_ != DicomMap::GetMainDicomTagsSignature(resource.type_)) { OrthancConfiguration::ReaderLock lock; @@ -2277,9 +2290,40 @@ } } - // MORE_TAGS: TODO: possibly merge missing requested tags from /tags - // log warning - // use resource.missingRequestedTags_ + // possibly merge missing requested tags from dicom-as-json + if (!resource.missingRequestedTags_.empty()) + { + std::string instanceId_ = instanceId; + Json::Value dicomAsJson_ = dicomAsJson; + if (dicomAsJson_.isNull()) + { + if (instanceId_.empty()) + { + if (level == ResourceType_Instance) + { + instanceId_ = publicId; + } + else + { + std::list instancesIds; + GetIndex().GetChildInstances(instancesIds, publicId); + if (instancesIds.size() < 1) + { + throw OrthancException(ErrorCode_InternalError, "ExpandResource: no instances found"); + } + instanceId_ = instancesIds.front(); + } + } + + // MORE_TAGS :TODO: log warning (add an option to disable them) + ReadDicomAsJson(dicomAsJson_, instanceId_); + } + + DicomMap allTags; + allTags.FromDicomAsJson(dicomAsJson_); + + resource.tags_.Merge(allTags); + } SerializeExpandedResource(target, resource, format, requestedTags); diff -r 8422e4f99a18 -r 3f9b9865c8cc OrthancServer/Sources/ServerContext.h --- a/OrthancServer/Sources/ServerContext.h Fri Mar 11 17:38:16 2022 +0100 +++ b/OrthancServer/Sources/ServerContext.h Mon Mar 14 13:13:29 2022 +0100 @@ -546,5 +546,13 @@ DicomToJsonFormat format, const std::set& requestedTags); + bool ExpandResource(Json::Value& target, + const std::string& publicId, + const std::string& instanceId, // optional: the id of an instance for the resource + const Json::Value& dicomAsJson, // optional: the dicom-as-json for the resource + ResourceType level, + DicomToJsonFormat format, + const std::set& requestedTags); + }; }