changeset 315:aad37d0b6407 am-2

Added LayerWidget::RemoveLayer + DELETE commands in WebService
author am@osimis.io
date Fri, 05 Oct 2018 10:38:16 +0200
parents 97f16214dc5e
children b66d13708f40
files Framework/Messages/MessageType.h Framework/Toolbox/IWebService.h Framework/Toolbox/OrthancApiClient.cpp Framework/Toolbox/OrthancApiClient.h Framework/Widgets/LayerWidget.cpp Framework/Widgets/LayerWidget.h Platforms/Generic/OracleWebService.h Platforms/Generic/WebServiceDeleteCommand.cpp Platforms/Generic/WebServiceDeleteCommand.h Platforms/Wasm/WasmWebService.cpp Platforms/Wasm/WasmWebService.h Platforms/Wasm/WasmWebService.js Resources/CMake/OrthancStoneConfiguration.cmake
diffstat 13 files changed, 273 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Messages/MessageType.h	Wed Oct 03 17:14:17 2018 +0200
+++ b/Framework/Messages/MessageType.h	Fri Oct 05 10:38:16 2018 +0200
@@ -47,9 +47,7 @@
     MessageType_OrthancApi_GenericGetJson_Ready,
     MessageType_OrthancApi_GenericGetBinary_Ready,
     MessageType_OrthancApi_GenericHttpError_Ready,
-    MessageType_OrthancApi_GetStudyIds_Ready,
-    MessageType_OrthancApi_GetStudy_Ready,
-    MessageType_OrthancApi_GetSeries_Ready,
+    MessageType_OrthancApi_GenericEmptyResponse_Ready,
 
     // used in unit tests only
     MessageType_Test1,
--- a/Framework/Toolbox/IWebService.h	Wed Oct 03 17:14:17 2018 +0200
+++ b/Framework/Toolbox/IWebService.h	Fri Oct 05 10:38:16 2018 +0200
@@ -97,5 +97,11 @@
                            MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL,
                            unsigned int timeoutInSeconds = 60) = 0;
 
+    virtual void DeleteAsync(const std::string& uri,
+                             const Headers& headers,
+                             Orthanc::IDynamicObject* payload,
+                             MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,
+                             MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL,
+                             unsigned int timeoutInSeconds = 60) = 0;
   };
 }
--- a/Framework/Toolbox/OrthancApiClient.cpp	Wed Oct 03 17:14:17 2018 +0200
+++ b/Framework/Toolbox/OrthancApiClient.cpp	Fri Oct 05 10:38:16 2018 +0200
@@ -120,6 +120,49 @@
     }
   };
 
+  // performs the translation between IWebService messages and OrthancApiClient messages
+  // TODO: handle destruction of this object (with shared_ptr ?::delete_later ???)
+  class HttpResponseToEmptyConverter : public IObserver, IObservable
+  {
+    std::auto_ptr<MessageHandler<OrthancApiClient::EmptyResponseReadyMessage>> orthancApiSuccessCallback_;
+    std::auto_ptr<MessageHandler<OrthancApiClient::HttpErrorMessage>> orthancApiFailureCallback_;
+  public:
+    HttpResponseToEmptyConverter(MessageBroker& broker,
+                                  MessageHandler<OrthancApiClient::EmptyResponseReadyMessage>* orthancApiSuccessCallback,
+                                  MessageHandler<OrthancApiClient::HttpErrorMessage>* orthancApiFailureCallback)
+      : IObserver(broker),
+        IObservable(broker),
+        orthancApiSuccessCallback_(orthancApiSuccessCallback),
+        orthancApiFailureCallback_(orthancApiFailureCallback)
+    {
+    }
+
+    void ConvertResponseToEmpty(const IWebService::HttpRequestSuccessMessage& message)
+    {
+      if (orthancApiSuccessCallback_.get() != NULL)
+      {
+        orthancApiSuccessCallback_->Apply(OrthancApiClient::EmptyResponseReadyMessage(message.uri_, message.payload_));
+      }
+      else if (orthancApiFailureCallback_.get() != NULL)
+      {
+        orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_, message.payload_));
+      }
+
+      delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this)
+    }
+
+    void ConvertError(const IWebService::HttpRequestErrorMessage& message)
+    {
+      if (orthancApiFailureCallback_.get() != NULL)
+      {
+        orthancApiFailureCallback_->Apply(OrthancApiClient::HttpErrorMessage(message.uri_));
+      }
+
+      delete this; // hack untill we find someone to take ownership of this object (https://isocpp.org/wiki/faq/freestore-mgmt#delete-this)
+    }
+  };
+
+
   void OrthancApiClient::GetJsonAsync(const std::string& uri,
                                       MessageHandler<JsonResponseReadyMessage>* successCallback,
                                       MessageHandler<HttpErrorMessage>* failureCallback,
@@ -168,5 +211,16 @@
     return PostBinaryAsyncExpectJson(uri, body, successCallback, failureCallback, payload);
   }
 
