changeset 5025:afa427f65444

Added an Asynchronous mode to /modalities/../move
author Alain Mazy <am@osimis.io>
date Tue, 21 Jun 2022 10:55:45 +0200
parents 559b35d18ef7
children bafef43b6f37
files NEWS OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp OrthancFramework/Sources/Enumerations.cpp OrthancFramework/Sources/Enumerations.h OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp OrthancServer/Sources/ServerJobs/DicomMoveScuJob.h
diffstat 7 files changed, 67 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Jun 15 15:40:07 2022 +0200
+++ b/NEWS	Tue Jun 21 10:55:45 2022 +0200
@@ -17,6 +17,11 @@
   DicomControlUserConnection::SetupPresentationContexts()
 * Improved HttpClient error logging (add method + url)
 
+
+* Added an Asynchronous mode to /modalities/../move.
+
+
+
 Version 1.11.0 (2022-05-09)
 ===========================
 
--- a/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp	Wed Jun 15 15:40:07 2022 +0200
+++ b/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp	Tue Jun 21 10:55:45 2022 +0200
@@ -362,27 +362,7 @@
     DcmDataset* dataset = query->GetDcmtkObject().getDataset();
 
     const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel;
-    switch (level)
-    {
-      case ResourceType_Patient:
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "PATIENT");
-        break;
-
-      case ResourceType_Study:
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "STUDY");
-        break;
-
-      case ResourceType_Series:
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "SERIES");
-        break;
-
-      case ResourceType_Instance:
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "IMAGE");
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
+    DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, ResourceTypeToDicomQueryRetrieveLevel(level));
 
     // Figure out which of the accepted presentation contexts should be used
     int presID = ASC_findAcceptedPresentationContextID(&association_->GetDcmtkAssociation(), sopClass);
@@ -519,32 +499,26 @@
     DcmDataset* dataset = query->GetDcmtkObject().getDataset();
     assert(dataset != NULL);
 
-    const char* clevel = NULL;
+    const char* clevel = ResourceTypeToDicomQueryRetrieveLevel(level);
     const char* sopClass = NULL;
 
+    DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, clevel);
+
     switch (level)
     {
       case ResourceType_Patient:
-        clevel = "PATIENT";
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "PATIENT");
         sopClass = UID_FINDPatientRootQueryRetrieveInformationModel;
         break;
 
       case ResourceType_Study:
-        clevel = "STUDY";
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "STUDY");
         sopClass = UID_FINDStudyRootQueryRetrieveInformationModel;
         break;
 
       case ResourceType_Series:
-        clevel = "SERIES";
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "SERIES");
         sopClass = UID_FINDStudyRootQueryRetrieveInformationModel;
         break;
 
       case ResourceType_Instance:
-        clevel = "IMAGE";
-        DU_putStringDOElement(dataset, DCM_QueryRetrieveLevel, "IMAGE");
         sopClass = UID_FINDStudyRootQueryRetrieveInformationModel;
         break;
 
--- a/OrthancFramework/Sources/Enumerations.cpp	Wed Jun 15 15:40:07 2022 +0200
+++ b/OrthancFramework/Sources/Enumerations.cpp	Tue Jun 21 10:55:45 2022 +0200
@@ -1314,6 +1314,27 @@
     throw OrthancException(ErrorCode_ParameterOutOfRange);
   }
 
+  const char* ResourceTypeToDicomQueryRetrieveLevel(ResourceType type)
+  {
+    if (type == ResourceType_Patient)
+    {
+      return "PATIENT";
+    }
+    else if (type == ResourceType_Study)
+    {
+      return "STUDY";
+    }
+    else if (type == ResourceType_Series)
+    {
+      return "SERIES";
+    }
+    else if (type == ResourceType_Instance)
+    {
+      return "IMAGE";
+    }
+
+    throw OrthancException(ErrorCode_ParameterOutOfRange);
+  }
 
   ImageFormat StringToImageFormat(const char* format)
   {
--- a/OrthancFramework/Sources/Enumerations.h	Wed Jun 15 15:40:07 2022 +0200
+++ b/OrthancFramework/Sources/Enumerations.h	Tue Jun 21 10:55:45 2022 +0200
@@ -862,6 +862,9 @@
   bool IsResourceLevelAboveOrEqual(ResourceType level,
                                    ResourceType reference);
 
+ORTHANC_PUBLIC
+  const char* ResourceTypeToDicomQueryRetrieveLevel(ResourceType type);
+
   ORTHANC_PUBLIC
   DicomModule GetModule(ResourceType type);
 
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Wed Jun 15 15:40:07 2022 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Tue Jun 21 10:55:45 2022 +0200
@@ -1517,6 +1517,7 @@
   {
     if (call.IsDocumentation())
     {
+      OrthancRestApi::DocumentSubmitCommandsJob(call);
       call.GetDocumentation()
         .SetTag("Networking")
         .SetSummary("Trigger C-MOVE SCU")
@@ -1534,12 +1535,12 @@
                          "Target AET that will be used by the remote DICOM modality as a target for its C-STORE SCU "
                          "commands, defaults to `DicomAet` configuration option in order to do a simple query/retrieve", false)
         .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number,
-                         "Timeout for the C-STORE command, in seconds", false)
+                         "Timeout for the C-MOVE command, in seconds", false)
         .SetUriArgument("id", "Identifier of the modality of interest");
       return;
     }
 
