changeset 982:3f6e5a38c88f toa2019090601

Merge
author Benjamin Golinvaux <bgo@osimis.io>
date Fri, 06 Sep 2019 09:39:18 +0200
parents c20dbaab360c (current diff) 8e497a4e3d96 (diff)
children d5868250d10f
files Framework/Messages/ICallable.h
diffstat 10 files changed, 294 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Sep 06 09:38:18 2019 +0200
+++ b/.hgignore	Fri Sep 06 09:39:18 2019 +0200
@@ -38,3 +38,5 @@
 Samples/WebAssembly/build/
 Samples/WebAssembly/ThirdPartyDownloads/
 Samples/WebAssembly/installDir/
+
+node_modules/
--- a/Framework/Messages/ICallable.h	Fri Sep 06 09:38:18 2019 +0200
+++ b/Framework/Messages/ICallable.h	Fri Sep 06 09:39:18 2019 +0200
@@ -71,8 +71,8 @@
     Callable(TObserver& observer,
              MemberFunction function) :
       observer_(observer),
-      observerFingerprint_(observer.GetFingerprint()),
-      function_(function)
+      function_(function),
+      observerFingerprint_(observer.GetFingerprint())
     {
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Oracle/HttpCommand.cpp	Fri Sep 06 09:39:18 2019 +0200
@@ -0,0 +1,79 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 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 "HttpCommand.h"
+
+#include <Core/OrthancException.h>
+
+#include <json/reader.h>
+#include <json/writer.h>
+
+namespace OrthancStone
+{
+  HttpCommand::SuccessMessage::SuccessMessage(const HttpCommand& command,
+                                              const HttpHeaders& answerHeaders,
+                                              std::string& answer) :
+    OriginMessage(command),
+    headers_(answerHeaders),
+    answer_(answer)
+  {
+  }
+
+
+  void HttpCommand::SuccessMessage::ParseJsonBody(Json::Value& target) const
+  {
+    Json::Reader reader;
+    if (!reader.parse(answer_, target))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+  }
+
+
+  HttpCommand::HttpCommand() :
+    method_(Orthanc::HttpMethod_Get),
+    url_("/"),
+    timeout_(600)
+  {
+  }
+
+
+  void HttpCommand::SetBody(const Json::Value& json)
+  {
+    Json::FastWriter writer;
+    body_ = writer.write(json);
+  }
+
+
+  const std::string& HttpCommand::GetBody() const
+  {
+    if (method_ == Orthanc::HttpMethod_Post ||
+        method_ == Orthanc::HttpMethod_Put)
+    {
+      return body_;
+    }
+    else
+    {
+      LOG(ERROR) << "HttpCommand::GetBody(): method_  not _Post or _Put";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Oracle/HttpCommand.h	Fri Sep 06 09:39:18 2019 +0200
@@ -0,0 +1,141 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 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 "../Messages/IMessage.h"
+#include "OracleCommandWithPayload.h"
+
+#include <Core/Enumerations.h>
+
+#include <map>
+#include <json/value.h>
+
+namespace OrthancStone
+{
+  class HttpCommand : public OracleCommandWithPayload
+  {
+  public:
+    typedef std::map<std::string, std::string>  HttpHeaders;
+
+    class SuccessMessage : public OriginMessage<HttpCommand>
+    {
+      ORTHANC_STONE_MESSAGE(__FILE__, __LINE__);
+      
+    private:
+      HttpHeaders   headers_;
+      std::string   answer_;
+
+    public:
+      SuccessMessage(const HttpCommand& command,
+                     const HttpHeaders& answerHeaders,
+                     std::string& answer  /* will be swapped to avoid a memcpy() */);
+
+      const std::string& GetAnswer() const
+      {
+        return answer_;
+      }
+
+      void ParseJsonBody(Json::Value& target) const;
+
+      const HttpHeaders&  GetAnswerHeaders() const
+      {
+        return headers_;
+      }
+    };
+
+
+  private:
+    Orthanc::HttpMethod  method_;
+    std::string          url_;
+    std::string          body_;
+    HttpHeaders          headers_;
+    unsigned int         timeout_;
+
+  public:
+    HttpCommand();
+
+    virtual Type GetType() const
+    {
+      return Type_Http;
+    }
+
+    void SetMethod(Orthanc::HttpMethod method)
+    {
+      method_ = method;
+    }
+
+    void SetUrl(const std::string& url)
+    {
+      url_ = url;
+    }
+
+    void SetBody(const std::string& body)
+    {
+      body_ = body;
+    }
+
+    void SetBody(const Json::Value& json);
+
+    void SwapBody(std::string& body)
+    {
+      body_.swap(body);
+    }
+
+    void SetHttpHeaders(const HttpHeaders& headers)
+    {
+      headers_ = headers;
+    }
+
+    void SetHttpHeader(const std::string& key,
+                       const std::string& value)
+    {
+      headers_[key] = value;
+    }
+
+    Orthanc::HttpMethod GetMethod() const
+    {
+      return method_;
+    }
+
+    const std::string& GetUrl() const
+    {
+      return url_;
+    }
+
+    const std::string& GetBody() const;
+
+    const HttpHeaders& GetHttpHeaders() const
+    {
+      return headers_;
+    }
+
+    void SetTimeout(unsigned int seconds)
+    {
+      timeout_ = seconds;
+    }
+
+    unsigned int GetTimeout() const
+    {
+      return timeout_;
+    }
+  };
+}
--- a/Framework/Oracle/IOracleCommand.h	Fri Sep 06 09:38:18 2019 +0200
+++ b/Framework/Oracle/IOracleCommand.h	Fri Sep 06 09:39:18 2019 +0200
@@ -30,6 +30,7 @@
   public:
     enum Type
     {
+      Type_Http,
       Type_Sleep,
       Type_OrthancRestApi,
       Type_GetOrthancImage,
--- a/Framework/Oracle/OrthancRestApiCommand.h	Fri Sep 06 09:38:18 2019 +0200
+++ b/Framework/Oracle/OrthancRestApiCommand.h	Fri Sep 06 09:39:18 2019 +0200
@@ -100,6 +100,11 @@
       body_.swap(body);
     }
 
+    void SetHttpHeaders(const HttpHeaders& headers)
+    {
+      headers_ = headers;
+    }
+
     void SetHttpHeader(const std::string& key,
                        const std::string& value)
     {
--- a/Framework/Oracle/ThreadedOracle.cpp	Fri Sep 06 09:38:18 2019 +0200
+++ b/Framework/Oracle/ThreadedOracle.cpp	Fri Sep 06 09:39:18 2019 +0200
@@ -23,6 +23,7 @@
 
 #include "GetOrthancImageCommand.h"
 #include "GetOrthancWebViewerJpegCommand.h"
+#include "HttpCommand.h"
 #include "OrthancRestApiCommand.h"
 #include "SleepOracleCommand.h"
 #include "OracleCommandExceptionMessage.h"
@@ -212,6 +213,34 @@
 
 
   static void Execute(IMessageEmitter& emitter,
+                      const IObserver& receiver,
+                      const HttpCommand& command)
+  {
+    Orthanc::HttpClient client;
+    client.SetUrl(command.GetUrl());
+    client.SetMethod(command.GetMethod());
+    client.SetTimeout(command.GetTimeout());
+
+    CopyHttpHeaders(client, command.GetHttpHeaders());
+
+    if (command.GetMethod() == Orthanc::HttpMethod_Post ||
+        command.GetMethod() == Orthanc::HttpMethod_Put)
+    {
+      client.SetBody(command.GetBody());
+    }
+
+    std::string answer;
+    Orthanc::HttpClient::HttpHeaders answerHeaders;
+    client.ApplyAndThrowException(answer, answerHeaders);
+
+    DecodeAnswer(answer, answerHeaders);
+
+    HttpCommand::SuccessMessage message(command, answerHeaders, answer);
+    emitter.EmitMessage(receiver, message);
+  }
+
+
+  static void Execute(IMessageEmitter& emitter,
                       const Orthanc::WebServiceParameters& orthanc,
                       const IObserver& receiver,
                       const OrthancRestApiCommand& command)
@@ -307,6 +336,11 @@
             break;
           }
 
+          case IOracleCommand::Type_Http:
+            Execute(emitter_, item.GetReceiver(), 
+                    dynamic_cast<const HttpCommand&>(item.GetCommand()));
+            break;
+
           case IOracleCommand::Type_OrthancRestApi:
             Execute(emitter_, orthanc_, item.GetReceiver(), 
                     dynamic_cast<const OrthancRestApiCommand&>(item.GetCommand()));
--- a/Framework/Toolbox/DicomInstanceParameters.cpp	Fri Sep 06 09:38:18 2019 +0200
+++ b/Framework/Toolbox/DicomInstanceParameters.cpp	Fri Sep 06 09:39:18 2019 +0200
@@ -176,6 +176,12 @@
     {
       expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16;
     }
+
+    // This computes the "IndexInSeries" metadata from Orthanc (check
+    // out "Orthanc::ServerIndex::Store()")
+    hasIndexInSeries_ = (
+      dicom.ParseUnsignedInteger32(indexInSeries_, Orthanc::DICOM_TAG_INSTANCE_NUMBER) ||
+      dicom.ParseUnsignedInteger32(indexInSeries_, Orthanc::DICOM_TAG_IMAGE_INDEX));
   }
 
 
@@ -398,4 +404,18 @@
       return new LookupTableTextureSceneLayer(*converted);
     }
   }
+
+  
+  unsigned int DicomInstanceParameters::GetIndexInSeries() const
+  {
+    if (data_.hasIndexInSeries_)
+    {
+      return data_.indexInSeries_;
+    }
+    else
+    {
+      LOG(ERROR) << "DicomInstanceParameters::GetIndexInSeries(): !data_.hasIndexInSeries_";
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+  }
 }
--- a/Framework/Toolbox/DicomInstanceParameters.h	Fri Sep 06 09:38:18 2019 +0200
+++ b/Framework/Toolbox/DicomInstanceParameters.h	Fri Sep 06 09:39:18 2019 +0200
@@ -57,6 +57,8 @@
       float                             defaultWindowingCenter_;
       float                             defaultWindowingWidth_;
       Orthanc::PixelFormat              expectedPixelFormat_;
+      bool                              hasIndexInSeries_;
+      unsigned int                      indexInSeries_;
 
       void ComputeDoseOffsets(const Orthanc::DicomMap& dicom);
 
@@ -191,5 +193,12 @@
     TextureBaseSceneLayer* CreateTexture(const Orthanc::ImageAccessor& pixelData) const;
 
     LookupTableTextureSceneLayer* CreateLookupTableTexture(const Orthanc::ImageAccessor& pixelData) const;
+
+    bool HasIndexInSeries() const
+    {
+      return data_.hasIndexInSeries_;
+    }
+
+    unsigned int GetIndexInSeries() const;
   };
 }
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Fri Sep 06 09:38:18 2019 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Fri Sep 06 09:39:18 2019 +0200
@@ -442,6 +442,7 @@
   ${ORTHANC_STONE_ROOT}/Framework/Oracle/GetOrthancWebViewerJpegCommand.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Oracle/OracleCommandWithPayload.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Oracle/OrthancRestApiCommand.cpp
+  ${ORTHANC_STONE_ROOT}/Framework/Oracle/HttpCommand.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Scene2D/CairoCompositor.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ColorTextureSceneLayer.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Scene2D/FloatTextureSceneLayer.cpp