+  void OrthancApiClient::DeleteAsync(const std::string& uri,
+                                     MessageHandler<EmptyResponseReadyMessage>* successCallback,
+                                     MessageHandler<HttpErrorMessage>* failureCallback,
+                                     Orthanc::IDynamicObject* payload)
+  {
+    HttpResponseToEmptyConverter* converter = new HttpResponseToEmptyConverter(broker_, successCallback, failureCallback);  // it is currently deleting itself after being used
+    orthanc_.DeleteAsync(uri, IWebService::Headers(), payload,
+                       new Callable<HttpResponseToEmptyConverter, IWebService::HttpRequestSuccessMessage>(*converter, &HttpResponseToEmptyConverter::ConvertResponseToEmpty),
+                       new Callable<HttpResponseToEmptyConverter, IWebService::HttpRequestErrorMessage>(*converter, &HttpResponseToEmptyConverter::ConvertError));
+  }
+
 
 }
--- a/Framework/Toolbox/OrthancApiClient.h	Wed Oct 03 17:14:17 2018 +0200
+++ b/Framework/Toolbox/OrthancApiClient.h	Fri Oct 05 10:38:16 2018 +0200
@@ -52,6 +52,20 @@
       }
     };
 
+    struct EmptyResponseReadyMessage : public BaseMessage<MessageType_OrthancApi_GenericEmptyResponse_Ready>
+    {
+      std::string   Uri;
+      Orthanc::IDynamicObject*  Payload;
+
+      EmptyResponseReadyMessage(const std::string& uri,
+                                Orthanc::IDynamicObject*  payload = NULL)
+        : BaseMessage(),
+          Uri(uri),
+          Payload(payload)
+      {
+      }
+    };
+
     struct HttpErrorMessage : public BaseMessage<MessageType_OrthancApi_GenericHttpError_Ready>
     {
       std::string   Uri;
@@ -142,5 +156,12 @@
                                  MessageHandler<HttpErrorMessage>* failureCallback = NULL,
                                  Orthanc::IDynamicObject* payload = NULL);
 
+    // schedule a DELETE request expecting an empty response.
+    void DeleteAsync(const std::string& uri,
+                     MessageHandler<EmptyResponseReadyMessage>* successCallback,
+                     MessageHandler<HttpErrorMessage>* failureCallback = NULL,
+                     Orthanc::IDynamicObject* payload = NULL);
+
+
   };
 }
--- a/Framework/Widgets/LayerWidget.cpp	Wed Oct 03 17:14:17 2018 +0200
+++ b/Framework/Widgets/LayerWidget.cpp	Fri Oct 05 10:38:16 2018 +0200
@@ -37,7 +37,7 @@
     double                        thickness_;
     size_t                        countMissing_;
     std::vector<ILayerRenderer*>  renderers_;
-
+public:
     void DeleteLayer(size_t index)
     {
       if (index >= renderers_.size())
@@ -56,7 +56,6 @@
       }
     }
 
-  public:
     Scene(const CoordinateSystem3D& slice,
           double thickness,
           size_t countLayers) :
@@ -365,15 +364,6 @@
     IObservable(broker),
     started_(false)
   {
-//    DeclareHandledMessage(MessageType_LayerSource_GeometryReady);
-//    DeclareHandledMessage(MessageType_LayerSource_ContentChanged);
-//    DeclareHandledMessage(MessageType_LayerSource_LayerReady);
-//    DeclareHandledMessage(MessageType_LayerSource_SliceChanged);
-//    DeclareHandledMessage(MessageType_LayerSource_GeometryError);
-
-//    DeclareEmittableMessage(MessageType_Widget_GeometryChanged);
-//    DeclareEmittableMessage(MessageType_Widget_ContentChanged);
-
     SetBackgroundCleared(true);
   }
   
