changeset 1801:2c60c357ee3e worklists

sdk primitives to handle worklists
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 20 Nov 2015 14:33:41 +0100
parents 30e97a1f4093
children 138664eb59de
files Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/OrthancPlugins.h Plugins/Include/orthanc/OrthancCPlugin.h
diffstat 3 files changed, 223 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Engine/OrthancPlugins.cpp	Fri Nov 20 13:53:20 2015 +0100
+++ b/Plugins/Engine/OrthancPlugins.cpp	Fri Nov 20 14:33:41 2015 +0100
@@ -47,6 +47,7 @@
 #include "../../OrthancServer/OrthancInitialization.h"
 #include "../../OrthancServer/ServerContext.h"
 #include "../../OrthancServer/ServerToolbox.h"
+#include "../../OrthancServer/Search/HierarchicalMatcher.h"
 #include "../../Core/Compression/ZlibCompressor.h"
 #include "../../Core/Compression/GzipCompressor.h"
 #include "../../Core/Images/Image.h"
@@ -61,6 +62,46 @@
 
 namespace Orthanc
 {
+  static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target,
+                                 const void* data,
+                                 size_t size)
+  {
+    target.size = size;
+
+    if (size == 0)
+    {
+      target.data = NULL;
+    }
+    else
+    {
+      target.data = malloc(size);
+      if (target.data != NULL)
+      {
+        memcpy(target.data, data, size);
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_NotEnoughMemory);
+      }
+    }
+  }
+
+
+  static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target,
+                                 const std::string& str)
+  {
+    if (str.size() == 0)
+    {
+      target.size = 0;
+      target.data = NULL;
+    }
+    else
+    {
+      CopyToMemoryBuffer(target, str.c_str(), str.size());
+    }
+  }
+
+
   namespace
   {
     class PluginStorageArea : public IStorageArea
@@ -268,6 +309,78 @@
 
 
   
+  class OrthancPlugins::WorklistHandler : public IWorklistRequestHandler
+  {
+  private:
+    OrthancPlugins&  that_;
+    std::auto_ptr<HierarchicalMatcher> matcher_;
+    ParsedDicomFile* currentQuery_;
+
+    void Reset()
+    {
+      matcher_.reset(NULL);
+      currentQuery_ = NULL;
+    }
+
+  public:
+    WorklistHandler(OrthancPlugins& that) : that_(that)
+    {
+      Reset();
+    }
+
+    virtual void Handle(DicomFindAnswers& answers,
+                        ParsedDicomFile& query,
+                        const std::string& remoteIp,
+                        const std::string& remoteAet,
+                        const std::string& calledAet)
+    {
+      bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false);
+      matcher_.reset(new HierarchicalMatcher(query, caseSensitivePN));
+      currentQuery_ = &query;
+
+      {
+        boost::recursive_mutex::scoped_lock lock(that_.pimpl_->worklistCallbackMutex_);
+
+        for (PImpl::WorklistCallbacks::const_iterator
+               callback = that_.pimpl_->worklistCallbacks_.begin(); 
+             callback != that_.pimpl_->worklistCallbacks_.end(); ++callback)
+        {
+          OrthancPluginErrorCode error = (*callback) 
+            (reinterpret_cast<OrthancPluginWorklistAnswers*>(&answers),
+             reinterpret_cast<const OrthancPluginWorklistQuery*>(this),
+             remoteAet.c_str(),
+             calledAet.c_str());
+
+          if (error != OrthancPluginErrorCode_Success)
+          {
+            Reset();
+            that_.GetErrorDictionary().LogError(error, true);
+            throw OrthancException(static_cast<ErrorCode>(error));
+          }
+        }
+      }
+
+      Reset();
+    }
+
+    bool IsMatch(const void* dicom,
+                 size_t size) const
+    {
+      assert(matcher_.get() != NULL);
+      ParsedDicomFile f(dicom, size);
+      return matcher_->Match(f);
+    }
+
+    void GetQueryDicom(OrthancPluginMemoryBuffer& target) const
+    {
+      assert(currentQuery_ != NULL);
+      std::string dicom;
+      currentQuery_->SaveToMemoryBuffer(dicom);
+      CopyToMemoryBuffer(target, dicom.c_str(), dicom.size());
+    }
+  };
+
+  
   static char* CopyString(const std::string& str)
   {
     char *result = reinterpret_cast<char*>(malloc(str.size() + 1));
@@ -549,46 +662,6 @@
 
 
 
-  static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target,
-                                 const void* data,
-                                 size_t size)
-  {
-    target.size = size;
-
-    if (size == 0)
-    {
-      target.data = NULL;
-    }
-    else
-    {
-      target.data = malloc(size);
-      if (target.data != NULL)
-      {
-        memcpy(target.data, data, size);
-      }
-      else
-      {
-        throw OrthancException(ErrorCode_NotEnoughMemory);
-      }
-    }
-  }
-
-
-  static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target,
-                                 const std::string& str)
-  {
-    if (str.size() == 0)
-    {
-      target.size = 0;
-      target.data = NULL;
-    }
-    else
-    {
-      CopyToMemoryBuffer(target, str.c_str(), str.size());
-    }
-  }
-
-
   void OrthancPlugins::RegisterRestCallback(const void* parameters,
                                             bool lock)
   {
@@ -1851,11 +1924,36 @@
 
       case _OrthancPluginService_AddWorklistAnswer:
       {
-        const _OrthancPluginAddWorklistAnswer& p =
-          *reinterpret_cast<const _OrthancPluginAddWorklistAnswer*>(parameters);
+        const _OrthancPluginWorklistAnswersOperation& p =
+          *reinterpret_cast<const _OrthancPluginWorklistAnswersOperation*>(parameters);
         
-        ParsedDicomFile answer(p.answerDicom, p.answerSize);
-        reinterpret_cast<DicomFindAnswers*>(p.target)->Add(answer);
+        ParsedDicomFile answer(p.dicom, p.size);
+        reinterpret_cast<DicomFindAnswers*>(p.answers)->Add(answer);
+        return true;
+      }
+
+      case _OrthancPluginService_MarkWorklistAnswersIncomplete:
+      {
+        const _OrthancPluginWorklistAnswersOperation& p =
+          *reinterpret_cast<const _OrthancPluginWorklistAnswersOperation*>(parameters);
+
+        reinterpret_cast<DicomFindAnswers*>(p.answers)->SetComplete(false);
+        return true;
+      }
+
+      case _OrthancPluginService_IsWorklistMatch:
+      {
+        const _OrthancPluginWorklistQueryOperation& p =
+          *reinterpret_cast<const _OrthancPluginWorklistQueryOperation*>(parameters);
+        *p.isMatch = reinterpret_cast<const WorklistHandler*>(p.query)->IsMatch(p.dicom, p.size);
+        return true;
+      }
+
+      case _OrthancPluginService_GetWorklistQueryDicom:
+      {
+        const _OrthancPluginWorklistQueryOperation& p =
+          *reinterpret_cast<const _OrthancPluginWorklistQueryOperation*>(parameters);
+        reinterpret_cast<const WorklistHandler*>(p.query)->GetQueryDicom(*p.target);
         return true;
       }
 
@@ -1978,54 +2076,6 @@
   }
 
 
