# HG changeset patch # User Sebastien Jodogne # Date 1541431107 -3600 # Node ID 8eb4fe74000f215053b55918ce79cdd3815f67e5 # Parent 70256a53ff21f56d68c2afa0b2131b6c715f926a refactoring diff -r 70256a53ff21 -r 8eb4fe74000f Applications/Generic/NativeStoneApplicationContext.cpp --- a/Applications/Generic/NativeStoneApplicationContext.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Applications/Generic/NativeStoneApplicationContext.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -56,8 +56,6 @@ void NativeStoneApplicationContext::Start() { - dynamic_cast(webService_)->Start(); - if (centralViewport_->HasUpdateContent()) { stopped_ = false; @@ -74,7 +72,5 @@ { updateThread_.join(); } - - dynamic_cast(webService_)->Stop(); } } diff -r 70256a53ff21 -r 8eb4fe74000f Applications/Generic/NativeStoneApplicationRunner.cpp --- a/Applications/Generic/NativeStoneApplicationRunner.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Applications/Generic/NativeStoneApplicationRunner.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -184,34 +184,43 @@ LogStatusBar statusBar; NativeStoneApplicationContext context; - Oracle oracle(4); // use 4 threads to download content - OracleWebService webService(broker_, oracle, webServiceParameters, context); - context.SetWebService(webService); - - application_.Initialize(&context, statusBar, parameters); { - NativeStoneApplicationContext::GlobalMutexLocker locker(context); - context.SetCentralWidget(application_.GetCentralWidget()); - context.GetCentralViewport().SetStatusBar(statusBar); - } + Oracle oracle(4); // use 4 threads to download content + oracle.Start(); + + { + OracleWebService webService(broker_, oracle, webServiceParameters, context); + context.SetWebService(webService); + + application_.Initialize(&context, statusBar, parameters); + + { + NativeStoneApplicationContext::GlobalMutexLocker locker(context); + context.SetCentralWidget(application_.GetCentralWidget()); + context.GetCentralViewport().SetStatusBar(statusBar); + } - std::string title = application_.GetTitle(); - if (title.empty()) - { - title = "Stone of Orthanc"; + std::string title = application_.GetTitle(); + if (title.empty()) + { + title = "Stone of Orthanc"; + } + + /**************************************************************** + * Run the application + ****************************************************************/ + + Run(context, title, argc, argv); + + /**************************************************************** + * Finalize the application + ****************************************************************/ + + oracle.Stop(); + } } - /**************************************************************** - * Run the application - ****************************************************************/ - - Run(context, title, argc, argv); - - /**************************************************************** - * Finalize the application - ****************************************************************/ - LOG(WARNING) << "The application is stopping"; application_.Finalize(); } diff -r 70256a53ff21 -r 8eb4fe74000f Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp --- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -21,15 +21,16 @@ #include "SimpleViewerApplication.h" -#if ORTHANC_ENABLE_QT==1 -#include "Qt/SimpleViewerMainWindow.h" +#if ORTHANC_ENABLE_QT == 1 +# include "Qt/SimpleViewerMainWindow.h" #endif -#if ORTHANC_ENABLE_WASM==1 -#include +#if ORTHANC_ENABLE_WASM == 1 +# include #endif -namespace SimpleViewer { +namespace SimpleViewer +{ void SimpleViewerApplication::Initialize(StoneApplicationContext* context, IStatusBar& statusBar, @@ -101,7 +102,7 @@ void SimpleViewerApplication::OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Json::Value& response = message.Response; + const Json::Value& response = message.GetJson(); if (response.isArray() && response.size() > 1) { @@ -110,7 +111,7 @@ } void SimpleViewerApplication::OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Json::Value& response = message.Response; + const Json::Value& response = message.GetJson(); if (response.isObject() && response["Series"].isArray()) { @@ -123,7 +124,7 @@ void SimpleViewerApplication::OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Json::Value& response = message.Response; + const Json::Value& response = message.GetJson(); if (response.isObject() && response["Instances"].isArray() && response["Instances"].size() > 0) { @@ -166,7 +167,7 @@ void SimpleViewerApplication::OnWidgetGeometryChanged(const LayerWidget::GeometryChangedMessage& message) { - message.origin_.FitContent(); + message.GetOrigin().FitContent(); } void SimpleViewerApplication::SelectSeriesInMainViewport(const std::string& seriesId) diff -r 70256a53ff21 -r 8eb4fe74000f Applications/Samples/SimpleViewerApplicationSingleFile.h --- a/Applications/Samples/SimpleViewerApplicationSingleFile.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Applications/Samples/SimpleViewerApplicationSingleFile.h Mon Nov 05 16:18:27 2018 +0100 @@ -44,8 +44,8 @@ namespace Samples { class SimpleViewerApplication : - public SampleSingleCanvasWithButtonsApplicationBase, - public IObserver + public SampleSingleCanvasWithButtonsApplicationBase, + public IObserver { private: class ThumbnailInteractor : public IWorldSceneInteractor @@ -169,20 +169,20 @@ { switch (keyChar) { - case 's': - widget.FitContent(); - break; + case 's': + widget.FitContent(); + break; - case 'l': - application_.currentTool_ = Tools_LineMeasure; - break; + case 'l': + application_.currentTool_ = Tools_LineMeasure; + break; - case 'c': - application_.currentTool_ = Tools_CircleMeasure; - break; + case 'c': + application_.currentTool_ = Tools_CircleMeasure; + break; - default: - break; + default: + break; } } }; @@ -196,7 +196,7 @@ public: SimpleViewerApplicationAdapter(MessageBroker& broker, SimpleViewerApplication& application) : WasmPlatformApplicationAdapter(broker, application), - viewerApplication_(application) + viewerApplication_(application) { } @@ -264,9 +264,9 @@ { boost::program_options::options_description generic("Sample options"); generic.add_options() - ("studyId", boost::program_options::value(), - "Orthanc ID of the study") - ; + ("studyId", boost::program_options::value(), + "Orthanc ID of the study") + ; options.add(generic); } @@ -319,7 +319,9 @@ if (parameters.count("studyId") < 1) { LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; - orthancApiClient_->GetJsonAsync("/studies", new Callable(*this, &SimpleViewerApplication::OnStudyListReceived)); + orthancApiClient_->GetJsonAsync("/studies", + new Callable + (*this, &SimpleViewerApplication::OnStudyListReceived)); } else { @@ -329,7 +331,7 @@ void OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Json::Value& response = message.Response; + const Json::Value& response = message.GetJson(); if (response.isArray() && response.size() > 1) { @@ -338,22 +340,26 @@ } void OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Json::Value& response = message.Response; + const Json::Value& response = message.GetJson(); if (response.isObject() && response["Series"].isArray()) { for (size_t i=0; i < response["Series"].size(); i++) { - orthancApiClient_->GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable(*this, &SimpleViewerApplication::OnSeriesReceived)); + orthancApiClient_->GetJsonAsync("/series/" + response["Series"][(int)i].asString(), + new Callable + (*this, &SimpleViewerApplication::OnSeriesReceived)); } } } void OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Json::Value& response = message.Response; + const Json::Value& response = message.GetJson(); - if (response.isObject() && response["Instances"].isArray() && response["Instances"].size() > 0) + if (response.isObject() && + response["Instances"].isArray() && + response["Instances"].size() > 0) { // keep track of all instances IDs const std::string& seriesId = response["ID"].asString(); @@ -395,7 +401,7 @@ void OnWidgetGeometryChanged(const LayerWidget::GeometryChangedMessage& message) { - message.origin_.FitContent(); + message.GetOrigin().FitContent(); } void SelectSeriesInMainViewport(const std::string& seriesId) @@ -417,8 +423,8 @@ virtual void GetButtonNames(std::string& pushButton1, std::string& pushButton2, std::string& tool1, - std::string& tool2 - ) { + std::string& tool2) + { tool1 = "line"; tool2 = "circle"; pushButton1 = "action1"; @@ -426,8 +432,8 @@ } #if ORTHANC_ENABLE_WASM==1 - virtual void InitializeWasm() { - + virtual void InitializeWasm() + { AttachWidgetToWasmViewport("canvas", thumbnailsLayout_); AttachWidgetToWasmViewport("canvas2", mainWidget_); } diff -r 70256a53ff21 -r 8eb4fe74000f Applications/Samples/SingleFrameApplication.h --- a/Applications/Samples/SingleFrameApplication.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Applications/Samples/SingleFrameApplication.h Mon Nov 05 16:18:27 2018 +0100 @@ -187,7 +187,7 @@ // Once the geometry of the series is downloaded from Orthanc, // display its middle slice, and adapt the viewport to fit this // slice - if (source_ == &message.origin_) + if (source_ == &message.GetOrigin()) { SetSlice(source_->GetSliceCount() / 2); } diff -r 70256a53ff21 -r 8eb4fe74000f Applications/Samples/SingleFrameEditorApplication.h --- a/Applications/Samples/SingleFrameEditorApplication.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Applications/Samples/SingleFrameEditorApplication.h Mon Nov 05 16:18:27 2018 +0100 @@ -1164,17 +1164,17 @@ void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) { - size_t index = dynamic_cast*>(message.Payload.get())->GetValue(); - - LOG(INFO) << "JSON received: " << message.Uri.c_str() - << " (" << message.AnswerSize << " bytes) for bitmap " << index; + size_t index = dynamic_cast&>(message.GetPayload()).GetValue(); + + LOG(INFO) << "JSON received: " << message.GetUri().c_str() + << " (" << message.GetAnswerSize() << " bytes) for bitmap " << index; Bitmaps::iterator bitmap = bitmaps_.find(index); if (bitmap != bitmaps_.end()) { assert(bitmap->second != NULL); - OrthancPlugins::FullOrthancDataset dicom(message.Answer, message.AnswerSize); + OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer(), message.GetAnswerSize()); dynamic_cast(bitmap->second)->SetDicomTags(dicom); float c, w; @@ -1193,10 +1193,10 @@ void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) { - size_t index = dynamic_cast*>(message.Payload.get())->GetValue(); + size_t index = dynamic_cast&>(message.GetPayload()).GetValue(); - LOG(INFO) << "DICOM frame received: " << message.Uri.c_str() - << " (" << message.AnswerSize << " bytes) for bitmap " << index; + LOG(INFO) << "DICOM frame received: " << message.GetUri().c_str() + << " (" << message.GetAnswerSize() << " bytes) for bitmap " << index; Bitmaps::iterator bitmap = bitmaps_.find(index); if (bitmap != bitmaps_.end()) @@ -1204,9 +1204,9 @@ assert(bitmap->second != NULL); std::string content; - if (message.AnswerSize > 0) + if (message.GetAnswerSize() > 0) { - content.assign(reinterpret_cast(message.Answer), message.AnswerSize); + content.assign(reinterpret_cast(message.GetAnswer()), message.GetAnswerSize()); } std::auto_ptr reader(new Orthanc::PamReader); @@ -2823,7 +2823,7 @@ void OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) { LOG(WARNING) << "DICOM export was successful:" - << message.Response.toStyledString(); + << message.GetJson().toStyledString(); } }; diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Layers/OrthancFrameLayerSource.cpp --- a/Framework/Layers/OrthancFrameLayerSource.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Layers/OrthancFrameLayerSource.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -34,7 +34,7 @@ void OrthancFrameLayerSource::OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message) { - if (message.origin_.GetSliceCount() > 0) + if (message.GetOrigin().GetSliceCount() > 0) { LayerSourceBase::NotifyGeometryReady(); } diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Messages/IMessage.h --- a/Framework/Messages/IMessage.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Messages/IMessage.h Mon Nov 05 16:18:27 2018 +0100 @@ -29,59 +29,79 @@ // base message that are exchanged between IObservable and IObserver - struct IMessage : public boost::noncopyable + class IMessage : public boost::noncopyable { + private: int messageType_; + protected: - IMessage(const int& messageType) - : messageType_(messageType) - {} + IMessage(const int& messageType) : + messageType_(messageType) + { + } + public: - virtual ~IMessage() {} + virtual ~IMessage() + { + } - virtual int GetType() const {return messageType_;} + virtual int GetType() const + { + return messageType_; + } }; // base class to derive from to implement your own messages // it handles the message type for you template - struct BaseMessage : public IMessage + class BaseMessage : public IMessage { + public: enum { Type = type }; - BaseMessage() - : IMessage(static_cast(Type)) - {} + BaseMessage() : + IMessage(static_cast(Type)) + { + } }; + // simple message implementation when no payload is needed // sample usage: // typedef NoPayloadMessage GeometryReadyMessage; template - struct NoPayloadMessage : public BaseMessage + class NoPayloadMessage : public BaseMessage { - NoPayloadMessage() - : BaseMessage() - {} - + public: + NoPayloadMessage() : + BaseMessage() + { + } }; // simple message implementation when no payload is needed but the origin is required // sample usage: // typedef OriginMessage SliceGeometryErrorMessage; template - struct OriginMessage : public BaseMessage + class OriginMessage : public BaseMessage { + private: TOrigin& origin_; - OriginMessage(TOrigin& origin) - : BaseMessage(), - origin_(origin) - {} - }; + public: + OriginMessage(TOrigin& origin) : + BaseMessage(), + origin_(origin) + { + } + TOrigin& GetOrigin() const + { + return origin_; + } + }; } diff -r 70256a53ff21 -r 8eb4fe74000f Framework/SmartLoader.cpp --- a/Framework/SmartLoader.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/SmartLoader.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -206,7 +206,7 @@ void SmartLoader::OnLayerGeometryReady(const ILayerSource::GeometryReadyMessage& message) { - OrthancFrameLayerSource& source = dynamic_cast(message.origin_); + OrthancFrameLayerSource& source = dynamic_cast(message.GetOrigin()); // save/replace the slice in cache const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() @@ -229,7 +229,7 @@ void SmartLoader::OnImageReady(const ILayerSource::ImageReadyMessage& message) { - OrthancFrameLayerSource& source = dynamic_cast(message.origin_); + OrthancFrameLayerSource& source = dynamic_cast(message.GetOrigin()); // save/replace the slice in cache const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? @@ -253,7 +253,7 @@ void SmartLoader::OnLayerReady(const ILayerSource::LayerReadyMessage& message) { - OrthancFrameLayerSource& source = dynamic_cast(message.origin_); + OrthancFrameLayerSource& source = dynamic_cast(message.GetOrigin()); const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + boost::lexical_cast(slice.GetFrame())); diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Toolbox/IWebService.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Toolbox/IWebService.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -0,0 +1,55 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "IWebService.h" + +#include + + +namespace OrthancStone +{ + const Orthanc::IDynamicObject& + IWebService::HttpRequestSuccessMessage::GetPayload() const + { + if (HasPayload()) + { + return *payload_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + + const Orthanc::IDynamicObject& + IWebService::HttpRequestErrorMessage::GetPayload() const + { + if (HasPayload()) + { + return *payload_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } +} diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Toolbox/IWebService.h --- a/Framework/Toolbox/IWebService.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Toolbox/IWebService.h Mon Nov 05 16:18:27 2018 +0100 @@ -21,12 +21,14 @@ #pragma once -#include #include "../../Framework/Messages/IObserver.h" #include "../../Framework/Messages/ICallable.h" + +#include +#include + #include #include -#include namespace OrthancStone { @@ -35,56 +37,110 @@ // in a WASM environment, the WebService is asynchronous, the IWebservice // also implements an asynchronous interface: you must schedule a request // and you'll be notified when the response/error is ready. - class IWebService + class IWebService : public boost::noncopyable { protected: MessageBroker& broker_; + public: typedef std::map Headers; - struct HttpRequestSuccessMessage: public BaseMessage + class HttpRequestSuccessMessage : public BaseMessage { - const std::string& uri_; - const void* answer_; - size_t answerSize_; - Orthanc::IDynamicObject* payload_; + private: + const std::string& uri_; + const void* answer_; + size_t answerSize_; + const Orthanc::IDynamicObject* payload_; + + public: HttpRequestSuccessMessage(const std::string& uri, const void* answer, size_t answerSize, - Orthanc::IDynamicObject* payload) - : BaseMessage(), - uri_(uri), - answer_(answer), - answerSize_(answerSize), - payload_(payload) - {} - }; + const Orthanc::IDynamicObject* payload) : + uri_(uri), + answer_(answer), + answerSize_(answerSize), + payload_(payload) + { + } + + const std::string& GetUri() const + { + return uri_; + } + + const void* GetAnswer() const + { + return answer_; + } + + size_t GetAnswerSize() const + { + return answerSize_; + } + + bool HasPayload() const + { + return payload_ != NULL; + } + + const Orthanc::IDynamicObject& GetPayload() const; - struct HttpRequestErrorMessage: public BaseMessage + const Orthanc::IDynamicObject* GetPayloadPointer() const + { + return payload_; + } + }; + + + class HttpRequestErrorMessage : public BaseMessage { - const std::string& uri_; - Orthanc::IDynamicObject* payload_; + private: + const std::string& uri_; + const Orthanc::IDynamicObject* payload_; + + public: HttpRequestErrorMessage(const std::string& uri, - Orthanc::IDynamicObject* payload) - : BaseMessage(), - uri_(uri), - payload_(payload) - {} + const Orthanc::IDynamicObject* payload) : + uri_(uri), + payload_(payload) + { + } + + const std::string& GetUri() const + { + return uri_; + } + + bool HasPayload() const + { + return payload_ != NULL; + } + + const Orthanc::IDynamicObject& GetPayload() const; + + const Orthanc::IDynamicObject* GetPayloadPointer() const + { + return payload_; + } }; + IWebService(MessageBroker& broker) : + broker_(broker) + { + } - IWebService(MessageBroker& broker) - : broker_(broker) - {} - + virtual ~IWebService() { } + virtual void GetAsync(const std::string& uri, const Headers& headers, - Orthanc::IDynamicObject* payload, + Orthanc::IDynamicObject* payload /* takes ownership */, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; @@ -92,14 +148,14 @@ virtual void PostAsync(const std::string& uri, const Headers& headers, const std::string& body, - Orthanc::IDynamicObject* payload, + Orthanc::IDynamicObject* payload /* takes ownership */, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; virtual void DeleteAsync(const std::string& uri, const Headers& headers, - Orthanc::IDynamicObject* payload, + Orthanc::IDynamicObject* payload /* takes ownership */, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Toolbox/OrthancApiClient.cpp --- a/Framework/Toolbox/OrthancApiClient.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Toolbox/OrthancApiClient.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -21,14 +21,67 @@ #include "OrthancApiClient.h" #include "MessagingToolbox.h" -#include #include "Framework/Toolbox/MessagingToolbox.h" -namespace OrthancStone { +#include - OrthancApiClient::OrthancApiClient(MessageBroker &broker, IWebService &orthanc) - : IObservable(broker), - orthanc_(orthanc) +namespace OrthancStone +{ + const Orthanc::IDynamicObject& OrthancApiClient::JsonResponseReadyMessage::GetPayload() const + { + if (HasPayload()) + { + return *payload_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + + const Orthanc::IDynamicObject& OrthancApiClient::BinaryResponseReadyMessage::GetPayload() const + { + if (HasPayload()) + { + return *payload_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + + const Orthanc::IDynamicObject& OrthancApiClient::EmptyResponseReadyMessage::GetPayload() const + { + if (HasPayload()) + { + return *payload_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + + const Orthanc::IDynamicObject& OrthancApiClient::HttpErrorMessage::GetPayload() const + { + if (HasPayload()) + { + return *payload_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + + OrthancApiClient::OrthancApiClient(MessageBroker &broker, IWebService &orthanc) : + IObservable(broker), + orthanc_(orthanc) { } @@ -54,16 +107,18 @@ void ConvertResponseToJson(const IWebService::HttpRequestSuccessMessage& message) { Json::Value response; - if (MessagingToolbox::ParseJson(response, message.answer_, message.answerSize_)) + if (MessagingToolbox::ParseJson(response, message.GetAnswer(), message.GetAnswerSize())) { if (orthancApiSuccessCallback_.get() != NULL) { - orthancApiSuccessCallback_->Apply(OrthancApiClient::JsonResponseReadyMessage(message.uri_, response, message.payload_)); + orthancApiSuccessCallback_->Apply(OrthancApiClient::JsonResponseReadyMessage + (message.GetUri(), response, message.GetPayloadPointer())); } } else if (orthancApiFailureCallback_.get() != NULL) { - orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_, message.payload_)); + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage + (message.GetUri(), message.GetPayloadPointer())); } delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) @@ -73,7 +128,7 @@ { if (orthancApiFailureCallback_.get() != NULL) { - orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_)); + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.GetUri(), message.GetPayloadPointer())); } delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) @@ -103,11 +158,14 @@ { if (orthancApiSuccessCallback_.get() != NULL) { - orthancApiSuccessCallback_->Apply(OrthancApiClient::BinaryResponseReadyMessage(message.uri_, message.answer_, message.answerSize_, message.payload_)); + orthancApiSuccessCallback_->Apply(OrthancApiClient::BinaryResponseReadyMessage + (message.GetUri(), message.GetAnswer(), + message.GetAnswerSize(), message.GetPayloadPointer())); } else if (orthancApiFailureCallback_.get() != NULL) { - orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_, message.payload_)); + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage + (message.GetUri(), message.GetPayloadPointer())); } delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) @@ -117,7 +175,7 @@ { if (orthancApiFailureCallback_.get() != NULL) { - orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_)); + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.GetUri(), message.GetPayloadPointer())); } delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) @@ -147,11 +205,13 @@ { if (orthancApiSuccessCallback_.get() != NULL) { - orthancApiSuccessCallback_->Apply(OrthancApiClient::EmptyResponseReadyMessage(message.uri_, message.payload_)); + orthancApiSuccessCallback_->Apply(OrthancApiClient::EmptyResponseReadyMessage + (message.GetUri(), message.GetPayloadPointer())); } else if (orthancApiFailureCallback_.get() != NULL) { - orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_, message.payload_)); + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage + (message.GetUri(), message.GetPayloadPointer())); } delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) @@ -161,7 +221,7 @@ { if (orthancApiFailureCallback_.get() != NULL) { - orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_)); + orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.GetUri(), message.GetPayloadPointer())); } delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this) diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Toolbox/OrthancApiClient.h --- a/Framework/Toolbox/OrthancApiClient.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Toolbox/OrthancApiClient.h Mon Nov 05 16:18:27 2018 +0100 @@ -30,105 +30,168 @@ namespace OrthancStone { - class OrthancApiClient: - public IObservable + class OrthancApiClient : public IObservable { public: - - struct JsonResponseReadyMessage : public BaseMessage + class JsonResponseReadyMessage : public BaseMessage { - Json::Value Response; - std::string Uri; - std::auto_ptr Payload; + private: + const std::string& uri_; + const Json::Value& json_; + const Orthanc::IDynamicObject* payload_; + public: JsonResponseReadyMessage(const std::string& uri, - const Json::Value& response, - Orthanc::IDynamicObject* payload = NULL) - : BaseMessage(), - Response(response), - Uri(uri), - Payload(payload) + const Json::Value& json, + const Orthanc::IDynamicObject* payload) : + uri_(uri), + json_(json), + payload_(payload) { } - }; - struct EmptyResponseReadyMessage : public BaseMessage - { - std::string Uri; - std::auto_ptr Payload; + const std::string& GetUri() const + { + return uri_; + } + + const Json::Value& GetJson() const + { + return json_; + } - EmptyResponseReadyMessage(const std::string& uri, - Orthanc::IDynamicObject* payload = NULL) - : BaseMessage(), - Uri(uri), - Payload(payload) + bool HasPayload() const { + return payload_ != NULL; } + + const Orthanc::IDynamicObject& GetPayload() const; }; + - struct HttpErrorMessage : public BaseMessage + class BinaryResponseReadyMessage : public BaseMessage { - std::string Uri; - std::auto_ptr Payload; + private: + const std::string& uri_; + const void* answer_; + size_t answerSize_; + const Orthanc::IDynamicObject* payload_; - HttpErrorMessage(const std::string& uri, - Orthanc::IDynamicObject* payload = NULL) - : BaseMessage(), - Uri(uri), - Payload(payload) - { - } - }; - - struct BinaryResponseReadyMessage : public BaseMessage - { - const void* Answer; - size_t AnswerSize; - std::string Uri; - std::auto_ptr Payload; - + public: BinaryResponseReadyMessage(const std::string& uri, const void* answer, size_t answerSize, - Orthanc::IDynamicObject* payload = NULL) - : BaseMessage(), - Answer(answer), - AnswerSize(answerSize), - Uri(uri), - Payload(payload) + const Orthanc::IDynamicObject* payload) : + uri_(uri), + answer_(answer), + answerSize_(answerSize), + payload_(payload) { } + + const std::string& GetUri() const + { + return uri_; + } + + const void* GetAnswer() const + { + return answer_; + } + + size_t GetAnswerSize() const + { + return answerSize_; + } + + bool HasPayload() const + { + return payload_ != NULL; + } + + const Orthanc::IDynamicObject& GetPayload() const; }; + class EmptyResponseReadyMessage : public BaseMessage + { + private: + const std::string& uri_; + const Orthanc::IDynamicObject* payload_; - public: + public: + EmptyResponseReadyMessage(const std::string& uri, + const Orthanc::IDynamicObject* payload) : + uri_(uri), + payload_(payload) + { + } + + const std::string& GetUri() const + { + return uri_; + } + + bool HasPayload() const + { + return payload_ != NULL; + } + + const Orthanc::IDynamicObject& GetPayload() const; + }; - enum Mode + + class HttpErrorMessage : public BaseMessage { - Mode_GetJson + private: + const std::string& uri_; + const Orthanc::IDynamicObject* payload_; + + public: + HttpErrorMessage(const std::string& uri, + const Orthanc::IDynamicObject* payload) : + uri_(uri), + payload_(payload) + { + } + + const std::string& GetUri() const + { + return uri_; + } + + bool HasPayload() const + { + return payload_ != NULL; + } + + const Orthanc::IDynamicObject& GetPayload() const; }; + protected: IWebService& orthanc_; public: OrthancApiClient(MessageBroker& broker, IWebService& orthanc); - virtual ~OrthancApiClient() {} + + virtual ~OrthancApiClient() + { + } // schedule a GET request expecting a JSON response. void GetJsonAsync(const std::string& uri, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL); + Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a GET request expecting a binary response. void GetBinaryAsync(const std::string& uri, const std::string& contentType, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL) + Orthanc::IDynamicObject* payload = NULL /* takes ownership */) { IWebService::Headers headers; headers["Accept"] = contentType; @@ -140,27 +203,27 @@ const IWebService::Headers& headers, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL); + Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a POST request expecting a JSON response. void PostBinaryAsyncExpectJson(const std::string& uri, const std::string& body, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL); + Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a POST request expecting a JSON response. void PostJsonAsyncExpectJson(const std::string& uri, const Json::Value& data, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL); + Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a DELETE request expecting an empty response. void DeleteAsync(const std::string& uri, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, - Orthanc::IDynamicObject* payload = NULL); + Orthanc::IDynamicObject* payload = NULL /* takes ownership */); }; diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Toolbox/OrthancSlicesLoader.cpp --- a/Framework/Toolbox/OrthancSlicesLoader.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Toolbox/OrthancSlicesLoader.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -232,13 +232,13 @@ void OrthancSlicesLoader::OnSliceImageError(const OrthancApiClient::HttpErrorMessage& message) { - NotifySliceImageError(dynamic_cast(*(message.Payload))); + NotifySliceImageError(dynamic_cast(message.GetPayload())); state_ = State_Error; } void OrthancSlicesLoader::ParseSeriesGeometry(const OrthancApiClient::JsonResponseReadyMessage& message) { - Json::Value series = message.Response; + const Json::Value& series = message.GetJson(); Json::Value::Members instances = series.getMemberNames(); slices_.Reserve(instances.size()); @@ -275,8 +275,8 @@ void OrthancSlicesLoader::ParseInstanceGeometry(const OrthancApiClient::JsonResponseReadyMessage& message) { - Json::Value tags = message.Response; - const std::string& instanceId = dynamic_cast(message.Payload.get())->GetInstanceId(); + const Json::Value& tags = message.GetJson(); + const std::string& instanceId = dynamic_cast(message.GetPayload()).GetInstanceId(); OrthancPlugins::FullOrthancDataset dataset(tags); @@ -312,9 +312,9 @@ void OrthancSlicesLoader::ParseFrameGeometry(const OrthancApiClient::JsonResponseReadyMessage& message) { - Json::Value tags = message.Response; - const std::string& instanceId = dynamic_cast(message.Payload.get())->GetInstanceId(); - unsigned int frame = dynamic_cast(message.Payload.get())->GetFrame(); + const Json::Value& tags = message.GetJson(); + const std::string& instanceId = dynamic_cast(message.GetPayload()).GetInstanceId(); + unsigned int frame = dynamic_cast(message.GetPayload()).GetFrame(); OrthancPlugins::FullOrthancDataset dataset(tags); @@ -340,13 +340,13 @@ void OrthancSlicesLoader::ParseSliceImagePng(const OrthancApiClient::BinaryResponseReadyMessage& message) { - const Operation& operation = dynamic_cast(*message.Payload.get()); + const Operation& operation = dynamic_cast(message.GetPayload()); boost::shared_ptr image; try { image.reset(new Orthanc::PngReader); - dynamic_cast(*image).ReadFromMemory(message.Answer, message.AnswerSize); + dynamic_cast(*image).ReadFromMemory(message.GetAnswer(), message.GetAnswerSize()); } catch (Orthanc::OrthancException&) { @@ -380,13 +380,13 @@ void OrthancSlicesLoader::ParseSliceImagePam(const OrthancApiClient::BinaryResponseReadyMessage& message) { - const Operation& operation = dynamic_cast(*message.Payload.get()); + const Operation& operation = dynamic_cast(message.GetPayload()); boost::shared_ptr image; try { image.reset(new Orthanc::PamReader); - dynamic_cast(*image).ReadFromMemory(std::string(reinterpret_cast(message.Answer), message.AnswerSize)); + dynamic_cast(*image).ReadFromMemory(std::string(reinterpret_cast(message.GetAnswer()), message.GetAnswerSize())); } catch (Orthanc::OrthancException&) { @@ -421,9 +421,9 @@ void OrthancSlicesLoader::ParseSliceImageJpeg(const OrthancApiClient::JsonResponseReadyMessage& message) { - const Operation& operation = dynamic_cast(*message.Payload.get()); + const Operation& operation = dynamic_cast(message.GetPayload()); - Json::Value encoded = message.Response; + const Json::Value& encoded = message.GetJson(); if (encoded.type() != Json::objectValue || !encoded.isMember("Orthanc") || encoded["Orthanc"].type() != Json::objectValue) @@ -432,7 +432,7 @@ return; } - Json::Value& info = encoded["Orthanc"]; + const Json::Value& info = encoded["Orthanc"]; if (!info.isMember("PixelData") || !info.isMember("Stretched") || !info.isMember("Compression") || @@ -593,11 +593,11 @@ void OrthancSlicesLoader::ParseSliceRawImage(const OrthancApiClient::BinaryResponseReadyMessage& message) { - const Operation& operation = dynamic_cast(*message.Payload.get()); + const Operation& operation = dynamic_cast(message.GetPayload()); Orthanc::GzipCompressor compressor; std::string raw; - compressor.Uncompress(raw, message.Answer, message.AnswerSize); + compressor.Uncompress(raw, message.GetAnswer(), message.GetAnswerSize()); const Orthanc::DicomImageInformation& info = operation.GetSlice().GetImageInformation(); diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Volumes/StructureSetLoader.cpp --- a/Framework/Volumes/StructureSetLoader.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Volumes/StructureSetLoader.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -37,7 +37,7 @@ void StructureSetLoader::OnReferencedSliceLoaded(const OrthancApiClient::JsonResponseReadyMessage& message) { - OrthancPlugins::FullOrthancDataset dataset(message.Response); + OrthancPlugins::FullOrthancDataset dataset(message.GetJson()); Orthanc::DicomMap slice; MessagingToolbox::ConvertDataset(slice, dataset); @@ -48,7 +48,7 @@ void StructureSetLoader::OnStructureSetLoaded(const OrthancApiClient::JsonResponseReadyMessage& message) { - OrthancPlugins::FullOrthancDataset dataset(message.Response); + OrthancPlugins::FullOrthancDataset dataset(message.GetJson()); structureSet_.reset(new DicomStructureSet(dataset)); std::set instances; @@ -66,7 +66,7 @@ void StructureSetLoader::OnLookupCompleted(const OrthancApiClient::JsonResponseReadyMessage& message) { - Json::Value lookup = message.Response; + const Json::Value& lookup = message.GetJson(); if (lookup.type() != Json::arrayValue || lookup.size() != 1 || diff -r 70256a53ff21 -r 8eb4fe74000f Framework/Widgets/LayerWidget.cpp --- a/Framework/Widgets/LayerWidget.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Framework/Widgets/LayerWidget.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -519,7 +519,7 @@ void LayerWidget::OnGeometryReady(const ILayerSource::GeometryReadyMessage& message) { size_t i; - if (LookupLayer(i, message.origin_)) + if (LookupLayer(i, message.GetOrigin())) { LOG(INFO) << ": Geometry ready for layer " << i << " in " << GetName(); @@ -558,7 +558,7 @@ void LayerWidget::OnContentChanged(const ILayerSource::ContentChangedMessage& message) { size_t index; - if (LookupLayer(index, message.origin_)) + if (LookupLayer(index, message.GetOrigin())) { InvalidateLayer(index); } @@ -571,7 +571,7 @@ if (message.slice_.ContainsPlane(slice_)) { size_t index; - if (LookupLayer(index, message.origin_)) + if (LookupLayer(index, message.GetOrigin())) { InvalidateLayer(index); } @@ -583,7 +583,7 @@ void LayerWidget::OnLayerReady(const ILayerSource::LayerReadyMessage& message) { size_t index; - if (LookupLayer(index, message.origin_)) + if (LookupLayer(index, message.GetOrigin())) { if (message.isError_) { diff -r 70256a53ff21 -r 8eb4fe74000f Platforms/Generic/OracleWebService.h --- a/Platforms/Generic/OracleWebService.h Mon Nov 05 13:25:03 2018 +0100 +++ b/Platforms/Generic/OracleWebService.h Mon Nov 05 16:18:27 2018 +0100 @@ -82,16 +82,5 @@ { oracle_.Submit(new WebServiceDeleteCommand(broker_, successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_)); } - - - void Start() - { - oracle_.Start(); - } - - void Stop() - { - oracle_.Stop(); - } }; } diff -r 70256a53ff21 -r 8eb4fe74000f Platforms/Generic/WebServiceCommandBase.cpp --- a/Platforms/Generic/WebServiceCommandBase.cpp Mon Nov 05 13:25:03 2018 +0100 +++ b/Platforms/Generic/WebServiceCommandBase.cpp Mon Nov 05 16:18:27 2018 +0100 @@ -49,17 +49,20 @@ void WebServiceCommandBase::Commit() { - NativeStoneApplicationContext::GlobalMutexLocker lock(context_); // we want to make sure that, i.e, the UpdateThread is not triggered while we are updating the "model" with the result of a WebServiceCommand + // We want to make sure that, i.e, the UpdateThread is not + // triggered while we are updating the "model" with the result of + // a WebServiceCommand + NativeStoneApplicationContext::GlobalMutexLocker lock(context_); if (success_ && successCallback_.get() != NULL) { - successCallback_->Apply(IWebService::HttpRequestSuccessMessage(uri_, answer_.c_str(), answer_.size(), payload_.release())); + IWebService::HttpRequestSuccessMessage message(uri_, answer_.c_str(), answer_.size(), payload_.get()); + successCallback_->Apply(message); } else if (!success_ && failureCallback_.get() != NULL) { - failureCallback_->Apply(IWebService::HttpRequestErrorMessage(uri_, payload_.release())); + IWebService::HttpRequestErrorMessage message(uri_, payload_.get()); + failureCallback_->Apply(message); } - } - } diff -r 70256a53ff21 -r 8eb4fe74000f Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Mon Nov 05 13:25:03 2018 +0100 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Mon Nov 05 16:18:27 2018 +0100 @@ -258,6 +258,7 @@ ${ORTHANC_STONE_ROOT}/Framework/Toolbox/Extent2D.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/FiniteProjectiveCamera.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GeometryToolbox.cpp + ${ORTHANC_STONE_ROOT}/Framework/Toolbox/IWebService.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/IWebService.h ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ImageGeometry.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/LinearAlgebra.cpp