-    const ServerContext& context = OrthancRestApi::GetContext(call);
+    ServerContext& context = OrthancRestApi::GetContext(call);
 
     Json::Value request;
 
@@ -1564,21 +1565,33 @@
     const RemoteModalityParameters source =
       MyGetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
 
-    DicomAssociationParameters params(localAet, source);
-    InjectAssociationTimeout(params, request);  // Handles KEY_TIMEOUT
+    std::unique_ptr<DicomMoveScuJob> job(new DicomMoveScuJob(context));
 
-    DicomControlUserConnection connection(params);
+    job->SetQueryFormat(DicomToJsonFormat_Short);
+    
+    // QueryAccessor query(call);
+    job->SetTargetAet(targetAet);
+    job->SetLocalAet(localAet);
+    job->SetRemoteModality(source);
+
+    if (request.isMember(KEY_TIMEOUT))
+    {
+      job->SetTimeout(SerializationToolbox::ReadUnsignedInteger(request, KEY_TIMEOUT));
+    }
 
     for (Json::Value::ArrayIndex i = 0; i < request[KEY_RESOURCES].size(); i++)
     {
       DicomMap resource;
       FromDcmtkBridge::FromJson(resource, request[KEY_RESOURCES][i], "Resources elements");
-      
-      connection.Move(targetAet, level, resource);
+
+      resource.SetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL, std::string(ResourceTypeToDicomQueryRetrieveLevel(level)), false);
+
+      job->AddQuery(resource);      
     }
 
-    // Move has succeeded
-    call.GetOutput().AnswerBuffer("{}", MimeType_Json);
+    OrthancRestApi::GetApi(call).SubmitCommandsJob
+      (call, job.release(), true /* synchronous by default */, request);
+    return;
   }
 
 
--- a/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp	Wed Jun 15 15:40:07 2022 +0200
+++ b/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp	Tue Jun 21 10:55:45 2022 +0200
@@ -107,7 +107,8 @@
     query.GetAnswer(query.GetSize() - 1).Remove(DICOM_TAG_SPECIFIC_CHARACTER_SET);
   }
 
-
+  // this method is used to implement the retrieve part of a Q&R 
+  // it keeps only the main dicom tags from the C-Find answer
   void DicomMoveScuJob::AddFindAnswer(const DicomMap& answer)
   {
     DicomMap item;
@@ -122,6 +123,13 @@
     AddCommand(new Command(*this, answer));
   }
 
+  // this method is used to implement a C-Move
+  // it keeps all tags from the C-Move query
+  void DicomMoveScuJob::AddQuery(const DicomMap& query)
+  {
+    AddToQuery(query_, query);
+    AddCommand(new Command(*this, query));
+  }
   
   void DicomMoveScuJob::AddFindAnswer(QueryRetrieveHandler& query,
                                       size_t i)
--- a/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.h	Wed Jun 15 15:40:07 2022 +0200
+++ b/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.h	Tue Jun 21 10:55:45 2022 +0200
@@ -51,7 +51,7 @@
   public:
     explicit DicomMoveScuJob(ServerContext& context) :
       context_(context),
-      query_(true /* this is for worklists */),
+      query_(false  /* this is not for worklists */),
       queryFormat_(DicomToJsonFormat_Short)
     {
     }
@@ -61,6 +61,8 @@
 
     void AddFindAnswer(const DicomMap& answer);
     
+    void AddQuery(const DicomMap& query);
+
     void AddFindAnswer(QueryRetrieveHandler& query,
                        size_t i);