-  void OrthancPlugins::HandleWorklist(DicomFindAnswers& answers,
-                                      ParsedDicomFile& query,
-                                      const std::string& remoteIp,
-                                      const std::string& remoteAet,
-                                      const std::string& calledAet)
-  {
-    boost::recursive_mutex::scoped_lock lock(pimpl_->worklistCallbackMutex_);
-
-    for (PImpl::WorklistCallbacks::const_iterator
-           callback = pimpl_->worklistCallbacks_.begin(); 
-         callback != pimpl_->worklistCallbacks_.end(); ++callback)
-    {
-      OrthancPluginErrorCode error = (*callback) 
-        (reinterpret_cast<OrthancPluginWorklistAnswers*>(&answers),
-         reinterpret_cast<OrthancPluginWorklistQuery*>(&query),
-         remoteAet.c_str(),
-         calledAet.c_str());
-
-      if (error != OrthancPluginErrorCode_Success)
-      {
-        GetErrorDictionary().LogError(error, true);
-        throw OrthancException(static_cast<ErrorCode>(error));
-      }
-    }
-  }
-
-
-  class OrthancPlugins::WorklistHandler : public IWorklistRequestHandler
-  {
-  private:
-    OrthancPlugins&  plugins_;
-
-  public:
-    WorklistHandler(OrthancPlugins& plugins) : plugins_(plugins)
-    {
-    }
-
-    virtual void Handle(DicomFindAnswers& answers,
-                        ParsedDicomFile& query,
-                        const std::string& remoteIp,
-                        const std::string& remoteAet,
-                        const std::string& calledAet)
-    {
-      plugins_.HandleWorklist(answers, query, remoteIp, remoteAet, calledAet);
-    }
-  };
-
-  
   IWorklistRequestHandler* OrthancPlugins::ConstructWorklistRequestHandler()
   {
     bool hasHandler;
--- a/Plugins/Engine/OrthancPlugins.h	Fri Nov 20 13:53:20 2015 +0100
+++ b/Plugins/Engine/OrthancPlugins.h	Fri Nov 20 14:33:41 2015 +0100
@@ -144,12 +144,6 @@
                               OrthancPluginResourceType resourceType,
                               const char* resource);
 
