changeset 484:b8ace6fc1d1f

preparation for handling Orthanc peers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 16 Jul 2013 12:51:27 +0200
parents 8c3573d28868
children bdbde1fbfab3
files NEWS OrthancExplorer/explorer.html OrthancExplorer/explorer.js OrthancServer/OrthancInitialization.cpp OrthancServer/OrthancInitialization.h OrthancServer/OrthancRestApi.cpp OrthancServer/OrthancRestApi.h Resources/Configuration.json
diffstat 8 files changed, 142 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Jul 16 12:01:39 2013 +0200
+++ b/NEWS	Tue Jul 16 12:51:27 2013 +0200
@@ -6,6 +6,7 @@
 -------------
 
 * Introduction of the C++ client
+* Send DICOM resources to other Orthanc instances through HTTP
 * Access to signed images (instances/.../image-int16)
   (Closes: Debian #716958)
 
@@ -13,6 +14,7 @@
 Minor changes
 -------------
 
+* Export of DICOM files to the host filesystem (instances/.../export)
 * Statistics about patients, studies, series and instances
 * Link from anonymized to original resource in Orthanc Explorer
 * Fixes for Red Hat and Debian packaging
--- a/OrthancExplorer/explorer.html	Tue Jul 16 12:01:39 2013 +0200
+++ b/OrthancExplorer/explorer.html	Tue Jul 16 12:51:27 2013 +0200
@@ -92,7 +92,7 @@
               <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c">
                 <li data-role="list-divider">Interact</li>
                 <li data-icon="delete"><a href="#" id="patient-delete">Delete this patient</a></li>
-                <li data-icon="forward"><a href="#" id="patient-store">Send to DICOM modality</a></li>
+                <li data-icon="forward"><a href="#" id="patient-store">Send to remote modality</a></li>
                 <li data-icon="star"><a href="#" id="patient-anonymize">Anonymize</a></li>
               </ul>
 
--- a/OrthancExplorer/explorer.js	Tue Jul 16 12:01:39 2013 +0200
+++ b/OrthancExplorer/explorer.js	Tue Jul 16 12:51:27 2013 +0200
@@ -792,8 +792,11 @@
     success: function(modalities) {
       var clickedModality = '';
       var items = $('<ul>')
+        .attr('data-divider-theme', 'd')
         .attr('data-role', 'listview');
 
+      items.append('<li data-role="list-divider">DICOM modalities</li>');
+
       for (var i = 0; i < modalities.length; i++) {
         var modality = modalities[i];
         var item = $('<li>')
@@ -805,10 +808,13 @@
         items.append(item);
       }
 
+      items.append('<li data-role="list-divider">Orthanc peers</li>');
+
+
       $('#dialog').simpledialog2({
         mode: 'blank',
         animate: false,
-        headerText: 'DICOM modality',
+        headerText: 'Choose target',
         headerClose: true,
         width: '100%',
         blankContent: items,
--- a/OrthancServer/OrthancInitialization.cpp	Tue Jul 16 12:01:39 2013 +0200
+++ b/OrthancServer/OrthancInitialization.cpp	Tue Jul 16 12:51:27 2013 +0200
@@ -260,36 +260,93 @@
 
 
 
-  void GetListOfDicomModalities(std::set<std::string>& target)
+  void GetOrthancPeer(const std::string& name,
+                      std::string& url,
+                      std::string& username,
+                      std::string& password)
+  {
+    boost::mutex::scoped_lock lock(globalMutex_);
+
+    if (!configuration_->isMember("OrthancPeers"))
+    {
+      throw OrthancException("");
+    }
+
+    const Json::Value& modalities = (*configuration_) ["OrthancPeers"];
+    if (modalities.type() != Json::objectValue ||
+        !modalities.isMember(name))
+    {
+      throw OrthancException("");
+    }
+
+    try
+    {
+      url = modalities[name].get(0u, "").asString();
+      username = modalities[name].get(1u, "").asString();
+      password = modalities[name].get(2u, "").asString();
+    }
+    catch (...)
+    {
+      throw OrthancException("Badly formatted Orthanc peer");
+    }
+  }
+
+
+  static bool ReadKeys(std::set<std::string>& target,
+                       const char* parameter,
+                       bool onlyAlphanumeric)
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
     target.clear();
   
-    if (!configuration_->isMember("DicomModalities"))
+    if (!configuration_->isMember(parameter))
     {
-      return;
+      return true;
     }
 
-    const Json::Value& modalities = (*configuration_) ["DicomModalities"];
+    const Json::Value& modalities = (*configuration_) [parameter];
     if (modalities.type() != Json::objectValue)
     {
-      throw OrthancException("Badly formatted list of DICOM modalities");
+      throw OrthancException(ErrorCode_BadFileFormat);
     }
 
     Json::Value::Members members = modalities.getMemberNames();
     for (size_t i = 0; i < members.size(); i++)
     {
-      for (size_t j = 0; j < members[i].size(); j++)
+      if (onlyAlphanumeric)
       {
-        if (!isalnum(members[i][j]) && members[i][j] != '-')
+        for (size_t j = 0; j < members[i].size(); j++)
         {
-          throw OrthancException("Only alphanumeric and dash characters are allowed in the names of the modalities");
+          if (!isalnum(members[i][j]) && members[i][j] != '-')
+          {
+            return false;
+          }
         }
       }
 
       target.insert(members[i]);
     }
+
+    return true;
+  }
+
+
+  void GetListOfDicomModalities(std::set<std::string>& target)
+  {
+    if (!ReadKeys(target, "DicomModalities", true))
+    {
+      throw OrthancException("Only alphanumeric and dash characters are allowed in the names of the modalities");
+    }
+  }
+
+
+  void GetListOfOrthancPeers(std::set<std::string>& target)
+  {
+    if (!ReadKeys(target, "OrthancPeers", true))
+    {
+      throw OrthancException("Only alphanumeric and dash characters are allowed in the names of Orthanc peers");
+    }
   }
 
 
--- a/OrthancServer/OrthancInitialization.h	Tue Jul 16 12:01:39 2013 +0200
+++ b/OrthancServer/OrthancInitialization.h	Tue Jul 16 12:51:27 2013 +0200
@@ -58,8 +58,15 @@
                         std::string& address,
                         int& port);
 
+  void GetOrthancPeer(const std::string& name,
+                      std::string& url,
+                      std::string& username,
+                      std::string& password);
+
   void GetListOfDicomModalities(std::set<std::string>& target);
 
+  void GetListOfOrthancPeers(std::set<std::string>& target);
+
   void SetupRegisteredUsers(MongooseServer& httpServer);
 
   std::string InterpretRelativePath(const std::string& baseDirectory,
--- a/OrthancServer/OrthancRestApi.cpp	Tue Jul 16 12:01:39 2013 +0200
+++ b/OrthancServer/OrthancRestApi.cpp	Tue Jul 16 12:51:27 2013 +0200
@@ -52,9 +52,13 @@
   ServerContext& context = contextApi.GetContext()
 
 #define RETRIEVE_MODALITIES(call)                                       \
-  const OrthancRestApi::Modalities& modalities =                        \
+  const OrthancRestApi::SetOfStrings& modalities =                      \
     dynamic_cast<OrthancRestApi&>(call.GetContext()).GetModalities();
 
+#define RETRIEVE_PEERS(call)                                            \
+  const OrthancRestApi::SetOfStrings& peers =                           \
+    dynamic_cast<OrthancRestApi&>(call.GetContext()).GetPeers();
+
 
 
 namespace Orthanc
@@ -881,7 +885,7 @@
 
   // DICOM bridge -------------------------------------------------------------
 
-  static bool IsExistingModality(const OrthancRestApi::Modalities& modalities,
+  static bool IsExistingModality(const OrthancRestApi::SetOfStrings& modalities,
                                  const std::string& id)
   {
     return modalities.find(id) != modalities.end();
@@ -892,7 +896,7 @@
     RETRIEVE_MODALITIES(call);
 
     Json::Value result = Json::arrayValue;
-    for (OrthancRestApi::Modalities::const_iterator 
+    for (OrthancRestApi::SetOfStrings::const_iterator 
            it = modalities.begin(); it != modalities.end(); it++)
     {
       result.append(*it);
@@ -1610,12 +1614,51 @@
 
 
 
+  // Orthanc Peers ------------------------------------------------------------
+
+  static bool IsExistingPeer(const OrthancRestApi::SetOfStrings& peers,
+                             const std::string& id)
+  {
+    return peers.find(id) != peers.end();
+  }
+
+  static void ListPeers(RestApi::GetCall& call)
+  {
+    RETRIEVE_PEERS(call);
+
+    Json::Value result = Json::arrayValue;
+    for (OrthancRestApi::SetOfStrings::const_iterator 
+           it = peers.begin(); it != peers.end(); it++)
+    {
+      result.append(*it);
+    }
+
+    call.GetOutput().AnswerJson(result);
+  }
+
+  static void ListPeerOperations(RestApi::GetCall& call)
+  {
+    RETRIEVE_PEERS(call);
+
+    std::string id = call.GetUriComponent("id", "");
+    if (IsExistingPeer(peers, id))
+    {
+      Json::Value result = Json::arrayValue;
+      result.append("store");
+      call.GetOutput().AnswerJson(result);
+    }
+  }
+
+
+
+
   // Registration of the various REST handlers --------------------------------
 
   OrthancRestApi::OrthancRestApi(ServerContext& context) : 
     context_(context)
   {
     GetListOfDicomModalities(modalities_);
+    GetListOfOrthancPeers(peers_);
 
     Register("/", ServeRoot);
     Register("/system", GetSystemInformation);
@@ -1692,6 +1735,9 @@
     Register("/modalities/{id}/find", DicomFind);
     Register("/modalities/{id}/store", DicomStore);
 
+    Register("/peers", ListPeers);
+    Register("/peers/{id}", ListPeerOperations);
+
     Register("/instances/{id}/modify", ModifyInstance);
     Register("/series/{id}/modify", ModifySeriesInplace);
     Register("/studies/{id}/modify", ModifyStudyInplace);
--- a/OrthancServer/OrthancRestApi.h	Tue Jul 16 12:01:39 2013 +0200
+++ b/OrthancServer/OrthancRestApi.h	Tue Jul 16 12:51:27 2013 +0200
@@ -42,11 +42,12 @@
   class OrthancRestApi : public RestApi
   {
   public:
-    typedef std::set<std::string> Modalities;
+    typedef std::set<std::string> SetOfStrings;
 
   private:
     ServerContext& context_;
-    Modalities modalities_;
+    SetOfStrings modalities_;
+    SetOfStrings peers_;
 
   public:
     OrthancRestApi(ServerContext& context);
@@ -56,9 +57,14 @@
       return context_;
     }
 
-    Modalities& GetModalities()
+    SetOfStrings& GetModalities()
     {
       return modalities_;
     }
+
+    SetOfStrings& GetPeers()
+    {
+      return peers_;
+    }
   };
 }
--- a/Resources/Configuration.json	Tue Jul 16 12:01:39 2013 +0200
+++ b/Resources/Configuration.json	Tue Jul 16 12:51:27 2013 +0200
@@ -105,7 +105,8 @@
     // "sample" : [ "STORESCP", "localhost", 2000 ]
   },
 
-  // The list of the known Orthanc peers (currently unused)
+  // The list of the known Orthanc peers
   "OrthancPeers" : {
+    // "peer" : [ "http://localhost:8043/", "alice", "alicePassword" ]
   }
 }