Mercurial > hg > orthanc-dicomweb
changeset 291:05b4f440a961 refactoring
reorganization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sat, 08 Jun 2019 17:42:49 +0200 |
parents | 77d6374435dd |
children | 0222a9afa866 |
files | CMakeLists.txt Plugin/Plugin.cpp Plugin/StowRs.cpp Plugin/StowRs.h |
diffstat | 4 files changed, 222 insertions(+), 206 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Sat Jun 08 17:21:53 2019 +0200 +++ b/CMakeLists.txt Sat Jun 08 17:42:49 2019 +0200 @@ -113,6 +113,7 @@ add_definitions( -DHAS_ORTHANC_EXCEPTION=1 + -DHAS_ORTHANC_FRAMEWORK=1 -DORTHANC_ENABLE_LOGGING_PLUGIN=1 -DORTHANC_FRAMEWORK_VERSION_MAJOR=${ORTHANC_FRAMEWORK_MAJOR} -DORTHANC_FRAMEWORK_VERSION_MINOR=${ORTHANC_FRAMEWORK_MINOR}
--- a/Plugin/Plugin.cpp Sat Jun 08 17:21:53 2019 +0200 +++ b/Plugin/Plugin.cpp Sat Jun 08 17:42:49 2019 +0200 @@ -171,211 +171,7 @@ - - - - -#include "DicomWebFormatter.h" - -class StowServer : public OrthancPlugins::MultipartRestCallback -{ -private: - class Handler : public IHandler - { - private: - OrthancPluginContext* context_; - bool xml_; - std::string wadoBase_; - std::string expectedStudy_; - bool isFirst_; - Json::Value result_; - Json::Value success_; - Json::Value failed_; - - public: - Handler(OrthancPluginContext* context, - bool xml, - const std::string& wadoBase, - const std::string& expectedStudy) : - context_(context), - xml_(xml), - wadoBase_(wadoBase), - expectedStudy_(expectedStudy), - isFirst_(true), - result_(Json::objectValue), - success_(Json::arrayValue), - failed_(Json::arrayValue) - { - } - - virtual OrthancPluginErrorCode AddPart(const std::string& contentType, - const std::map<std::string, std::string>& headers, - const void* data, - size_t size) - { - if (contentType != "application/dicom") - { - throw Orthanc::OrthancException( - Orthanc::ErrorCode_UnsupportedMediaType, - "The STOW-RS request contains a part that is not " - "\"application/dicom\" (it is: \"" + contentType + "\")"); - } - - Json::Value dicom; - - try - { - OrthancPlugins::OrthancString s; - s.Assign(OrthancPluginDicomBufferToJson(context_, data, size, - OrthancPluginDicomToJsonFormat_Short, - OrthancPluginDicomToJsonFlags_None, 256)); - s.ToJson(dicom); - } - catch (Orthanc::OrthancException&) - { - // Bad DICOM file => TODO add to error - OrthancPlugins::LogWarning("STOW-RS cannot parse an incoming DICOM file"); - return OrthancPluginErrorCode_Success; - } - - if (dicom.type() != Json::objectValue || - !dicom.isMember(Orthanc::DICOM_TAG_SERIES_INSTANCE_UID.Format()) || - !dicom.isMember(Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()) || - !dicom.isMember(Orthanc::DICOM_TAG_SOP_INSTANCE_UID.Format()) || - !dicom.isMember(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID.Format()) || - dicom[Orthanc::DICOM_TAG_SERIES_INSTANCE_UID.Format()].type() != Json::stringValue || - dicom[Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()].type() != Json::stringValue || - dicom[Orthanc::DICOM_TAG_SOP_INSTANCE_UID.Format()].type() != Json::stringValue || - dicom[Orthanc::DICOM_TAG_STUDY_INSTANCE_UID.Format()].type() != Json::stringValue) - { - OrthancPlugins::LogWarning("STOW-RS: Missing a mandatory tag in incoming DICOM file"); - return OrthancPluginErrorCode_Success; - } - - const std::string seriesInstanceUid = dicom[Orthanc::DICOM_TAG_SERIES_INSTANCE_UID.Format()].asString(); - const std::string sopClassUid = dicom[Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()].asString(); - const std::string sopInstanceUid = dicom[Orthanc::DICOM_TAG_SOP_INSTANCE_UID.Format()].asString(); - const std::string studyInstanceUid = dicom[Orthanc::DICOM_TAG_STUDY_INSTANCE_UID.Format()].asString(); - - Json::Value item = Json::objectValue; - item[OrthancPlugins::DICOM_TAG_REFERENCED_SOP_CLASS_UID.Format()] = sopClassUid; - item[OrthancPlugins::DICOM_TAG_REFERENCED_SOP_INSTANCE_UID.Format()] = sopInstanceUid; - - if (!expectedStudy_.empty() && - studyInstanceUid != expectedStudy_) - { - OrthancPlugins::LogInfo("STOW-RS request restricted to study [" + expectedStudy_ + - "]: Ignoring instance from study [" + studyInstanceUid + "]"); - - /*item[OrthancPlugins::DICOM_TAG_WARNING_REASON.Format()] = - boost::lexical_cast<std::string>(0xB006); // Elements discarded - success.append(item);*/ - } - else - { - if (isFirst_) - { - std::string url = wadoBase_ + "studies/" + studyInstanceUid; - result_[OrthancPlugins::DICOM_TAG_RETRIEVE_URL.Format()] = url; - isFirst_ = false; - } - - OrthancPlugins::MemoryBuffer tmp; - bool ok = tmp.RestApiPost("/instances", data, size, false); - tmp.Clear(); - - if (ok) - { - std::string url = (wadoBase_ + - "studies/" + studyInstanceUid + - "/series/" + seriesInstanceUid + - "/instances/" + sopInstanceUid); - - item[OrthancPlugins::DICOM_TAG_RETRIEVE_URL.Format()] = url; - success_.append(item); - } - else - { - OrthancPlugins::LogError("Orthanc was unable to store one instance in a STOW-RS request"); - item[OrthancPlugins::DICOM_TAG_FAILURE_REASON.Format()] = - boost::lexical_cast<std::string>(0x0110); // Processing failure - failed_.append(item); - } - } - - return OrthancPluginErrorCode_Success; - } - - virtual OrthancPluginErrorCode Execute(OrthancPluginRestOutput* output) - { - result_[OrthancPlugins::DICOM_TAG_FAILED_SOP_SEQUENCE.Format()] = failed_; - result_[OrthancPlugins::DICOM_TAG_REFERENCED_SOP_SEQUENCE.Format()] = success_; - - std::string answer; - - { - OrthancPlugins::DicomWebFormatter::Locker locker(OrthancPluginDicomWebBinaryMode_Ignore, ""); - locker.Apply(answer, context_, result_, xml_); - } - - OrthancPluginAnswerBuffer(context_, output, answer.c_str(), answer.size(), - xml_ ? "application/dicom+xml" : "application/dicom+json"); - - return OrthancPluginErrorCode_Success; - } - }; - -public: - virtual IHandler* CreateHandler(OrthancPluginHttpMethod method, - const std::string& url, - const std::string& contentType, - const std::string& subType, - const std::vector<std::string>& groups, - const std::map<std::string, std::string>& headers) - { - OrthancPluginContext* context = OrthancPlugins::GetGlobalContext(); - - if (method != OrthancPluginHttpMethod_Post) - { - return NULL; - } - - const std::string wadoBase = OrthancPlugins::Configuration::GetBaseUrl(headers); - - std::string expectedStudy; - if (groups.size() == 1) - { - expectedStudy = groups[0]; - } - - if (expectedStudy.empty()) - { - OrthancPlugins::LogInfo("STOW-RS request without study"); - } - else - { - OrthancPlugins::LogInfo("STOW-RS request restricted to study UID " + expectedStudy); - } - - if (contentType != "multipart/related") - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_UnsupportedMediaType, - "The Content-Type of a STOW-RS request must be \"multipart/related\""); - } - - if (subType != "application/dicom") - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_UnsupportedMediaType, - "The STOW-RS plugin currently only supports \"application/dicom\" subtype"); - } - - return new Handler(context, IsXmlExpected(headers), wadoBase, expectedStudy); - } -}; - - -static StowServer stowServer_; - +static OrthancPlugins::StowServer stowServer_; #include <boost/filesystem.hpp>
--- a/Plugin/StowRs.cpp Sat Jun 08 17:21:53 2019 +0200 +++ b/Plugin/StowRs.cpp Sat Jun 08 17:42:49 2019 +0200 @@ -270,3 +270,201 @@ OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), isXml ? "application/dicom+xml" : "application/dicom+json"); } + + + + +namespace OrthancPlugins +{ + class StowServer::Handler : public IHandler + { + private: + OrthancPluginContext* context_; + bool xml_; + std::string wadoBase_; + std::string expectedStudy_; + bool isFirst_; + Json::Value result_; + Json::Value success_; + Json::Value failed_; + + public: + Handler(OrthancPluginContext* context, + bool xml, + const std::string& wadoBase, + const std::string& expectedStudy) : + context_(context), + xml_(xml), + wadoBase_(wadoBase), + expectedStudy_(expectedStudy), + isFirst_(true), + result_(Json::objectValue), + success_(Json::arrayValue), + failed_(Json::arrayValue) + { + } + + virtual OrthancPluginErrorCode AddPart(const std::string& contentType, + const std::map<std::string, std::string>& headers, + const void* data, + size_t size) + { + if (contentType != "application/dicom") + { + throw Orthanc::OrthancException( + Orthanc::ErrorCode_UnsupportedMediaType, + "The STOW-RS request contains a part that is not " + "\"application/dicom\" (it is: \"" + contentType + "\")"); + } + + Json::Value dicom; + + try + { + OrthancString s; + s.Assign(OrthancPluginDicomBufferToJson(context_, data, size, + OrthancPluginDicomToJsonFormat_Short, + OrthancPluginDicomToJsonFlags_None, 256)); + s.ToJson(dicom); + } + catch (Orthanc::OrthancException&) + { + // Bad DICOM file => TODO add to error + LogWarning("STOW-RS cannot parse an incoming DICOM file"); + return OrthancPluginErrorCode_Success; + } + + if (dicom.type() != Json::objectValue || + !dicom.isMember(Orthanc::DICOM_TAG_SERIES_INSTANCE_UID.Format()) || + !dicom.isMember(Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()) || + !dicom.isMember(Orthanc::DICOM_TAG_SOP_INSTANCE_UID.Format()) || + !dicom.isMember(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID.Format()) || + dicom[Orthanc::DICOM_TAG_SERIES_INSTANCE_UID.Format()].type() != Json::stringValue || + dicom[Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()].type() != Json::stringValue || + dicom[Orthanc::DICOM_TAG_SOP_INSTANCE_UID.Format()].type() != Json::stringValue || + dicom[Orthanc::DICOM_TAG_STUDY_INSTANCE_UID.Format()].type() != Json::stringValue) + { + LogWarning("STOW-RS: Missing a mandatory tag in incoming DICOM file"); + return OrthancPluginErrorCode_Success; + } + + const std::string seriesInstanceUid = dicom[Orthanc::DICOM_TAG_SERIES_INSTANCE_UID.Format()].asString(); + const std::string sopClassUid = dicom[Orthanc::DICOM_TAG_SOP_CLASS_UID.Format()].asString(); + const std::string sopInstanceUid = dicom[Orthanc::DICOM_TAG_SOP_INSTANCE_UID.Format()].asString(); + const std::string studyInstanceUid = dicom[Orthanc::DICOM_TAG_STUDY_INSTANCE_UID.Format()].asString(); + + Json::Value item = Json::objectValue; + item[DICOM_TAG_REFERENCED_SOP_CLASS_UID.Format()] = sopClassUid; + item[DICOM_TAG_REFERENCED_SOP_INSTANCE_UID.Format()] = sopInstanceUid; + + if (!expectedStudy_.empty() && + studyInstanceUid != expectedStudy_) + { + LogInfo("STOW-RS request restricted to study [" + expectedStudy_ + + "]: Ignoring instance from study [" + studyInstanceUid + "]"); + + /*item[DICOM_TAG_WARNING_REASON.Format()] = + boost::lexical_cast<std::string>(0xB006); // Elements discarded + success.append(item);*/ + } + else + { + if (isFirst_) + { + std::string url = wadoBase_ + "studies/" + studyInstanceUid; + result_[DICOM_TAG_RETRIEVE_URL.Format()] = url; + isFirst_ = false; + } + + MemoryBuffer tmp; + bool ok = tmp.RestApiPost("/instances", data, size, false); + tmp.Clear(); + + if (ok) + { + std::string url = (wadoBase_ + + "studies/" + studyInstanceUid + + "/series/" + seriesInstanceUid + + "/instances/" + sopInstanceUid); + + item[DICOM_TAG_RETRIEVE_URL.Format()] = url; + success_.append(item); + } + else + { + LogError("Orthanc was unable to store one instance in a STOW-RS request"); + item[DICOM_TAG_FAILURE_REASON.Format()] = + boost::lexical_cast<std::string>(0x0110); // Processing failure + failed_.append(item); + } + } + + return OrthancPluginErrorCode_Success; + } + + virtual OrthancPluginErrorCode Execute(OrthancPluginRestOutput* output) + { + result_[DICOM_TAG_FAILED_SOP_SEQUENCE.Format()] = failed_; + result_[DICOM_TAG_REFERENCED_SOP_SEQUENCE.Format()] = success_; + + std::string answer; + + { + DicomWebFormatter::Locker locker(OrthancPluginDicomWebBinaryMode_Ignore, ""); + locker.Apply(answer, context_, result_, xml_); + } + + OrthancPluginAnswerBuffer(context_, output, answer.c_str(), answer.size(), + xml_ ? "application/dicom+xml" : "application/dicom+json"); + + return OrthancPluginErrorCode_Success; + } + }; + + + StowServer::IHandler* StowServer::CreateHandler(OrthancPluginHttpMethod method, + const std::string& url, + const std::string& contentType, + const std::string& subType, + const std::vector<std::string>& groups, + const std::map<std::string, std::string>& headers) + { + OrthancPluginContext* context = GetGlobalContext(); + + if (method != OrthancPluginHttpMethod_Post) + { + return NULL; + } + + const std::string wadoBase = Configuration::GetBaseUrl(headers); + + std::string expectedStudy; + if (groups.size() == 1) + { + expectedStudy = groups[0]; + } + + if (expectedStudy.empty()) + { + LogInfo("STOW-RS request without study"); + } + else + { + LogInfo("STOW-RS request restricted to study UID " + expectedStudy); + } + + if (contentType != "multipart/related") + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_UnsupportedMediaType, + "The Content-Type of a STOW-RS request must be \"multipart/related\""); + } + + if (subType != "application/dicom") + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_UnsupportedMediaType, + "The STOW-RS plugin currently only supports \"application/dicom\" subtype"); + } + + return new Handler(context, IsXmlExpected(headers), wadoBase, expectedStudy); + } +}
--- a/Plugin/StowRs.h Sat Jun 08 17:21:53 2019 +0200 +++ b/Plugin/StowRs.h Sat Jun 08 17:42:49 2019 +0200 @@ -23,10 +23,31 @@ #include "Configuration.h" +#include <Plugins/Samples/Common/OrthancPluginCppWrapper.h> + + bool IsXmlExpected(const std::map<std::string, std::string>& headers); - bool IsXmlExpected(const OrthancPluginHttpRequest* request); +bool IsXmlExpected(const OrthancPluginHttpRequest* request); void StowCallback(OrthancPluginRestOutput* output, const char* url, const OrthancPluginHttpRequest* request); + + +namespace OrthancPlugins +{ + class StowServer : public MultipartRestCallback + { + private: + class Handler; + + public: + virtual IHandler* CreateHandler(OrthancPluginHttpMethod method, + const std::string& url, + const std::string& contentType, + const std::string& subType, + const std::vector<std::string>& groups, + const std::map<std::string, std::string>& headers); + }; +}