Mercurial > hg > orthanc
changeset 5666:aa231c18b9d2 find-refactoring
adding computed tags
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 04 Jul 2024 18:31:54 +0200 |
parents | d8c86698110c |
children | 93dff1fccf36 |
files | OrthancServer/Sources/Database/Compatibility/GenericFind.cpp OrthancServer/Sources/Database/FindRequest.h OrthancServer/Sources/Database/FindResponse.cpp OrthancServer/Sources/Database/FindResponse.h OrthancServer/Sources/ResourceFinder.cpp OrthancServer/Sources/ResourceFinder.h |
diffstat | 6 files changed, 197 insertions(+), 120 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp Thu Jul 04 14:36:24 2024 +0200 +++ b/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp Thu Jul 04 18:31:54 2024 +0200 @@ -411,16 +411,20 @@ } } - if (request.GetLevel() != ResourceType_Instance && - request.GetChildrenRetrieveSpecification(GetChildResourceType(request.GetLevel())).IsRetrieveIdentifiers()) + if (request.GetLevel() != ResourceType_Instance) { // TODO-FIND: Retrieve other levels than immediate children - std::list<std::string> children; - transaction_.GetChildrenPublicId(children, internalId); + const ResourceType childLevel = GetChildResourceType(request.GetLevel()); - for (std::list<std::string>::const_iterator it = children.begin(); it != children.end(); ++it) + if (request.GetChildrenRetrieveSpecification(childLevel).IsRetrieveIdentifiers()) { - resource->AddChildIdentifier(*it); + std::list<std::string> children; + transaction_.GetChildrenPublicId(children, internalId); + + for (std::list<std::string>::const_iterator it = children.begin(); it != children.end(); ++it) + { + resource->AddChildIdentifier(childLevel, *it); + } } } @@ -432,7 +436,8 @@ resource->AddChildrenMetadata(*it, values); } - if (request.IsRetrieveOneInstanceIdentifier()) + if (request.IsRetrieveOneInstanceIdentifier() && + !request.GetChildrenRetrieveSpecification(ResourceType_Instance).IsRetrieveIdentifiers()) { int64_t currentId = internalId; ResourceType currentLevel = level; @@ -452,7 +457,7 @@ } } - resource->SetOneInstanceIdentifier(transaction_.GetPublicId(currentId)); + resource->AddChildIdentifier(ResourceType_Instance, transaction_.GetPublicId(currentId)); } response.Add(resource.release());
--- a/OrthancServer/Sources/Database/FindRequest.h Thu Jul 04 14:36:24 2024 +0200 +++ b/OrthancServer/Sources/Database/FindRequest.h Thu Jul 04 18:31:54 2024 +0200 @@ -407,7 +407,8 @@ bool IsRetrieveOneInstanceIdentifier() const { - return retrieveOneInstanceIdentifier_; + return (retrieveOneInstanceIdentifier_ || + GetChildrenRetrieveSpecification(ResourceType_Instance).IsRetrieveIdentifiers()); } }; }
--- a/OrthancServer/Sources/Database/FindResponse.cpp Thu Jul 04 14:36:24 2024 +0200 +++ b/OrthancServer/Sources/Database/FindResponse.cpp Thu Jul 04 18:31:54 2024 +0200 @@ -142,11 +142,57 @@ } - void FindResponse::Resource::AddChildIdentifier(const std::string& identifier) + std::set<std::string>& FindResponse::Resource::GetChildrenIdentifiers(ResourceType level) { - if (childrenIdentifiers_.find(identifier) == childrenIdentifiers_.end()) + switch (level) { - childrenIdentifiers_.insert(identifier); + case ResourceType_Study: + if (level_ == ResourceType_Patient) + { + return childrenStudiesIdentifiers_; + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + case ResourceType_Series: + if (level_ == ResourceType_Patient || + level_ == ResourceType_Study) + { + return childrenSeriesIdentifiers_; + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + case ResourceType_Instance: + if (level_ == ResourceType_Patient || + level_ == ResourceType_Study || + level_ == ResourceType_Series) + { + return childrenInstancesIdentifiers_; + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + void FindResponse::Resource::AddChildIdentifier(ResourceType level, + const std::string& identifier) + { + std::set<std::string>& target = GetChildrenIdentifiers(level); + + if (target.find(identifier) == target.end()) + { + target.insert(identifier); } else { @@ -375,49 +421,17 @@ } - void FindResponse::Resource::SetOneInstanceIdentifier(const std::string& id) + const std::string& FindResponse::Resource::GetOneInstanceIdentifier() const { - if (level_ == ResourceType_Instance) + const std::set<std::string>& instances = GetChildrenIdentifiers(ResourceType_Instance); + + if (instances.size() == 0) { - throw OrthancException(ErrorCode_BadParameterType); - } - else if (HasOneInstanceIdentifier()) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); + throw OrthancException(ErrorCode_BadSequenceOfCalls); // HasOneInstanceIdentifier() should have been called } else { - oneInstanceIdentifier_.reset(new std::string(id)); - } - } - - - const std::string& FindResponse::Resource::GetOneInstanceIdentifier() const - { - if (level_ == ResourceType_Instance) - { - throw OrthancException(ErrorCode_BadParameterType); - } - else if (HasOneInstanceIdentifier()) - { - return *oneInstanceIdentifier_; - } - else - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - } - - - bool FindResponse::Resource::HasOneInstanceIdentifier() const - { - if (level_ == ResourceType_Instance) - { - throw OrthancException(ErrorCode_BadParameterType); - } - else - { - return oneInstanceIdentifier_.get() != NULL; + return *instances.begin(); } } @@ -523,9 +537,10 @@ } else { + const std::set<std::string>& ids = GetChildrenIdentifiers(levels[i]); + Json::Value v = Json::arrayValue; - for (std::set<std::string>::const_iterator it = childrenIdentifiers_.begin(); - it != childrenIdentifiers_.end(); ++it) + for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); ++it) { v.append(*it); }
--- a/OrthancServer/Sources/Database/FindResponse.h Thu Jul 04 14:36:24 2024 +0200 +++ b/OrthancServer/Sources/Database/FindResponse.h Thu Jul 04 18:31:54 2024 +0200 @@ -85,11 +85,12 @@ std::map<MetadataType, std::string> metadataStudy_; std::map<MetadataType, std::string> metadataSeries_; std::map<MetadataType, std::string> metadataInstance_; - std::set<std::string> childrenIdentifiers_; - std::set<std::string> labels_; + std::set<std::string> childrenStudiesIdentifiers_; + std::set<std::string> childrenSeriesIdentifiers_; + std::set<std::string> childrenInstancesIdentifiers_; + std::set<std::string> labels_; std::map<FileContentType, FileInfo> attachments_; ChildrenMetadata childrenMetadata_; - std::unique_ptr<std::string> oneInstanceIdentifier_; MainDicomTagsAtLevel& GetMainDicomTagsAtLevel(ResourceType level); @@ -98,6 +99,8 @@ return const_cast<Resource&>(*this).GetMainDicomTagsAtLevel(level); } + std::set<std::string>& GetChildrenIdentifiers(ResourceType level); + public: Resource(ResourceType level, int64_t internalId, @@ -167,11 +170,12 @@ ResourceType level, MetadataType metadata) const; - void AddChildIdentifier(const std::string& childId); + void AddChildIdentifier(ResourceType level, + const std::string& childId); - const std::set<std::string>& GetChildrenIdentifiers() const + const std::set<std::string>& GetChildrenIdentifiers(ResourceType level) const { - return childrenIdentifiers_; + return const_cast<Resource&>(*this).GetChildrenIdentifiers(level); } void AddLabel(const std::string& label); @@ -204,9 +208,10 @@ const std::string& GetOneInstanceIdentifier() const; - void SetOneInstanceIdentifier(const std::string& id); - - bool HasOneInstanceIdentifier() const; + bool HasOneInstanceIdentifier() const + { + return !GetChildrenIdentifiers(ResourceType_Instance).empty(); + } void DebugExport(Json::Value& target, const FindRequest& request) const;
--- a/OrthancServer/Sources/ResourceFinder.cpp Thu Jul 04 14:36:24 2024 +0200 +++ b/OrthancServer/Sources/ResourceFinder.cpp Thu Jul 04 18:31:54 2024 +0200 @@ -35,6 +35,65 @@ namespace Orthanc { + void ResourceFinder::ConfigureChildrenCountComputedTag(DicomTag tag, + ResourceType parentLevel, + ResourceType childLevel) + { + if (request_.GetLevel() == parentLevel) + { + requestedComputedTags_.insert(tag); + hasRequestedTags_ = true; + request_.GetChildrenRetrieveSpecification(childLevel).SetRetrieveCount(true); + } + } + + + void ResourceFinder::InjectChildrenCountComputedTag(DicomMap& requestedTags, + DicomTag tag, + const FindResponse::Resource& resource, + ResourceType level) const + { + if (IsRequestedComputedTag(tag)) + { + const std::set<std::string>& children = resource.GetChildrenIdentifiers(level); + requestedTags.SetValue(tag, boost::lexical_cast<std::string>(children.size()), false); + } + } + + + void ResourceFinder::InjectComputedTags(DicomMap& requestedTags, + const FindResponse::Resource& resource) const + { + switch (resource.GetLevel()) + { + case ResourceType_Patient: + InjectChildrenCountComputedTag(requestedTags, DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES, resource, ResourceType_Study); + InjectChildrenCountComputedTag(requestedTags, DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES, resource, ResourceType_Series); + InjectChildrenCountComputedTag(requestedTags, DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES, resource, ResourceType_Instance); + break; + + case ResourceType_Study: + InjectChildrenCountComputedTag(requestedTags, DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES, resource, ResourceType_Series); + InjectChildrenCountComputedTag(requestedTags, DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES, resource, ResourceType_Instance); + break; + + case ResourceType_Series: + InjectChildrenCountComputedTag(requestedTags, DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES, resource, ResourceType_Instance); + break; + + case ResourceType_Instance: + if (IsRequestedComputedTag(DICOM_TAG_INSTANCE_AVAILABILITY)) + { + requestedTags.SetValue(DICOM_TAG_INSTANCE_AVAILABILITY, "ONLINE", false); + } + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + } + + SeriesStatus ResourceFinder::GetSeriesStatus(uint32_t& expectedNumberOfInstances, const FindResponse::Resource& resource) const { @@ -95,34 +154,6 @@ } - static void InjectRequestedTags(DicomMap& requestedTags, - std::set<DicomTag>& missingTags /* out */, - const FindResponse::Resource& resource, - ResourceType level, - const std::set<DicomTag>& tags) - { - if (!tags.empty()) - { - DicomMap m; - resource.GetMainDicomTags(m, level); - - for (std::set<DicomTag>::const_iterator it = tags.begin(); it != tags.end(); ++it) - { - std::string value; - if (m.LookupStringValue(value, *it, false /* not binary */)) - { - requestedTags.SetValue(*it, value, false /* not binary */); - } - else - { - // This is the case where the Housekeeper should be run - missingTags.insert(*it); - } - } - } - } - - void ResourceFinder::Expand(Json::Value& target, const FindResponse::Resource& resource, ServerIndex& index) const @@ -165,7 +196,7 @@ if (resource.GetLevel() != ResourceType_Instance) { - const std::set<std::string>& children = resource.GetChildrenIdentifiers(); + const std::set<std::string>& children = resource.GetChildrenIdentifiers(GetChildResourceType(resource.GetLevel())); Json::Value c = Json::arrayValue; for (std::set<std::string>::const_iterator @@ -482,20 +513,35 @@ hasRequestedTags_ = true; } + else if (tag == DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES) + { + ConfigureChildrenCountComputedTag(tag, ResourceType_Patient, ResourceType_Study); + } + else if (tag == DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES) + { + ConfigureChildrenCountComputedTag(tag, ResourceType_Patient, ResourceType_Series); + } + else if (tag == DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES) + { + ConfigureChildrenCountComputedTag(tag, ResourceType_Patient, ResourceType_Instance); + } + else if (tag == DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES) + { + ConfigureChildrenCountComputedTag(tag, ResourceType_Study, ResourceType_Series); + } + else if (tag == DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES) + { + ConfigureChildrenCountComputedTag(tag, ResourceType_Study, ResourceType_Instance); + } + else if (tag == DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES) + { + ConfigureChildrenCountComputedTag(tag, ResourceType_Series, ResourceType_Instance); + } else if (tag == DICOM_TAG_INSTANCE_AVAILABILITY) { requestedComputedTags_.insert(tag); hasRequestedTags_ = true; } - else if (tag == DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES) - { - if (request_.GetLevel() == ResourceType_Series) - { - requestedComputedTags_.insert(tag); - hasRequestedTags_ = true; - request_.GetChildrenRetrieveSpecification(ResourceType_Instance).SetRetrieveCount(true); - } - } else { // This is neither a main DICOM tag, nor a computed DICOM tag: @@ -521,34 +567,30 @@ } - void ResourceFinder::InjectComputedTags(DicomMap& requestedTags, - const FindResponse::Resource& resource) const + static void InjectRequestedTags(DicomMap& requestedTags, + std::set<DicomTag>& missingTags /* out */, + const FindResponse::Resource& resource, + ResourceType level, + const std::set<DicomTag>& tags) { - switch (resource.GetLevel()) + if (!tags.empty()) { - case ResourceType_Patient: - break; + DicomMap m; + resource.GetMainDicomTags(m, level); - case ResourceType_Study: - break; - - case ResourceType_Series: - if (IsRequestedComputedTag(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES)) + for (std::set<DicomTag>::const_iterator it = tags.begin(); it != tags.end(); ++it) + { + std::string value; + if (m.LookupStringValue(value, *it, false /* not binary */)) { - requestedTags.SetValue(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES, - boost::lexical_cast<std::string>(resource.GetChildrenIdentifiers().size()), false); + requestedTags.SetValue(*it, value, false /* not binary */); } - break; - - case ResourceType_Instance: - if (IsRequestedComputedTag(DICOM_TAG_INSTANCE_AVAILABILITY)) + else { - requestedTags.SetValue(DICOM_TAG_INSTANCE_AVAILABILITY, "ONLINE", false); + // This is the case where the Housekeeper should be run + missingTags.insert(*it); } - break; - - default: - throw OrthancException(ErrorCode_InternalError); + } } }
--- a/OrthancServer/Sources/ResourceFinder.h Thu Jul 04 14:36:24 2024 +0200 +++ b/OrthancServer/Sources/ResourceFinder.h Thu Jul 04 18:31:54 2024 +0200 @@ -52,6 +52,15 @@ return requestedComputedTags_.find(tag) != requestedComputedTags_.end(); } + void ConfigureChildrenCountComputedTag(DicomTag tag, + ResourceType parentLevel, + ResourceType childLevel); + + void InjectChildrenCountComputedTag(DicomMap& requestedTags, + DicomTag tag, + const FindResponse::Resource& resource, + ResourceType level) const; + SeriesStatus GetSeriesStatus(uint32_t& expectedNumberOfInstances, const FindResponse::Resource& resource) const;