@@ -440,6 +430,26 @@
     InvalidateLayer(index);
   }
 
+  void LayerWidget::RemoveLayer(size_t index)
+  {
+    if (index >= layers_.size())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+
+    ILayerSource* previousLayer = layers_[index];
+    layersIndex_.erase(layersIndex_.find(previousLayer));
+    layers_.erase(layers_.begin() + index);
+    changedLayers_.erase(changedLayers_.begin() + index);
+    styles_.erase(styles_.begin() + index);
+
+    delete layers_[index];
+
+    currentScene_->DeleteLayer(index);
+    ResetPendingScene();
+
+    NotifyContentChanged();
+  }
 
   const RenderStyle& LayerWidget::GetLayerStyle(size_t layer) const
   {
--- a/Framework/Widgets/LayerWidget.h	Wed Oct 03 17:14:17 2018 +0200
+++ b/Framework/Widgets/LayerWidget.h	Fri Oct 05 10:38:16 2018 +0200
@@ -97,6 +97,8 @@
 
     void ReplaceLayer(size_t layerIndex, ILayerSource* layer); // Takes ownership
 
+    void RemoveLayer(size_t layerIndex);
+
     size_t GetLayerCount() const
     {
       return layers_.size();
--- a/Platforms/Generic/OracleWebService.h	Wed Oct 03 17:14:17 2018 +0200
+++ b/Platforms/Generic/OracleWebService.h	Fri Oct 05 10:38:16 2018 +0200
@@ -25,6 +25,7 @@
 #include "Oracle.h"
 #include "WebServiceGetCommand.h"
 #include "WebServicePostCommand.h"
+#include "WebServiceDeleteCommand.h"
 #include "../../Applications/Generic/NativeStoneApplicationContext.h"
 
 namespace OrthancStone
@@ -72,6 +73,17 @@
       oracle_.Submit(new WebServicePostCommand(broker_, successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, body, payload, context_));
     }
 
+    virtual void DeleteAsync(const std::string& uri,
+                             const Headers& headers,
+                             Orthanc::IDynamicObject* payload,
+                             MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,
+                             MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL,
+                             unsigned int timeoutInSeconds = 60)
+    {
+      oracle_.Submit(new WebServiceDeleteCommand(broker_, successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_));
+    }
+
+
     void Start()
     {
       oracle_.Start();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/WebServiceDeleteCommand.cpp	Fri Oct 05 10:38:16 2018 +0200
@@ -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 <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "WebServiceDeleteCommand.h"
+
+#include <Core/HttpClient.h>
+
+namespace OrthancStone
+{
+  WebServiceDeleteCommand::WebServiceDeleteCommand(MessageBroker& broker,
+                                                   MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+                                                   MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
+                                                   const Orthanc::WebServiceParameters& parameters,
+                                                   const std::string& uri,
+                                                   const IWebService::Headers& headers,
+                                                   unsigned int timeoutInSeconds,
+                                                   Orthanc::IDynamicObject* payload /* takes ownership */,
+                                                   NativeStoneApplicationContext& context) :
+    WebServiceCommandBase(broker, successCallback, failureCallback, parameters, uri, headers, timeoutInSeconds, payload, context)
+  {
+  }
+
+  void WebServiceDeleteCommand::Execute()
+  {
+    Orthanc::HttpClient client(parameters_, uri_);
+    client.SetTimeout(timeoutInSeconds_);
+    client.SetMethod(Orthanc::HttpMethod_Delete);
+
+    for (IWebService::Headers::const_iterator it = headers_.begin(); it != headers_.end(); it++ )
+    {
+      client.AddHeader(it->first, it->second);
+    }
+
+    success_ = client.Apply(answer_);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/WebServiceDeleteCommand.h	Fri Oct 05 10:38:16 2018 +0200
@@ -0,0 +1,43 @@
+/**
+ * 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 <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "WebServiceCommandBase.h"
+
+namespace OrthancStone
+{
+  class WebServiceDeleteCommand : public WebServiceCommandBase
+  {
+  public:
+    WebServiceDeleteCommand(MessageBroker& broker,
+                            MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback,  // takes ownership
+                            MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback,  // takes ownership
+                            const Orthanc::WebServiceParameters& parameters,
+                            const std::string& uri,
+                            const IWebService::Headers& headers,
+                            unsigned int timeoutInSeconds,
+                            Orthanc::IDynamicObject* payload /* takes ownership */,
+                            NativeStoneApplicationContext& context);
+
+    virtual void Execute();
+  };
+}
--- a/Platforms/Wasm/WasmWebService.cpp	Wed Oct 03 17:14:17 2018 +0200
+++ b/Platforms/Wasm/WasmWebService.cpp	Fri Oct 05 10:38:16 2018 +0200
@@ -23,6 +23,12 @@
                                        void* payload,
                                        unsigned int timeoutInSeconds);
 
+  extern void WasmWebService_DeleteAsync(void* callableSuccess,
+                                         void* callableFailure,
+                                         const char* uri,
+                                         const char* headersInJsonString,
+                                         void* payload,
+                                         unsigned int timeoutInSeconds);
 
   void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifyError(void* failureCallable,
                                                        const char* uri,
@@ -116,7 +122,21 @@
                                        body.c_str(), body.size(), payload, timeoutInSeconds);
   }
 
-   void WasmWebService::GetAsync(const std::string& relativeUri,
+  void WasmWebService::DeleteAsync(const std::string& relativeUri,
+                                   const Headers& headers,
+                                   Orthanc::IDynamicObject* payload,
+                                   MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable,
+                                   MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable,
+                                   unsigned int timeoutInSeconds)
+  {
+    std::string uri = baseUri_ + relativeUri;
+    std::string headersInJsonString;
+    ToJsonString(headersInJsonString, headers);
+    WasmWebService_DeleteAsync(successCallable, failureCallable, uri.c_str(), headersInJsonString.c_str(),
+                               payload, timeoutInSeconds);
+  }
+
+  void WasmWebService::GetAsync(const std::string& relativeUri,
                                  const Headers& headers,
                                  Orthanc::IDynamicObject* payload,
                                  MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable,
--- a/Platforms/Wasm/WasmWebService.h	Wed Oct 03 17:14:17 2018 +0200
+++ b/Platforms/Wasm/WasmWebService.h	Fri Oct 05 10:38:16 2018 +0200
@@ -52,6 +52,13 @@
                            MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable = NULL,
                            unsigned int timeoutInSeconds = 60);
 
+    virtual void DeleteAsync(const std::string& uri,
+                             const Headers& headers,
+                             Orthanc::IDynamicObject* payload,
+                             MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable,
+                             MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable = NULL,
+                             unsigned int timeoutInSeconds = 60);
+
     virtual void Start()
     {
     }
--- a/Platforms/Wasm/WasmWebService.js	Wed Oct 03 17:14:17 2018 +0200
+++ b/Platforms/Wasm/WasmWebService.js	Fri Oct 05 10:38:16 2018 +0200
@@ -57,5 +57,34 @@
     }
 
     xhr.send(new Uint8ClampedArray(HEAPU8.buffer, body, bodySize));
+  },
+
+  WasmWebService_DeleteAsync: function(callableSuccess, callableFailure, url, headersInJsonString, payload, timeoutInSeconds) {
+    var xhr = new XMLHttpRequest();
+    var url_ = UTF8ToString(url);
+    var headersInJsonString_ = UTF8ToString(headersInJsonString);
+    xhr.open('DELETE', url_, true);
+    xhr.timeout = timeoutInSeconds * 1000;
+    xhr.responseType = 'arraybuffer';
+    xhr.setRequestHeader('Content-type', 'application/octet-stream');
+  
+    var headers = JSON.parse(headersInJsonString_);
+    for (var key in headers) {
+      xhr.setRequestHeader(key, headers[key]);
+    }
+    
+    xhr.onreadystatechange = function() {
+      if (this.readyState == XMLHttpRequest.DONE) {
+        if (xhr.status === 200) {
+          WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response),
+                                       this.response.byteLength, payload);
+        } else {
+          WasmWebService_NotifyError(callableFailure, url_, payload);
+        }
+      }
+    }
+  
+    xhr.send();
   }
+  
 });
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Wed Oct 03 17:14:17 2018 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Fri Oct 05 10:38:16 2018 +0200
@@ -175,6 +175,7 @@
     ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceCommandBase.cpp
     ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceGetCommand.cpp
     ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServicePostCommand.cpp
+    ${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceDeleteCommand.cpp
     ${ORTHANC_STONE_ROOT}/Platforms/Generic/Oracle.cpp
     ${ORTHANC_STONE_ROOT}/Platforms/Generic/OracleWebService.h
     )