Mercurial > hg > orthanc
diff OrthancServer/Sources/Database/FindResponse.cpp @ 5596:81a29ad7fb4b find-refactoring
added possibility to retrieve main DICOM tags and metadata at any level
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 07 May 2024 18:44:53 +0200 |
parents | a87f2a56257d |
children | 8796c100aaf8 |
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/FindResponse.cpp Tue May 07 12:53:12 2024 +0200 +++ b/OrthancServer/Sources/Database/FindResponse.cpp Tue May 07 18:44:53 2024 +0200 @@ -22,16 +22,17 @@ #include "FindResponse.h" -#include "../../../OrthancFramework/Sources/DicomFormat/DicomInstanceHasher.h" +#include "../../../OrthancFramework/Sources/DicomFormat/DicomArray.h" #include "../../../OrthancFramework/Sources/OrthancException.h" #include "../../../OrthancFramework/Sources/SerializationToolbox.h" +#include <boost/lexical_cast.hpp> #include <cassert> namespace Orthanc { - class FindResponse::Resource::DicomValue : public boost::noncopyable + class FindResponse::MainDicomTagsAtLevel::DicomValue : public boost::noncopyable { public: enum ValueType @@ -74,8 +75,18 @@ }; - void FindResponse::Resource::AddNullDicomTag(uint16_t group, - uint16_t element) + FindResponse::MainDicomTagsAtLevel::~MainDicomTagsAtLevel() + { + for (MainDicomTags::iterator it = mainDicomTags_.begin(); it != mainDicomTags_.end(); ++it) + { + assert(it->second != NULL); + delete it->second; + } + } + + + void FindResponse::MainDicomTagsAtLevel::AddNullDicomTag(uint16_t group, + uint16_t element) { const DicomTag tag(group, element); @@ -90,9 +101,9 @@ } - void FindResponse::Resource::AddStringDicomTag(uint16_t group, - uint16_t element, - const std::string& value) + void FindResponse::MainDicomTagsAtLevel::AddStringDicomTag(uint16_t group, + uint16_t element, + const std::string& value) { const DicomTag tag(group, element); @@ -107,7 +118,7 @@ } - void FindResponse::Resource::GetMainDicomTags(DicomMap& target) const + void FindResponse::MainDicomTagsAtLevel::Export(DicomMap& target) const { for (MainDicomTags::const_iterator it = mainDicomTags_.begin(); it != mainDicomTags_.end(); ++it) { @@ -130,11 +141,11 @@ } - void FindResponse::ChildrenAtLevel::AddIdentifier(const std::string& identifier) + void FindResponse::Resource::AddChildIdentifier(const std::string& identifier) { - if (identifiers_.find(identifier) == identifiers_.end()) + if (childrenIdentifiers_.find(identifier) == childrenIdentifiers_.end()) { - identifiers_.insert(identifier); + childrenIdentifiers_.insert(identifier); } else { @@ -143,42 +154,26 @@ } - FindResponse::ChildrenAtLevel& FindResponse::Resource::GetChildrenAtLevel(ResourceType level) + FindResponse::MainDicomTagsAtLevel& FindResponse::Resource::GetMainDicomTagsAtLevel(ResourceType level) { + if (!IsResourceLevelAboveOrEqual(level, level_)) + { + throw OrthancException(ErrorCode_BadParameterType); + } + switch (level) { + case ResourceType_Patient: + return mainDicomTagsPatient_; + case ResourceType_Study: - if (level_ == ResourceType_Patient) - { - return childrenStudies_; - } - else - { - throw OrthancException(ErrorCode_BadParameterType); - } + return mainDicomTagsStudy_; case ResourceType_Series: - if (level_ == ResourceType_Patient || - level_ == ResourceType_Study) - { - return childrenSeries_; - } - else - { - throw OrthancException(ErrorCode_BadParameterType); - } + return mainDicomTagsSeries_; case ResourceType_Instance: - if (level_ == ResourceType_Patient || - level_ == ResourceType_Study || - level_ == ResourceType_Series) - { - return childrenInstances_; - } - else - { - throw OrthancException(ErrorCode_BadParameterType); - } + return mainDicomTagsInstance_; default: throw OrthancException(ErrorCode_ParameterOutOfRange); @@ -186,26 +181,59 @@ } - void FindResponse::Resource::AddMetadata(MetadataType metadata, + void FindResponse::Resource::AddMetadata(ResourceType level, + MetadataType metadata, const std::string& value) { - if (metadata_.find(metadata) != metadata_.end()) + std::map<MetadataType, std::string>& m = GetMetadata(level); + + if (m.find(metadata) != m.end()) { throw OrthancException(ErrorCode_BadSequenceOfCalls); // Metadata already present } else { - metadata_[metadata] = value; + m[metadata] = value; + } + } + + + std::map<MetadataType, std::string>& FindResponse::Resource::GetMetadata(ResourceType level) + { + if (!IsResourceLevelAboveOrEqual(level, level_)) + { + throw OrthancException(ErrorCode_BadParameterType); + } + + switch (level) + { + case ResourceType_Patient: + return metadataPatient_; + + case ResourceType_Study: + return metadataStudy_; + + case ResourceType_Series: + return metadataSeries_; + + case ResourceType_Instance: + return metadataInstance_; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); } } bool FindResponse::Resource::LookupMetadata(std::string& value, + ResourceType level, MetadataType metadata) const { - std::map<MetadataType, std::string>::const_iterator found = metadata_.find(metadata); + const std::map<MetadataType, std::string>& m = GetMetadata(level); - if (found == metadata_.end()) + std::map<MetadataType, std::string>::const_iterator found = m.find(metadata); + + if (found == m.end()) { return false; } @@ -217,16 +245,6 @@ } - void FindResponse::Resource::ListMetadata(std::set<MetadataType>& target) const - { - target.clear(); - - for (std::map<MetadataType, std::string>::const_iterator it = metadata_.begin(); it != metadata_.end(); ++it) - { - target.insert(it->first); - } - } - const std::string& FindResponse::Resource::GetParentIdentifier() const { if (level_ == ResourceType_Patient) @@ -246,12 +264,6 @@ FindResponse::Resource::~Resource() { - for (MainDicomTags::iterator it = mainDicomTags_.begin(); it != mainDicomTags_.end(); ++it) - { - assert(it->second != NULL); - delete it->second; - } - for (ChildrenMetadata::iterator it = childrenMetadata_.begin(); it != childrenMetadata_.end(); ++it) { assert(it->second != NULL); @@ -362,6 +374,36 @@ } + void FindResponse::Resource::AddAttachmentOfOneInstance(const FileInfo& info) + { + if (attachmentOfOneInstance_.find(info.GetContentType()) == attachmentOfOneInstance_.end()) + { + attachmentOfOneInstance_[info.GetContentType()] = info; + } + else + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + } + + + bool FindResponse::Resource::LookupAttachmentOfOneInstance(FileInfo& target, + FileContentType type) const + { + std::map<FileContentType, FileInfo>::const_iterator found = attachmentOfOneInstance_.find(type); + + if (found == attachmentOfOneInstance_.end()) + { + return false; + } + else + { + target = found->second; + return true; + } + } + + SeriesStatus FindResponse::Resource::GetSeriesStatus(uint32_t& expectedNumberOfInstances) const { if (level_ != ResourceType_Series) @@ -370,7 +412,7 @@ } std::string s; - if (!LookupMetadata(s, MetadataType_Series_ExpectedNumberOfInstances) || + if (!LookupMetadata(s, ResourceType_Series, MetadataType_Series_ExpectedNumberOfInstances) || !SerializationToolbox::ParseUnsignedInteger32(expectedNumberOfInstances, s)) { return SeriesStatus_Unknown; @@ -422,7 +464,8 @@ void FindResponse::Resource::Expand(Json::Value& target, - const FindRequest& request) const + const FindRequest& request, + bool includeAllMetadata) const { /** @@ -444,35 +487,15 @@ **/ + /** + * This method closely follows "SerializeExpandedResource()" in + * "ServerContext.cpp" from Orthanc 1.12.3. + **/ + target = Json::objectValue; target["ID"] = identifier_; target["Type"] = GetResourceTypeText(level_, false, true); - if (request.IsRetrieveMetadata()) - { - Json::Value metadata = Json::objectValue; - - for (std::map<MetadataType, std::string>::const_iterator - it = metadata_.begin(); it != metadata_.end(); ++it) - { - metadata[EnumerationToString(it->first)] = it->second; - } - - target["Metadata"] = metadata; - } - - if (request.IsRetrieveLabels()) - { - Json::Value labels = Json::arrayValue; - - for (std::set<std::string>::const_iterator it = labels_.begin(); it != labels_.end(); ++it) - { - labels.append(*it); - } - - target["Labels"] = labels; - } - if (request.IsRetrieveParentIdentifier()) { switch (level_) @@ -499,10 +522,9 @@ if (request.IsRetrieveChildrenIdentifiers()) { - Json::Value c = Json::arrayValue; + const std::set<std::string>& children = GetChildrenIdentifiers(); - const std::set<std::string>& children = GetChildrenAtLevel(GetChildResourceType(level_)).GetIdentifiers(); - + Json::Value c = Json::arrayValue; for (std::set<std::string>::const_iterator it = children.begin(); it != children.end(); ++it) { @@ -527,6 +549,269 @@ throw OrthancException(ErrorCode_InternalError); } } + + if (request.IsRetrieveMetadata(level_)) + { + switch (level_) + { + case ResourceType_Patient: + case ResourceType_Study: + break; + + case ResourceType_Series: + { + uint32_t expectedNumberOfInstances; + SeriesStatus status = GetSeriesStatus(expectedNumberOfInstances); + + target["Status"] = EnumerationToString(status); + + if (status == SeriesStatus_Unknown) + { + target["ExpectedNumberOfInstances"] = Json::nullValue; + } + else + { + target["ExpectedNumberOfInstances"] = Json::nullValue; + } + + break; + } + + case ResourceType_Instance: + { + // TODO-FIND + break; + } + + default: + throw OrthancException(ErrorCode_InternalError); + } + } + + if (request.IsRetrieveLabels()) + { + Json::Value labels = Json::arrayValue; + + for (std::set<std::string>::const_iterator it = labels_.begin(); it != labels_.end(); ++it) + { + labels.append(*it); + } + + target["Labels"] = labels; + } + + if (request.IsRetrieveMetadata(level_) && + includeAllMetadata) + { + const std::map<MetadataType, std::string>& m = GetMetadata(level_); + + Json::Value metadata = Json::objectValue; + + for (std::map<MetadataType, std::string>::const_iterator it = m.begin(); it != m.end(); ++it) + { + metadata[EnumerationToString(it->first)] = it->second; + } + + target["Metadata"] = metadata; + } + } + + + static void DebugDicomMap(Json::Value& target, + const DicomMap& m) + { + DicomArray a(m); + for (size_t i = 0; i < a.GetSize(); i++) + { + if (a.GetElement(i).GetValue().IsNull()) + { + target[a.GetElement(i).GetTag().Format()] = Json::nullValue; + } + else if (a.GetElement(i).GetValue().IsString()) + { + target[a.GetElement(i).GetTag().Format()] = a.GetElement(i).GetValue().GetContent(); + } + else + { + throw OrthancException(ErrorCode_InternalError); + } + } + } + + + static void DebugMetadata(Json::Value& target, + const std::map<MetadataType, std::string>& m) + { + target = Json::objectValue; + + for (std::map<MetadataType, std::string>::const_iterator it = m.begin(); it != m.end(); ++it) + { + target[EnumerationToString(it->first)] = it->second; + } + } + + + static void DebugAddAttachment(Json::Value& target, + const FileInfo& info) + { + Json::Value u = Json::arrayValue; + u.append(info.GetUuid()); + u.append(info.GetUncompressedSize()); + target[EnumerationToString(info.GetContentType())] = u; + } + + void FindResponse::Resource::DebugExport(Json::Value& target, + const FindRequest& request) const + { + target = Json::objectValue; + + target["Level"] = EnumerationToString(GetLevel()); + target["ID"] = GetIdentifier(); + + if (request.IsRetrieveParentIdentifier()) + { + target["ParentID"] = GetParentIdentifier(); + } + + if (request.IsRetrieveMainDicomTags(ResourceType_Patient)) + { + DicomMap m; + GetMainDicomTags(m, ResourceType_Patient); + DebugDicomMap(target["Patient"]["MainDicomTags"], m); + } + + if (request.IsRetrieveMetadata(ResourceType_Patient)) + { + DebugMetadata(target["Patient"]["Metadata"], GetMetadata(ResourceType_Patient)); + } + + if (request.GetLevel() != ResourceType_Patient) + { + if (request.IsRetrieveMainDicomTags(ResourceType_Study)) + { + DicomMap m; + GetMainDicomTags(m, ResourceType_Study); + DebugDicomMap(target["Study"]["MainDicomTags"], m); + } + + if (request.IsRetrieveMetadata(ResourceType_Study)) + { + DebugMetadata(target["Study"]["Metadata"], GetMetadata(ResourceType_Study)); + } + } + + if (request.GetLevel() != ResourceType_Patient && + request.GetLevel() != ResourceType_Study) + { + if (request.IsRetrieveMainDicomTags(ResourceType_Series)) + { + DicomMap m; + GetMainDicomTags(m, ResourceType_Series); + DebugDicomMap(target["Series"]["MainDicomTags"], m); + } + + if (request.IsRetrieveMetadata(ResourceType_Series)) + { + DebugMetadata(target["Series"]["Metadata"], GetMetadata(ResourceType_Series)); + } + } + + if (request.GetLevel() != ResourceType_Patient && + request.GetLevel() != ResourceType_Study && + request.GetLevel() != ResourceType_Series) + { + if (request.IsRetrieveMainDicomTags(ResourceType_Instance)) + { + DicomMap m; + GetMainDicomTags(m, ResourceType_Instance); + DebugDicomMap(target["Instance"]["MainDicomTags"], m); + } + + if (request.IsRetrieveMetadata(ResourceType_Instance)) + { + DebugMetadata(target["Instance"]["Metadata"], GetMetadata(ResourceType_Instance)); + } + } + + if (request.IsRetrieveChildrenIdentifiers()) + { + Json::Value v = Json::arrayValue; + for (std::set<std::string>::const_iterator it = childrenIdentifiers_.begin(); + it != childrenIdentifiers_.end(); ++it) + { + v.append(*it); + } + target["Children"] = v; + } + + if (request.IsRetrieveLabels()) + { + Json::Value v = Json::arrayValue; + for (std::set<std::string>::const_iterator it = labels_.begin(); + it != labels_.end(); ++it) + { + v.append(*it); + } + target["Labels"] = v; + } + + if (request.IsRetrieveAttachments()) + { + Json::Value v = Json::objectValue; + for (std::map<FileContentType, FileInfo>::const_iterator it = attachments_.begin(); + it != attachments_.end(); ++it) + { + if (it->first != it->second.GetContentType()) + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + else + { + DebugAddAttachment(v, it->second); + } + } + target["Attachments"] = v; + } + + for (std::set<MetadataType>::const_iterator it = request.GetRetrieveChildrenMetadata().begin(); + it != request.GetRetrieveChildrenMetadata().end(); ++it) + { + std::list<std::string> l; + if (LookupChildrenMetadata(l, *it)) + { + Json::Value v = Json::arrayValue; + for (std::list<std::string>::const_iterator it2 = l.begin(); it2 != l.end(); ++it2) + { + v.append(*it2); + } + target["ChildrenMetadata"][EnumerationToString(*it)] = v; + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + } + + for (std::set<FileContentType>::const_iterator it = request.GetRetrieveAttachmentOfOneInstance().begin(); + it != request.GetRetrieveAttachmentOfOneInstance().end(); ++it) + { + FileInfo info; + if (LookupAttachmentOfOneInstance(info, *it)) + { + if (info.GetContentType() == *it) + { + DebugAddAttachment(target["AttachmentOfOneInstance"], info); + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + } }