Mercurial > hg > orthanc
changeset 2894:a27b0e9a3fd9 db-changes
refactoring DicomInstanceToStore
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 18 Oct 2018 10:35:09 +0200 |
parents | 1723cbba55c7 |
children | da43ef7ff32a |
files | OrthancServer/DicomInstanceToStore.cpp OrthancServer/DicomInstanceToStore.h OrthancServer/LuaScripting.h OrthancServer/ServerContext.cpp OrthancServer/ServerIndex.h |
diffstat | 5 files changed, 352 insertions(+), 271 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/DicomInstanceToStore.cpp Tue Oct 16 19:47:09 2018 +0200 +++ b/OrthancServer/DicomInstanceToStore.cpp Thu Oct 18 10:35:09 2018 +0200 @@ -35,7 +35,9 @@ #include "DicomInstanceToStore.h" #include "../Core/DicomParsing/FromDcmtkBridge.h" +#include "../Core/DicomParsing/ParsedDicomFile.h" #include "../Core/Logging.h" +#include "../Core/OrthancException.h" #include <dcmtk/dcmdata/dcfilefo.h> #include <dcmtk/dcmdata/dcdeftag.h> @@ -43,161 +45,355 @@ namespace Orthanc { + // Anonymous namespace to avoid clashes between compilation modules + namespace + { + template <typename T> + class SmartContainer + { + private: + T* content_; + bool toDelete_; + bool isReadOnly_; + + void Deallocate() + { + if (content_ && toDelete_) + { + delete content_; + toDelete_ = false; + content_ = NULL; + } + } + + public: + SmartContainer() : content_(NULL), toDelete_(false), isReadOnly_(true) + { + } + + ~SmartContainer() + { + Deallocate(); + } + + void Allocate() + { + Deallocate(); + content_ = new T; + toDelete_ = true; + isReadOnly_ = false; + } + + void TakeOwnership(T* content) + { + if (content == NULL) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + Deallocate(); + content_ = content; + toDelete_ = true; + isReadOnly_ = false; + } + + void SetReference(T& content) // Read and write assign, without transfering ownership + { + Deallocate(); + content_ = &content; + toDelete_ = false; + isReadOnly_ = false; + } + + void SetConstReference(const T& content) // Read-only assign, without transfering ownership + { + Deallocate(); + content_ = &const_cast<T&>(content); + toDelete_ = false; + isReadOnly_ = true; + } + + bool HasContent() const + { + return content_ != NULL; + } + + T& GetContent() + { + if (content_ == NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + if (isReadOnly_) + { + throw OrthancException(ErrorCode_ReadOnly); + } + + return *content_; + } + + const T& GetConstContent() const + { + if (content_ == NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + return *content_; + } + }; + } + + + struct DicomInstanceToStore::PImpl + { + DicomInstanceOrigin origin_; + SmartContainer<std::string> buffer_; + SmartContainer<ParsedDicomFile> parsed_; + SmartContainer<DicomMap> summary_; + SmartContainer<Json::Value> json_; + MetadataMap metadata_; + + void ComputeMissingInformation() + { + if (buffer_.HasContent() && + summary_.HasContent() && + json_.HasContent()) + { + // Fine, everything is available + return; + } + + if (!buffer_.HasContent()) + { + if (!parsed_.HasContent()) + { + if (!summary_.HasContent()) + { + throw OrthancException(ErrorCode_NotImplemented); + } + else + { + parsed_.TakeOwnership(new ParsedDicomFile(summary_.GetConstContent())); + } + } + + // Serialize the parsed DICOM file + buffer_.Allocate(); + if (!FromDcmtkBridge::SaveToMemoryBuffer(buffer_.GetContent(), + *parsed_.GetContent().GetDcmtkObject().getDataset())) + { + LOG(ERROR) << "Unable to serialize a DICOM file to a memory buffer"; + throw OrthancException(ErrorCode_InternalError); + } + } + + if (summary_.HasContent() && + json_.HasContent()) + { + return; + } + + // At this point, we know that the DICOM file is available as a + // memory buffer, but that its summary or its JSON version is + // missing + + if (!parsed_.HasContent()) + { + parsed_.TakeOwnership(new ParsedDicomFile(buffer_.GetConstContent())); + } + + // At this point, we have parsed the DICOM file + + if (!summary_.HasContent()) + { + summary_.Allocate(); + FromDcmtkBridge::ExtractDicomSummary(summary_.GetContent(), + *parsed_.GetContent().GetDcmtkObject().getDataset()); + } + + if (!json_.HasContent()) + { + json_.Allocate(); + + std::set<DicomTag> ignoreTagLength; + FromDcmtkBridge::ExtractDicomAsJson(json_.GetContent(), + *parsed_.GetContent().GetDcmtkObject().getDataset(), + ignoreTagLength); + } + } + + + const char* GetBufferData() + { + ComputeMissingInformation(); + + if (!buffer_.HasContent()) + { + throw OrthancException(ErrorCode_InternalError); + } + + if (buffer_.GetConstContent().size() == 0) + { + return NULL; + } + else + { + return buffer_.GetConstContent().c_str(); + } + } + + + size_t GetBufferSize() + { + ComputeMissingInformation(); + + if (!buffer_.HasContent()) + { + throw OrthancException(ErrorCode_InternalError); + } + + return buffer_.GetConstContent().size(); + } + + + const DicomMap& GetSummary() + { + ComputeMissingInformation(); + + if (!summary_.HasContent()) + { + throw OrthancException(ErrorCode_InternalError); + } + + return summary_.GetConstContent(); + } + + + const Json::Value& GetJson() + { + ComputeMissingInformation(); + + if (!json_.HasContent()) + { + throw OrthancException(ErrorCode_InternalError); + } + + return json_.GetConstContent(); + } + + + bool LookupTransferSyntax(std::string& result) + { + ComputeMissingInformation(); + + DicomMap header; + if (DicomMap::ParseDicomMetaInformation(header, GetBufferData(), GetBufferSize())) + { + const DicomValue* value = header.TestAndGetValue(DICOM_TAG_TRANSFER_SYNTAX_UID); + if (value != NULL && + !value->IsBinary() && + !value->IsNull()) + { + result = Toolbox::StripSpaces(value->GetContent()); + return true; + } + } + + return false; + } + }; + + + DicomInstanceToStore::DicomInstanceToStore() : + pimpl_(new PImpl) + { + } + + + void DicomInstanceToStore::SetOrigin(const DicomInstanceOrigin& origin) + { + pimpl_->origin_ = origin; + } + + + const DicomInstanceOrigin& DicomInstanceToStore::GetOrigin() const + { + return pimpl_->origin_; + } + + + void DicomInstanceToStore::SetBuffer(const std::string& dicom) + { + pimpl_->buffer_.SetConstReference(dicom); + } + + + void DicomInstanceToStore::SetParsedDicomFile(ParsedDicomFile& parsed) + { + pimpl_->parsed_.SetReference(parsed); + } + + + void DicomInstanceToStore::SetSummary(const DicomMap& summary) + { + pimpl_->summary_.SetConstReference(summary); + } + + + void DicomInstanceToStore::SetJson(const Json::Value& json) + { + pimpl_->json_.SetConstReference(json); + } + + + const DicomInstanceToStore::MetadataMap& DicomInstanceToStore::GetMetadata() const + { + return pimpl_->metadata_; + } + + + DicomInstanceToStore::MetadataMap& DicomInstanceToStore::GetMetadata() + { + return pimpl_->metadata_; + } + + void DicomInstanceToStore::AddMetadata(ResourceType level, MetadataType metadata, const std::string& value) { - metadata_[std::make_pair(level, metadata)] = value; + pimpl_->metadata_[std::make_pair(level, metadata)] = value; } - void DicomInstanceToStore::ComputeMissingInformation() - { - if (buffer_.HasContent() && - summary_.HasContent() && - json_.HasContent()) - { - // Fine, everything is available - return; - } - - if (!buffer_.HasContent()) - { - if (!parsed_.HasContent()) - { - if (!summary_.HasContent()) - { - throw OrthancException(ErrorCode_NotImplemented); - } - else - { - parsed_.TakeOwnership(new ParsedDicomFile(summary_.GetConstContent())); - } - } - - // Serialize the parsed DICOM file - buffer_.Allocate(); - if (!FromDcmtkBridge::SaveToMemoryBuffer(buffer_.GetContent(), - *parsed_.GetContent().GetDcmtkObject().getDataset())) - { - LOG(ERROR) << "Unable to serialize a DICOM file to a memory buffer"; - throw OrthancException(ErrorCode_InternalError); - } - } - - if (summary_.HasContent() && - json_.HasContent()) - { - return; - } - - // At this point, we know that the DICOM file is available as a - // memory buffer, but that its summary or its JSON version is - // missing - - if (!parsed_.HasContent()) - { - parsed_.TakeOwnership(new ParsedDicomFile(buffer_.GetConstContent())); - } - - // At this point, we have parsed the DICOM file - - if (!summary_.HasContent()) - { - summary_.Allocate(); - FromDcmtkBridge::ExtractDicomSummary(summary_.GetContent(), - *parsed_.GetContent().GetDcmtkObject().getDataset()); - } - - if (!json_.HasContent()) - { - json_.Allocate(); - - std::set<DicomTag> ignoreTagLength; - FromDcmtkBridge::ExtractDicomAsJson(json_.GetContent(), - *parsed_.GetContent().GetDcmtkObject().getDataset(), - ignoreTagLength); - } - } - - - const char* DicomInstanceToStore::GetBufferData() { - ComputeMissingInformation(); - - if (!buffer_.HasContent()) - { - throw OrthancException(ErrorCode_InternalError); - } - - if (buffer_.GetConstContent().size() == 0) - { - return NULL; - } - else - { - return buffer_.GetConstContent().c_str(); - } + return pimpl_->GetBufferData(); } size_t DicomInstanceToStore::GetBufferSize() { - ComputeMissingInformation(); - - if (!buffer_.HasContent()) - { - throw OrthancException(ErrorCode_InternalError); - } - - return buffer_.GetConstContent().size(); + return pimpl_->GetBufferSize(); } const DicomMap& DicomInstanceToStore::GetSummary() { - ComputeMissingInformation(); - - if (!summary_.HasContent()) - { - throw OrthancException(ErrorCode_InternalError); - } - - return summary_.GetConstContent(); + return pimpl_->GetSummary(); } const Json::Value& DicomInstanceToStore::GetJson() { - ComputeMissingInformation(); - - if (!json_.HasContent()) - { - throw OrthancException(ErrorCode_InternalError); - } - - return json_.GetConstContent(); + return pimpl_->GetJson(); } bool DicomInstanceToStore::LookupTransferSyntax(std::string& result) { - ComputeMissingInformation(); - - DicomMap header; - if (DicomMap::ParseDicomMetaInformation(header, GetBufferData(), GetBufferSize())) - { - const DicomValue* value = header.TestAndGetValue(DICOM_TAG_TRANSFER_SYNTAX_UID); - if (value != NULL && - !value->IsBinary() && - !value->IsNull()) - { - result = Toolbox::StripSpaces(value->GetContent()); - return true; - } - } - - return false; + return pimpl_->LookupTransferSyntax(result); } }
--- a/OrthancServer/DicomInstanceToStore.h Tue Oct 16 19:47:09 2018 +0200 +++ b/OrthancServer/DicomInstanceToStore.h Thu Oct 18 10:35:09 2018 +0200 @@ -33,166 +33,48 @@ #pragma once -#include "../Core/DicomParsing/ParsedDicomFile.h" -#include "../Core/OrthancException.h" +#include "../Core/DicomFormat/DicomMap.h" #include "DicomInstanceOrigin.h" -#include "ServerIndex.h" +#include "ServerEnumerations.h" + +#include <boost/shared_ptr.hpp> namespace Orthanc { + class ParsedDicomFile; + class DicomInstanceToStore { - private: - template <typename T> - class SmartContainer - { - private: - T* content_; - bool toDelete_; - bool isReadOnly_; - - void Deallocate() - { - if (content_ && toDelete_) - { - delete content_; - toDelete_ = false; - content_ = NULL; - } - } - - public: - SmartContainer() : content_(NULL), toDelete_(false), isReadOnly_(true) - { - } - - ~SmartContainer() - { - Deallocate(); - } - - void Allocate() - { - Deallocate(); - content_ = new T; - toDelete_ = true; - isReadOnly_ = false; - } - - void TakeOwnership(T* content) - { - if (content == NULL) - { - throw OrthancException(ErrorCode_ParameterOutOfRange); - } - - Deallocate(); - content_ = content; - toDelete_ = true; - isReadOnly_ = false; - } + public: + typedef std::map<std::pair<ResourceType, MetadataType>, std::string> MetadataMap; - void SetReference(T& content) // Read and write assign, without transfering ownership - { - Deallocate(); - content_ = &content; - toDelete_ = false; - isReadOnly_ = false; - } - - void SetConstReference(const T& content) // Read-only assign, without transfering ownership - { - Deallocate(); - content_ = &const_cast<T&>(content); - toDelete_ = false; - isReadOnly_ = true; - } - - bool HasContent() const - { - return content_ != NULL; - } - - T& GetContent() - { - if (content_ == NULL) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - - if (isReadOnly_) - { - throw OrthancException(ErrorCode_ReadOnly); - } - - return *content_; - } - - const T& GetConstContent() const - { - if (content_ == NULL) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - - return *content_; - } - }; - - DicomInstanceOrigin origin_; - SmartContainer<std::string> buffer_; - SmartContainer<ParsedDicomFile> parsed_; - SmartContainer<DicomMap> summary_; - SmartContainer<Json::Value> json_; - ServerIndex::MetadataMap metadata_; - - void ComputeMissingInformation(); + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; public: - void SetOrigin(const DicomInstanceOrigin& origin) - { - origin_ = origin; - } + DicomInstanceToStore(); + + void SetOrigin(const DicomInstanceOrigin& origin); - const DicomInstanceOrigin& GetOrigin() const - { - return origin_; - } + const DicomInstanceOrigin& GetOrigin() const; - void SetBuffer(const std::string& dicom) - { - buffer_.SetConstReference(dicom); - } + void SetBuffer(const std::string& dicom); - void SetParsedDicomFile(ParsedDicomFile& parsed) - { - parsed_.SetReference(parsed); - } + void SetParsedDicomFile(ParsedDicomFile& parsed); + + void SetSummary(const DicomMap& summary); - void SetSummary(const DicomMap& summary) - { - summary_.SetConstReference(summary); - } + void SetJson(const Json::Value& json); - void SetJson(const Json::Value& json) - { - json_.SetConstReference(json); - } + const MetadataMap& GetMetadata() const; + + MetadataMap& GetMetadata(); void AddMetadata(ResourceType level, MetadataType metadata, const std::string& value); - const ServerIndex::MetadataMap& GetMetadata() const - { - return metadata_; - } - - ServerIndex::MetadataMap& GetMetadata() - { - return metadata_; - } - const char* GetBufferData(); size_t GetBufferSize();
--- a/OrthancServer/LuaScripting.h Tue Oct 16 19:47:09 2018 +0200 +++ b/OrthancServer/LuaScripting.h Thu Oct 18 10:35:09 2018 +0200 @@ -34,6 +34,7 @@ #pragma once #include "DicomInstanceToStore.h" +#include "ServerIndexChange.h" #include "ServerJobs/LuaJobManager.h" #include "../Core/MultiThreading/SharedMessageQueue.h"
--- a/OrthancServer/ServerContext.cpp Tue Oct 16 19:47:09 2018 +0200 +++ b/OrthancServer/ServerContext.cpp Thu Oct 18 10:35:09 2018 +0200 @@ -316,8 +316,10 @@ { StorageAccessor accessor(area_); - DicomInstanceHasher hasher(dicom.GetSummary()); - resultPublicId = hasher.HashInstance(); + { + DicomInstanceHasher hasher(dicom.GetSummary()); + resultPublicId = hasher.HashInstance(); + } Json::Value simplifiedTags; ServerToolbox::SimplifyTags(simplifiedTags, dicom.GetJson(), DicomToJsonFormat_Human);
--- a/OrthancServer/ServerIndex.h Tue Oct 16 19:47:09 2018 +0200 +++ b/OrthancServer/ServerIndex.h Thu Oct 18 10:35:09 2018 +0200 @@ -54,7 +54,7 @@ { public: typedef std::list<FileInfo> Attachments; - typedef std::map< std::pair<ResourceType, MetadataType>, std::string> MetadataMap; + typedef std::map<std::pair<ResourceType, MetadataType>, std::string> MetadataMap; private: class Listener;