-    void HandleWorklist(DicomFindAnswers& answers,
-                        ParsedDicomFile& query,
-                        const std::string& remoteIp,
-                        const std::string& remoteAet,
-                        const std::string& calledAet);
-
   public:
     OrthancPlugins();
 
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Nov 20 13:53:20 2015 +0100
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Nov 20 14:33:41 2015 +0100
@@ -469,6 +469,9 @@
 
     /* Primitives for handling worklists */
     _OrthancPluginService_AddWorklistAnswer = 7000,
+    _OrthancPluginService_MarkWorklistAnswersIncomplete = 7001,
+    _OrthancPluginService_IsWorklistMatch = 7002,
+    _OrthancPluginService_GetWorklistQueryDicom = 7003,
 
     _OrthancPluginService_INTERNAL = 0x7fffffff
   } _OrthancPluginService;
@@ -4100,27 +4103,91 @@
   
   typedef struct
   {
-    OrthancPluginWorklistAnswers*  target;
-    const void*                    answerDicom;
-    uint32_t                       answerSize;
-  } _OrthancPluginAddWorklistAnswer;
-
-
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginAddWorklistAnswer(
+    OrthancPluginWorklistAnswers*  answers;
+    const void*                    dicom;
+    uint32_t                       size;
+  } _OrthancPluginWorklistAnswersOperation;
+
+  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistAnswersOperation(
     OrthancPluginContext*          context,
-    OrthancPluginWorklistAnswers*  target,
-    const void*                    answerDicom,
-    uint32_t                       answerSize)
+    OrthancPluginWorklistAnswers*  answers,
+    const void*                    dicom,
+    uint32_t                       size)
   {
-    _OrthancPluginAddWorklistAnswer params;
-    params.target = target;
-    params.answerDicom = answerDicom;
-    params.answerSize = answerSize;
+    _OrthancPluginWorklistAnswersOperation params;
+    params.answers = answers;
+    params.dicom = dicom;
+    params.size = size;
 
     return context->InvokeService(context, _OrthancPluginService_AddWorklistAnswer, &params);
   }
 
 
+  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginMarkWorklistAnswersIncomplete(
+    OrthancPluginContext*          context,
+    OrthancPluginWorklistAnswers*  answers)
+  {
+    _OrthancPluginWorklistAnswersOperation params;
+    params.answers = answers;
+    params.dicom = NULL;
+    params.size = 0;
+
+    return context->InvokeService(context, _OrthancPluginService_MarkWorklistAnswersIncomplete, &params);
+  }
+
+
+  typedef struct
+  {
+    const OrthancPluginWorklistQuery*  query;
+    const void*                        dicom;
+    uint32_t                           size;
+    int32_t*                           isMatch;
+    OrthancPluginMemoryBuffer*         target;
+  } _OrthancPluginWorklistQueryOperation;
+
+  ORTHANC_PLUGIN_INLINE int32_t  OrthancPluginIsWorklistMatch(
+    OrthancPluginContext*              context,
+    const OrthancPluginWorklistQuery*  query,
+    const void*                        dicom,
+    uint32_t                           size)
+  {
+    int32_t isMatch = 0;
+
+    _OrthancPluginWorklistQueryOperation params;
+    params.query = query;
+    params.dicom = dicom;
+    params.size = size;
+    params.isMatch = &isMatch;
+    params.target = NULL;
+
+    if (context->InvokeService(context, _OrthancPluginService_IsWorklistMatch, &params) == OrthancPluginErrorCode_Success)
+    {
+      return isMatch;
+    }
+    else
+    {
+      /* Error: Assume non-match */
+      return 0;
+    }
+  }
+
+
+  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginGetWorklistQueryDicom(
+    OrthancPluginContext*              context,
+    OrthancPluginMemoryBuffer*         target,
+    const OrthancPluginWorklistQuery*  query)
+  {
+    _OrthancPluginWorklistQueryOperation params;
+    params.query = query;
+    params.dicom = NULL;
+    params.size = 0;
+    params.isMatch = NULL;
+    params.target = target;
+
+    return context->InvokeService(context, _OrthancPluginService_GetWorklistQueryDicom, &params);
+  }
+
+
 #ifdef  __cplusplus
 }
 #endif