Mercurial > hg > orthanc
changeset 5574:5a13483d12c5 find-refactoring
find-refactoring: attachments
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Fri, 26 Apr 2024 16:32:18 +0200 |
parents | 738f80622e91 |
children | 9e74e761b108 |
files | NEWS OrthancServer/Sources/Database/FindRequest.h OrthancServer/Sources/Database/FindResponse.h OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp |
diffstat | 6 files changed, 104 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Thu Apr 25 17:07:33 2024 +0200 +++ b/NEWS Fri Apr 26 16:32:18 2024 +0200 @@ -27,7 +27,7 @@ in case you just want to update the MainDicomTags of that resource level only e.g. after you have updated the 'ExtraMainDicomTags' for this level. * TODO-FIND: complete the list of updated routes: - /studies?expand and sibbling routes now also return "Metadata" + /studies?expand and sibbling routes now also return "Metadata" (if the DB implements 'extended-api-v1') Plugins -------
--- a/OrthancServer/Sources/Database/FindRequest.h Thu Apr 25 17:07:33 2024 +0200 +++ b/OrthancServer/Sources/Database/FindRequest.h Fri Apr 26 16:32:18 2024 +0200 @@ -49,7 +49,8 @@ ResponseContent_Parent = (1 << 4), // get the id of the parent ResponseContent_Children = (1 << 5), // retrieve the list of children ids ResponseContent_ChildInstanceId = (1 << 6), // When you need to access all tags from a patient/study/series, you might need to open the DICOM file of a child instance - ResponseContent_IsStable = (1 << 7), // This is currently not saved in DB but it could be in the future. + ResponseContent_ChildrenMetadata = (1 << 7), // That is actually required to compute the series status but could be usefull for other stuffs. + ResponseContent_IsStable = (1 << 8), // This is currently not saved in DB but it could be in the future. ResponseContent_IdentifiersOnly = 0, ResponseContent_INTERNAL = 0x7FFFFFFF
--- a/OrthancServer/Sources/Database/FindResponse.h Thu Apr 25 17:07:33 2024 +0200 +++ b/OrthancServer/Sources/Database/FindResponse.h Fri Apr 26 16:32:18 2024 +0200 @@ -23,6 +23,8 @@ #pragma once #include "../../../OrthancFramework/Sources/DicomFormat/DicomMap.h" +#include "../../../OrthancFramework/Sources/Enumerations.h" +#include "../../../OrthancFramework/Sources/FileStorage/FileInfo.h" #include "../ServerEnumerations.h" #include "OrthancIdentifiers.h" #include "FindRequest.h" @@ -90,7 +92,7 @@ std::string childInstanceId_; std::set<std::string> labels_; std::map<MetadataType, std::string> metadata_; - std::map<uint16_t, std::string> attachments_; + std::map<FileContentType, FileInfo> attachments_; public: Item(FindRequest::ResponseContent responseContent, @@ -194,6 +196,29 @@ { return labels_; } + + void AddAttachment(const FileInfo& attachment) + { + attachments_[attachment.GetContentType()] = attachment; + } + + const std::map<FileContentType, FileInfo>& GetAttachments() const + { + return attachments_; + } + + bool LookupAttachment(FileInfo& target, FileContentType type) const + { + std::map<FileContentType, FileInfo>::const_iterator it = attachments_.find(type); + if (it != attachments_.end()) + { + target = it->second; + return true; + } + + return false; + } + // TODO-FIND: add other getters and setters };
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Thu Apr 25 17:07:33 2024 +0200 +++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Fri Apr 26 16:32:18 2024 +0200 @@ -1285,7 +1285,29 @@ } } - // TODO-FIND: implement other responseContent: ResponseContent_ChildInstanceId, ResponseContent_Attachments, (later: ResponseContent_IsStable) + if (request.HasResponseContent(FindRequest::ResponseContent_Attachments)) + { + SQLite::Statement statement(db_, SQLITE_FROM_HERE, + "SELECT filtered.publicId, uuid, fileType, uncompressedSize, compressionType, compressedSize, " + " uncompressedMD5, compressedMD5 " + "FROM AttachedFiles " + " INNER JOIN FilteredResourcesIds filtered ON filtered.internalId = AttachedFiles.id"); + + while (statement.Step()) + { + const std::string& resourceId = statement.ColumnString(0); + FileInfo attachment = FileInfo(statement.ColumnString(1), + static_cast<FileContentType>(statement.ColumnInt(2)), + statement.ColumnInt64(3), + statement.ColumnString(6), + static_cast<CompressionType>(statement.ColumnInt(4)), + statement.ColumnInt64(5), + statement.ColumnString(7)); + items[resourceId]->AddAttachment(attachment); + }; + } + + // TODO-FIND: implement other responseContent: ResponseContent_ChildInstanceId, ResponseContent_ChildrenMetadata (later: ResponseContent_IsStable) } }
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Thu Apr 25 17:07:33 2024 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Fri Apr 26 16:32:18 2024 +0200 @@ -3926,6 +3926,24 @@ { labels_ = item.GetLabels(); } - // TODO-FIND: continue: isStable_, satus_, fileSize_, fileUuid_ + + if (item.HasResponseContent(FindRequest::ResponseContent_Attachments)) + { + FileInfo attachment; + if (item.LookupAttachment(attachment, FileContentType_Dicom)) + { + fileSize_ = attachment.GetUncompressedSize(); + fileUuid_ = attachment.GetUuid(); + } + } + + if (item.HasResponseContent(FindRequest::ResponseContent_ChildrenMetadata)) + { + // TODO-FIND: the status_ is normally obtained from transaction.GetSeriesStatus(internalId, i) + // but, that's an heavy operation for something that is rarely used -> we should have dedicated SQL code + // to compute it AFAP and we should compute it only if the user request it ! + } + + // TODO-FIND: continue: isStable_, status_ } }
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Apr 25 17:07:33 2024 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri Apr 26 16:32:18 2024 +0200 @@ -230,20 +230,47 @@ * EXPERIMENTAL VERSION **/ + // TODO-FIND: include the FindRequest options parsing in a method (parse from get-arguments and from post payload) + // TODO-FIND: support other values for expand like expand=MainDicomTags,Labels,Parent,SeriesStatus const bool expand = (call.HasArgument("expand") && call.GetBooleanArgument("expand", true)); + std::set<DicomTag> requestedTags; + OrthancRestApi::GetRequestedTags(requestedTags, call); + + const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); + FindRequest request(resourceType); if (expand) { - request.SetResponseContent(static_cast<FindRequest::ResponseContent>(FindRequest::ResponseContent_MainDicomTags | + // compatibility with default expand option + FindRequest::ResponseContent responseContent = static_cast<FindRequest::ResponseContent>(FindRequest::ResponseContent_MainDicomTags | FindRequest::ResponseContent_Metadata | - FindRequest::ResponseContent_Labels | - FindRequest::ResponseContent_Attachments | - FindRequest::ResponseContent_Parent | - FindRequest::ResponseContent_Children)); - + FindRequest::ResponseContent_Labels); + + if (requestedTags.size() > 0 && resourceType != ResourceType_Instance) // if we are requesting specific tags that might be outside of the MainDicomTags, we must get a childInstanceId too + { + responseContent = static_cast<FindRequest::ResponseContent>(responseContent | FindRequest::ResponseContent_ChildInstanceId); + } + if (resourceType == ResourceType_Series) + { + responseContent = static_cast<FindRequest::ResponseContent>(responseContent | FindRequest::ResponseContent_ChildrenMetadata); // required for the SeriesStatus + } + if (resourceType != ResourceType_Instance) + { + responseContent = static_cast<FindRequest::ResponseContent>(responseContent | FindRequest::ResponseContent_Children); + } + if (resourceType == ResourceType_Instance) + { + responseContent = static_cast<FindRequest::ResponseContent>(responseContent | FindRequest::ResponseContent_Attachments); // for FileSize & FileUuid + } + if (resourceType != ResourceType_Patient) + { + responseContent = static_cast<FindRequest::ResponseContent>(responseContent | FindRequest::ResponseContent_Parent); + } + + request.SetResponseContent(responseContent); request.SetRetrieveTagsAtLevel(resourceType, true); if (resourceType == ResourceType_Study) @@ -294,11 +321,6 @@ } else { - std::set<DicomTag> requestedTags; - OrthancRestApi::GetRequestedTags(requestedTags, call); - - const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); - for (size_t i = 0; i < response.GetSize(); i++) { context.AppendFindResponse(answer, response.GetItem(i), format, requestedTags, true /* allowStorageAccess */);