changeset 31:9aace933cb64

sharing code with the Orthanc core
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 16 Dec 2016 15:41:20 +0100
parents 1099a148f7e5
children 517c46f527cd
files Framework/Applications/BasicApplicationContext.cpp Framework/Applications/BasicApplicationContext.h Framework/Applications/IBasicApplication.cpp Framework/Layers/SingleFrameRendererFactory.cpp Framework/Layers/SingleFrameRendererFactory.h Framework/Messaging/CurlOrthancConnection.cpp Framework/Messaging/CurlOrthancConnection.h Framework/Messaging/IOrthancConnection.h Framework/Messaging/MessagingToolbox.cpp Framework/Messaging/MessagingToolbox.h Framework/Toolbox/DicomDataset.cpp Framework/Toolbox/DicomDataset.h Framework/Toolbox/DicomStructureSet.cpp Framework/Toolbox/DicomStructureSet.h Framework/Toolbox/ISeriesLoader.h Framework/Toolbox/OrthancSeriesLoader.cpp Framework/Toolbox/OrthancSeriesLoader.h Resources/CMake/OrthancStone.cmake Resources/Graveyard/Messaging/CurlOrthancConnection.cpp Resources/Graveyard/Messaging/CurlOrthancConnection.h Resources/Graveyard/Messaging/IOrthancConnection.h Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp Resources/Orthanc/Plugins/Samples/Common/DicomPath.h Resources/Orthanc/Plugins/Samples/Common/DicomTag.cpp Resources/Orthanc/Plugins/Samples/Common/DicomTag.h Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h Resources/Orthanc/Plugins/Samples/Common/IDicomDataset.h Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.cpp Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h Resources/Orthanc/Plugins/Samples/Common/OrthancPluginException.h Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.h Resources/SyncOrthancFolder.py
diffstat 38 files changed, 1830 insertions(+), 245 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Applications/BasicApplicationContext.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Applications/BasicApplicationContext.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -38,7 +38,7 @@
 
 namespace OrthancStone
 {
-  BasicApplicationContext::BasicApplicationContext(IOrthancConnection& orthanc) :
+  BasicApplicationContext::BasicApplicationContext(OrthancPlugins::IOrthancConnection& orthanc) :
     orthanc_(orthanc)
   {
   }
--- a/Framework/Applications/BasicApplicationContext.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Applications/BasicApplicationContext.h	Fri Dec 16 15:41:20 2016 +0100
@@ -48,14 +48,15 @@
     typedef std::list<IWorldSceneInteractor*>  Interactors;
     typedef std::list<DicomStructureSet*>      StructureSets;
 
-    IOrthancConnection&  orthanc_;
-    WidgetViewport       viewport_;
-    Volumes              volumes_;
-    Interactors          interactors_;
-    StructureSets        structureSets_;
+    OrthancPlugins::IOrthancConnection&  orthanc_;
+
+    WidgetViewport   viewport_;
+    Volumes          volumes_;
+    Interactors      interactors_;
+    StructureSets    structureSets_;
 
   public:
-    BasicApplicationContext(IOrthancConnection& orthanc);
+    BasicApplicationContext(OrthancPlugins::IOrthancConnection& orthanc);
 
     ~BasicApplicationContext();
 
@@ -66,7 +67,7 @@
       return viewport_;
     }
 
-    IOrthancConnection& GetOrthancConnection()
+    OrthancPlugins::IOrthancConnection& GetOrthancConnection()
     {
       return orthanc_;
     }
--- a/Framework/Applications/IBasicApplication.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Applications/IBasicApplication.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -34,7 +34,7 @@
 
 #include "../../Resources/Orthanc/Core/Logging.h"
 #include "../../Resources/Orthanc/Core/HttpClient.h"
-#include "../Messaging/CurlOrthancConnection.h"
+#include "../../Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h"
 #include "Sdl/SdlEngine.h"
 
 namespace OrthancStone
@@ -208,7 +208,7 @@
       }
 
       LOG(WARNING) << "URL to the Orthanc REST API: " << webService.GetUrl();
-      CurlOrthancConnection orthanc(webService);
+      OrthancPlugins::OrthancHttpConnection orthanc(webService);
 
       if (!MessagingToolbox::CheckOrthancVersion(orthanc))
       {
--- a/Framework/Layers/SingleFrameRendererFactory.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Layers/SingleFrameRendererFactory.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -39,7 +39,7 @@
 
 namespace OrthancStone
 {
-  SingleFrameRendererFactory::SingleFrameRendererFactory(IOrthancConnection& orthanc,
+  SingleFrameRendererFactory::SingleFrameRendererFactory(OrthancPlugins::IOrthancConnection& orthanc,
                                                          const std::string& instanceId,
                                                          unsigned int frame) :
     orthanc_(orthanc),
--- a/Framework/Layers/SingleFrameRendererFactory.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Layers/SingleFrameRendererFactory.h	Fri Dec 16 15:41:20 2016 +0100
@@ -39,14 +39,15 @@
   class SingleFrameRendererFactory : public ILayerRendererFactory
   {
   private:
-    IOrthancConnection&   orthanc_;
+    OrthancPlugins::IOrthancConnection&   orthanc_;
+
     DicomDataset          dicom_;
     std::string           instance_;
     unsigned int          frame_;
     Orthanc::PixelFormat  format_;
 
   public:
-    SingleFrameRendererFactory(IOrthancConnection& orthanc,
+    SingleFrameRendererFactory(OrthancPlugins::IOrthancConnection& orthanc,
                                const std::string& instanceId,
                                unsigned int frame);
 
--- a/Framework/Messaging/CurlOrthancConnection.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders of this
- * program give permission to link the code of its release with the
- * OpenSSL project's "OpenSSL" library (or with modified versions of it
- * that use the same license as the "OpenSSL" library), and distribute
- * the linked executables. You must obey the GNU General Public License
- * in all respects for all of the code used other than "OpenSSL". If you
- * modify file(s) with this exception, you may extend this exception to
- * your version of the file(s), but you are not obligated to do so. If
- * you do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source files
- * in the program, then also delete it here.
- * 
- * 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "CurlOrthancConnection.h"
-
-#if ORTHANC_ENABLE_CURL == 1
-
-#include "../../Resources/Orthanc/Core/HttpClient.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-
-namespace OrthancStone
-{
-  void CurlOrthancConnection::RestApiGet(std::string& result,
-                                         const std::string& uri)
-  {
-    /**
-     * TODO: This function sometimes crashes if compiled with
-     * MinGW-W64 (32 bit) in Release mode, on Windows XP. Introducing
-     * a mutex here fixes the issue. Not sure of what is the
-     * culprit. Maybe a bug in a old version of MinGW?
-     **/
-
-    Orthanc::HttpClient client(parameters_, uri);
-
-    // Don't follow 3xx HTTP (avoid redirections to "unsupported.png" in Orthanc)
-    client.SetRedirectionFollowed(false);  
-   
-    if (!client.Apply(result))
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
-    }
-  }
-
-
-  void CurlOrthancConnection::RestApiPost(std::string& result,
-                                          const std::string& uri,
-                                          const std::string& body)
-  {
-    Orthanc::HttpClient client(parameters_, uri);
-
-    // Don't follow 3xx HTTP (avoid redirections to "unsupported.png" in Orthanc)
-    client.SetRedirectionFollowed(false);  
-
-    client.SetBody(body);
-    client.SetMethod(Orthanc::HttpMethod_Post);
-   
-    if (!client.Apply(result))
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
-    }
-  }
-}
-
-#endif
--- a/Framework/Messaging/CurlOrthancConnection.h	Wed Dec 14 17:05:41 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders of this
- * program give permission to link the code of its release with the
- * OpenSSL project's "OpenSSL" library (or with modified versions of it
- * that use the same license as the "OpenSSL" library), and distribute
- * the linked executables. You must obey the GNU General Public License
- * in all respects for all of the code used other than "OpenSSL". If you
- * modify file(s) with this exception, you may extend this exception to
- * your version of the file(s), but you are not obligated to do so. If
- * you do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source files
- * in the program, then also delete it here.
- * 
- * 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "IOrthancConnection.h"
-
-#if ORTHANC_ENABLE_CURL == 1
-
-#include "../../Resources/Orthanc/Core/WebServiceParameters.h"
-
-namespace OrthancStone
-{
-  class CurlOrthancConnection : public IOrthancConnection
-  {
-  private:
-    Orthanc::WebServiceParameters  parameters_;
-
-  public:
-    CurlOrthancConnection(const Orthanc::WebServiceParameters& parameters) :
-      parameters_(parameters)
-    {
-    }
-
-    const Orthanc::WebServiceParameters& GetParameters() const
-    {
-      return parameters_;
-    }
-
-    virtual void RestApiGet(std::string& result,
-                            const std::string& uri);
-
-    virtual void RestApiPost(std::string& result,
-                             const std::string& uri,
-                             const std::string& body);
-  };
-}
-
-#endif
--- a/Framework/Messaging/IOrthancConnection.h	Wed Dec 14 17:05:41 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders of this
- * program give permission to link the code of its release with the
- * OpenSSL project's "OpenSSL" library (or with modified versions of it
- * that use the same license as the "OpenSSL" library), and distribute
- * the linked executables. You must obey the GNU General Public License
- * in all respects for all of the code used other than "OpenSSL". If you
- * modify file(s) with this exception, you may extend this exception to
- * your version of the file(s), but you are not obligated to do so. If
- * you do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source files
- * in the program, then also delete it here.
- * 
- * 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "../Toolbox/IThreadSafety.h"
-
-#include <string>
-
-namespace OrthancStone
-{
-  // Derived classes must be thread-safe
-  class IOrthancConnection : public IThreadSafe
-  {
-  public:
-    virtual void RestApiGet(std::string& result,
-                            const std::string& uri) = 0;
-
-    virtual void RestApiPost(std::string& result,
-                             const std::string& uri,
-                             const std::string& body) = 0;
-  };
-}
--- a/Framework/Messaging/MessagingToolbox.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Messaging/MessagingToolbox.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -173,7 +173,7 @@
     }
 
     void RestApiGet(Json::Value& target,
-                    IOrthancConnection& orthanc,
+                    OrthancPlugins::IOrthancConnection& orthanc,
                     const std::string& uri)
     {
       std::string tmp;
@@ -182,7 +182,7 @@
     }
 
 
-    bool HasWebViewerInstalled(IOrthancConnection& orthanc)
+    bool HasWebViewerInstalled(OrthancPlugins::IOrthancConnection& orthanc)
     {
       try
       {
@@ -197,7 +197,7 @@
     }
 
 
-    bool CheckOrthancVersion(IOrthancConnection& orthanc)
+    bool CheckOrthancVersion(OrthancPlugins::IOrthancConnection& orthanc)
     {
       Json::Value json;
       std::string version;
@@ -250,7 +250,7 @@
     }
 
 
-    Orthanc::ImageAccessor* DecodeFrame(IOrthancConnection& orthanc,
+    Orthanc::ImageAccessor* DecodeFrame(OrthancPlugins::IOrthancConnection& orthanc,
                                         const std::string& instance,
                                         unsigned int frame,
                                         Orthanc::PixelFormat targetFormat)
@@ -297,7 +297,7 @@
     }
 
 
-    Orthanc::ImageAccessor* DecodeJpegFrame(IOrthancConnection& orthanc,
+    Orthanc::ImageAccessor* DecodeJpegFrame(OrthancPlugins::IOrthancConnection& orthanc,
                                             const std::string& instance,
                                             unsigned int frame,
                                             unsigned int quality,
--- a/Framework/Messaging/MessagingToolbox.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Messaging/MessagingToolbox.h	Fri Dec 16 15:41:20 2016 +0100
@@ -32,7 +32,7 @@
 
 #pragma once
 
-#include "IOrthancConnection.h"
+#include "../../Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h"
 
 #include "../Enumerations.h"
 #include "../../Resources/Orthanc/Core/Images/ImageAccessor.h"
@@ -73,22 +73,22 @@
                    const std::string& source);
 
     void RestApiGet(Json::Value& target,
-                    IOrthancConnection& orthanc,
+                    OrthancPlugins::IOrthancConnection& orthanc,
                     const std::string& uri);
 
-    bool HasWebViewerInstalled(IOrthancConnection& orthanc);
+    bool HasWebViewerInstalled(OrthancPlugins::IOrthancConnection& orthanc);
 
-    bool CheckOrthancVersion(IOrthancConnection& orthanc);
+    bool CheckOrthancVersion(OrthancPlugins::IOrthancConnection& orthanc);
 
     // This downloads the image from Orthanc and keeps its pixel
     // format unchanged (will be either Grayscale8, Grayscale16,
     // SignedGrayscale16, or RGB24)
-    Orthanc::ImageAccessor* DecodeFrame(IOrthancConnection& orthanc,
+    Orthanc::ImageAccessor* DecodeFrame(OrthancPlugins::IOrthancConnection& orthanc,
                                         const std::string& instance,
                                         unsigned int frame,
                                         Orthanc::PixelFormat targetFormat);
 
-    Orthanc::ImageAccessor* DecodeJpegFrame(IOrthancConnection& orthanc,
+    Orthanc::ImageAccessor* DecodeJpegFrame(OrthancPlugins::IOrthancConnection& orthanc,
                                             const std::string& instance,
                                             unsigned int frame,
                                             unsigned int quality,
--- a/Framework/Toolbox/DicomDataset.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/DicomDataset.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -153,7 +153,7 @@
   }
 
 
-  DicomDataset::DicomDataset(IOrthancConnection& orthanc,
+  DicomDataset::DicomDataset(OrthancPlugins::IOrthancConnection& orthanc,
                              const std::string& instanceId)
   {
     std::string content;
--- a/Framework/Toolbox/DicomDataset.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/DicomDataset.h	Fri Dec 16 15:41:20 2016 +0100
@@ -33,7 +33,7 @@
 #pragma once
 
 #include "GeometryToolbox.h"
-#include "../Messaging/IOrthancConnection.h"
+#include "../../Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h"
 
 #include <map>
 #include <stdint.h>
@@ -68,7 +68,7 @@
       Parse(content);
     }
 
-    DicomDataset(IOrthancConnection& orthanc,
+    DicomDataset(OrthancPlugins::IOrthancConnection& orthanc,
                  const std::string& instanceId);
 
     bool HasTag(const Tag& tag) const
--- a/Framework/Toolbox/DicomStructureSet.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/DicomStructureSet.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -82,7 +82,7 @@
 
 
   SliceGeometry DicomStructureSet::ExtractSliceGeometry(double& sliceThickness,
-                                                        IOrthancConnection& orthanc,
+                                                        OrthancPlugins::IOrthancConnection& orthanc,
                                                         const Json::Value& contour)
   {
     const Json::Value& sequence = GetSequence(contour, 0x3006, 0x0016);
@@ -198,7 +198,7 @@
   }
 
 
-  DicomStructureSet::DicomStructureSet(IOrthancConnection& orthanc,
+  DicomStructureSet::DicomStructureSet(OrthancPlugins::IOrthancConnection& orthanc,
                                        const std::string& instanceId)
   {
     Json::Value instance;
--- a/Framework/Toolbox/DicomStructureSet.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/DicomStructureSet.h	Fri Dec 16 15:41:20 2016 +0100
@@ -70,7 +70,7 @@
     Vector       normal_;
 
     SliceGeometry ExtractSliceGeometry(double& sliceThickness,
-                                       IOrthancConnection& orthanc,
+                                       OrthancPlugins::IOrthancConnection& orthanc,
                                        const Json::Value& contour);
 
     const Structure& GetStructure(size_t index) const;
@@ -80,7 +80,7 @@
 
 
   public:
-    DicomStructureSet(IOrthancConnection& orthanc,
+    DicomStructureSet(OrthancPlugins::IOrthancConnection& orthanc,
                       const std::string& instanceId);
 
     size_t GetStructureCount() const
--- a/Framework/Toolbox/ISeriesLoader.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/ISeriesLoader.h	Fri Dec 16 15:41:20 2016 +0100
@@ -34,6 +34,7 @@
 
 #include "ParallelSlices.h"
 
+#include "IThreadSafety.h"
 #include "../../Resources/Orthanc/Core/Images/ImageAccessor.h"
 
 namespace OrthancStone
--- a/Framework/Toolbox/OrthancSeriesLoader.cpp	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/OrthancSeriesLoader.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -137,7 +137,7 @@
       std::sort(slices_.begin(), slices_.end(), comparator);
     }
 
-    void LoadSeriesFast(IOrthancConnection&  orthanc,
+    void LoadSeriesFast(OrthancPlugins::IOrthancConnection&  orthanc,
                         const std::string& series)
     {
       // Retrieve the orientation of this series
@@ -203,7 +203,7 @@
     }
 
       
-    void LoadSeriesSafe(IOrthancConnection& orthanc,
+    void LoadSeriesSafe(OrthancPlugins::IOrthancConnection& orthanc,
                         const std::string& seriesId)
     {
       Json::Value series;
@@ -331,7 +331,7 @@
 
 
 
-  OrthancSeriesLoader::OrthancSeriesLoader(IOrthancConnection& orthanc,
+  OrthancSeriesLoader::OrthancSeriesLoader(OrthancPlugins::IOrthancConnection& orthanc,
                                            const std::string& series) :
     orthanc_(orthanc),
     slices_(new SetOfSlices)
--- a/Framework/Toolbox/OrthancSeriesLoader.h	Wed Dec 14 17:05:41 2016 +0100
+++ b/Framework/Toolbox/OrthancSeriesLoader.h	Fri Dec 16 15:41:20 2016 +0100
@@ -48,17 +48,17 @@
     class Slice;
     class SetOfSlices;
 
-    IOrthancConnection&             orthanc_;
-    boost::shared_ptr<SetOfSlices>  slices_;
-    ParallelSlices                  geometry_;
-    Orthanc::PixelFormat            format_;
-    unsigned int                    width_;
-    unsigned int                    height_;
+    OrthancPlugins::IOrthancConnection&  orthanc_;
+    boost::shared_ptr<SetOfSlices>       slices_;
+    ParallelSlices                       geometry_;
+    Orthanc::PixelFormat                 format_;
+    unsigned int                         width_;
+    unsigned int                         height_;
 
     void CheckFrame(const Orthanc::ImageAccessor& frame) const;
 
   public:
-    OrthancSeriesLoader(IOrthancConnection& orthanc,
+    OrthancSeriesLoader(OrthancPlugins::IOrthancConnection& orthanc,
                         const std::string& series);
     
     virtual Orthanc::PixelFormat GetPixelFormat()
--- a/Resources/CMake/OrthancStone.cmake	Wed Dec 14 17:05:41 2016 +0100
+++ b/Resources/CMake/OrthancStone.cmake	Fri Dec 16 15:41:20 2016 +0100
@@ -116,6 +116,7 @@
 endif()
 
 add_definitions(
+  -DHAS_ORTHANC_EXCEPTION=1
   -DORTHANC_ENABLE_MD5=0
   -DORTHANC_ENABLE_BASE64=1
   -DORTHANC_ENABLE_PUGIXML=0
@@ -170,7 +171,6 @@
   ${ORTHANC_STONE_DIR}/Framework/Layers/SeriesFrameRendererFactory.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/SiblingSliceLocationFactory.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/SingleFrameRendererFactory.cpp
-  ${ORTHANC_STONE_DIR}/Framework/Messaging/CurlOrthancConnection.cpp
   ${ORTHANC_STONE_DIR}/Framework/Messaging/MessagingToolbox.cpp
   ${ORTHANC_STONE_DIR}/Framework/Toolbox/BinarySemaphore.cpp
   ${ORTHANC_STONE_DIR}/Framework/Toolbox/DicomDataset.cpp
@@ -216,6 +216,13 @@
   ${ORTHANC_ROOT}/Core/Toolbox.cpp
   ${ORTHANC_ROOT}/Core/WebServiceParameters.cpp
   ${ORTHANC_ROOT}/Resources/ThirdParty/base64/base64.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomDatasetReader.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomPath.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomTag.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/FullOrthancDataset.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/IOrthancConnection.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancHttpConnection.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp
 
   ${AUTOGENERATED_SOURCES}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Graveyard/Messaging/CurlOrthancConnection.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,83 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "CurlOrthancConnection.h"
+
+#if ORTHANC_ENABLE_CURL == 1
+
+#include "../../Resources/Orthanc/Core/HttpClient.h"
+#include "../../Resources/Orthanc/Core/OrthancException.h"
+
+namespace OrthancStone
+{
+  void CurlOrthancConnection::RestApiGet(std::string& result,
+                                         const std::string& uri)
+  {
+    /**
+     * TODO: This function sometimes crashes if compiled with
+     * MinGW-W64 (32 bit) in Release mode, on Windows XP. Introducing
+     * a mutex here fixes the issue. Not sure of what is the
+     * culprit. Maybe a bug in a old version of MinGW?
+     **/
+
+    Orthanc::HttpClient client(parameters_, uri);
+
+    // Don't follow 3xx HTTP (avoid redirections to "unsupported.png" in Orthanc)
+    client.SetRedirectionFollowed(false);  
+   
+    if (!client.Apply(result))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
+    }
+  }
+
+
+  void CurlOrthancConnection::RestApiPost(std::string& result,
+                                          const std::string& uri,
+                                          const std::string& body)
+  {
+    Orthanc::HttpClient client(parameters_, uri);
+
+    // Don't follow 3xx HTTP (avoid redirections to "unsupported.png" in Orthanc)
+    client.SetRedirectionFollowed(false);  
+
+    client.SetBody(body);
+    client.SetMethod(Orthanc::HttpMethod_Post);
+   
+    if (!client.Apply(result))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
+    }
+  }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Graveyard/Messaging/CurlOrthancConnection.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,68 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOrthancConnection.h"
+
+#if ORTHANC_ENABLE_CURL == 1
+
+#include "../../Resources/Orthanc/Core/WebServiceParameters.h"
+
+namespace OrthancStone
+{
+  class CurlOrthancConnection : public IOrthancConnection
+  {
+  private:
+    Orthanc::WebServiceParameters  parameters_;
+
+  public:
+    CurlOrthancConnection(const Orthanc::WebServiceParameters& parameters) :
+      parameters_(parameters)
+    {
+    }
+
+    const Orthanc::WebServiceParameters& GetParameters() const
+    {
+      return parameters_;
+    }
+
+    virtual void RestApiGet(std::string& result,
+                            const std::string& uri);
+
+    virtual void RestApiPost(std::string& result,
+                             const std::string& uri,
+                             const std::string& body);
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Graveyard/Messaging/IOrthancConnection.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,52 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "../Toolbox/IThreadSafety.h"
+
+#include <string>
+
+namespace OrthancStone
+{
+  // Derived classes must be thread-safe
+  class IOrthancConnection : public IThreadSafe
+  {
+  public:
+    virtual void RestApiGet(std::string& result,
+                            const std::string& uri) = 0;
+
+    virtual void RestApiPost(std::string& result,
+                             const std::string& uri,
+                             const std::string& body) = 0;
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,122 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "DicomDatasetReader.h"
+
+#include "OrthancPluginException.h"
+
+#include <boost/lexical_cast.hpp>
+
+namespace OrthancPlugins
+{
+  // This function is copied-pasted from "../../../Core/Toolbox.cpp",
+  // in order to avoid the dependency of plugins against the Orthanc core
+  static std::string StripSpaces(const std::string& source)
+  {
+    size_t first = 0;
+
+    while (first < source.length() &&
+           isspace(source[first]))
+    {
+      first++;
+    }
+
+    if (first == source.length())
+    {
+      // String containing only spaces
+      return "";
+    }
+
+    size_t last = source.length();
+    while (last > first &&
+           isspace(source[last - 1]))
+    {
+      last--;
+    }          
+    
+    assert(first <= last);
+    return source.substr(first, last - first);
+  }
+
+
+  DicomDatasetReader::DicomDatasetReader(IDicomDataset* dataset) :  // takes ownership
+    dataset_(dataset)
+  {
+    if (dataset == NULL)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
+    }
+  }
+  
+
+  std::string DicomDatasetReader::GetMandatoryStringValue(const DicomPath& path) const
+  {
+    std::string s;
+    if (dataset_->GetStringValue(s, path))
+    {
+      return s;
+    }
+    else
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentTag);
+    }
+  }
+
+
+  int DicomDatasetReader::GetIntegerValue(const DicomPath& path)
+  {
+    try
+    {
+      std::string s = StripSpaces(GetMandatoryStringValue(path));
+      return boost::lexical_cast<int>(s);
+    }
+    catch (boost::bad_lexical_cast&)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);        
+    }
+  }
+
+
+  unsigned int DicomDatasetReader::GetUnsignedIntegerValue(const DicomPath& path)
+  {
+    int value = GetIntegerValue(path);
+
+    if (value >= 0)
+    {
+      return static_cast<unsigned int>(value);
+    }
+    else
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,60 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IDicomDataset.h"
+
+#include <memory>
+
+namespace OrthancPlugins
+{
+  class DicomDatasetReader : public boost::noncopyable
+  {
+  private:
+    std::auto_ptr<IDicomDataset>  dataset_;
+
+  public:
+    DicomDatasetReader(IDicomDataset* dataset);  // takes ownership
+
+    IDicomDataset& GetDataset() const
+    {
+      return *dataset_;
+    }
+
+    std::string GetMandatoryStringValue(const DicomPath& path) const;
+
+    int GetIntegerValue(const DicomPath& path);
+
+    unsigned int GetUnsignedIntegerValue(const DicomPath& path);
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,86 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "DicomPath.h"
+
+#include "OrthancPluginException.h"
+
+namespace OrthancPlugins
+{
+  const DicomPath::Prefix& DicomPath::GetPrefixItem(size_t depth) const
+  {
+    if (depth >= prefix_.size())
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
+    }
+    else
+    {
+      return prefix_[depth];
+    }
+  }
+
+
+  DicomPath::DicomPath(const DicomTag& sequence,
+                       size_t index,
+                       const DicomTag& tag) :
+    finalTag_(tag)
+  {
+    AddToPrefix(sequence, index);
+  }
+
+
+  DicomPath::DicomPath(const DicomTag& sequence1,
+                       size_t index1,
+                       const DicomTag& sequence2,
+                       size_t index2,
+                       const DicomTag& tag) :
+    finalTag_(tag)
+  {
+    AddToPrefix(sequence1, index1);
+    AddToPrefix(sequence2, index2);
+  }
+
+
+  DicomPath::DicomPath(const DicomTag& sequence1,
+                       size_t index1,
+                       const DicomTag& sequence2,
+                       size_t index2,
+                       const DicomTag& sequence3,
+                       size_t index3,
+                       const DicomTag& tag) :
+    finalTag_(tag)
+  {
+    AddToPrefix(sequence1, index1);
+    AddToPrefix(sequence2, index2);
+    AddToPrefix(sequence3, index3);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomPath.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,107 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "DicomTag.h"
+
+#include <vector>
+#include <stddef.h>
+
+namespace OrthancPlugins
+{
+  class DicomPath
+  {
+  private:
+    typedef std::pair<DicomTag, size_t>  Prefix;
+
+    std::vector<Prefix>  prefix_;
+    DicomTag             finalTag_;
+
+    const Prefix& GetPrefixItem(size_t depth) const;
+
+  public:
+    DicomPath(const DicomTag& finalTag) :
+    finalTag_(finalTag)
+    {
+    }
+
+    DicomPath(const DicomTag& sequence,
+              size_t index,
+              const DicomTag& tag);
+
+    DicomPath(const DicomTag& sequence1,
+              size_t index1,
+              const DicomTag& sequence2,
+              size_t index2,
+              const DicomTag& tag);
+
+    DicomPath(const DicomTag& sequence1,
+              size_t index1,
+              const DicomTag& sequence2,
+              size_t index2,
+              const DicomTag& sequence3,
+              size_t index3,
+              const DicomTag& tag);
+
+    void AddToPrefix(const DicomTag& tag,
+                     size_t position)
+    {
+      prefix_.push_back(std::make_pair(tag, position));
+    }
+
+    size_t GetPrefixLength() const
+    {
+      return prefix_.size();
+    }
+    
+    DicomTag GetPrefixTag(size_t depth) const
+    {
+      return GetPrefixItem(depth).first;
+    }
+
+    size_t GetPrefixIndex(size_t depth) const
+    {
+      return GetPrefixItem(depth).second;
+    }
+    
+    const DicomTag& GetFinalTag() const
+    {
+      return finalTag_;
+    }
+
+    void SetFinalTag(const DicomTag& tag)
+    {
+      finalTag_ = tag;
+    }
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomTag.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,110 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "DicomTag.h"
+
+#include "OrthancPluginException.h"
+
+namespace OrthancPlugins
+{
+  const char* DicomTag::GetName() const
+  {
+    if (*this == DICOM_TAG_BITS_STORED)
+    {
+      return "BitsStored";
+    }
+    else if (*this == DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)
+    {
+      return "ColumnPositionInTotalImagePixelMatrix";
+    }
+    else if (*this == DICOM_TAG_COLUMNS)
+    {
+      return "Columns";
+    }
+    else if (*this == DICOM_TAG_MODALITY)
+    {
+      return "Modality";
+    }
+    else if (*this == DICOM_TAG_NUMBER_OF_FRAMES)
+    {
+      return "NumberOfFrames";
+    }
+    else if (*this == DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE)
+    {
+      return "PerFrameFunctionalGroupsSequence";
+    }
+    else if (*this == DICOM_TAG_PHOTOMETRIC_INTERPRETATION)
+    {
+      return "PhotometricInterpretation";
+    }
+    else if (*this == DICOM_TAG_PIXEL_REPRESENTATION)
+    {
+      return "PixelRepresentation";
+    }
+    else if (*this == DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE)
+    {
+      return "PlanePositionSlideSequence";
+    }
+    else if (*this == DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)
+    {
+      return "RowPositionInTotalImagePixelMatrix";
+    }
+    else if (*this == DICOM_TAG_ROWS)
+    {
+      return "Rows";
+    }
+    else if (*this == DICOM_TAG_SOP_CLASS_UID)
+    {
+      return "SOPClassUID";
+    }
+    else if (*this == DICOM_TAG_SAMPLES_PER_PIXEL)
+    {
+      return "SamplesPerPixel";
+    }
+    else if (*this == DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS)
+    {
+      return "TotalPixelMatrixColumns";
+    }
+    else if (*this == DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS)
+    {
+      return "TotalPixelMatrixRows";
+    }
+    else if (*this == DICOM_TAG_TRANSFER_SYNTAX_UID)
+    {
+      return "TransferSyntaxUID";
+    }
+    else
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NotImplemented);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/DicomTag.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,95 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include <stdint.h>
+
+namespace OrthancPlugins
+{
+  class DicomTag
+  {
+  private:
+    uint16_t  group_;
+    uint16_t  element_;
+
+    DicomTag();  // Forbidden
+
+  public:
+    DicomTag(uint16_t group,
+             uint16_t element) :
+      group_(group),
+      element_(element)
+    {
+    }
+
+    uint16_t GetGroup() const
+    {
+      return group_;
+    }
+
+    uint16_t GetElement() const
+    {
+      return element_;
+    }
+
+    const char* GetName() const;
+
+    bool operator== (const DicomTag& other) const
+    {
+      return group_ == other.group_ && element_ == other.element_;
+    }
+
+    bool operator!= (const DicomTag& other) const
+    {
+      return !(*this == other);
+    }
+  };
+
+
+  static const DicomTag DICOM_TAG_BITS_STORED(0x0028, 0x0101);
+  static const DicomTag DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021e);
+  static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011);
+  static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060);
+  static const DicomTag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008);
+  static const DicomTag DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE(0x5200, 0x9230);
+  static const DicomTag DICOM_TAG_PHOTOMETRIC_INTERPRETATION(0x0028, 0x0004);
+  static const DicomTag DICOM_TAG_PIXEL_REPRESENTATION(0x0028, 0x0103);
+  static const DicomTag DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE(0x0048, 0x021a);
+  static const DicomTag DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021f);
+  static const DicomTag DICOM_TAG_ROWS(0x0028, 0x0010);
+  static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016);
+  static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002);
+  static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS(0x0048, 0x0006);
+  static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS(0x0048, 0x0007);
+  static const DicomTag DICOM_TAG_TRANSFER_SYNTAX_UID(0x0002, 0x0010);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,199 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "FullOrthancDataset.h"
+
+#include "OrthancPluginException.h"
+
+#include <stdio.h>
+#include <cassert>
+
+namespace OrthancPlugins
+{
+  static const Json::Value* AccessTag(const Json::Value& dataset,
+                                      const DicomTag& tag) 
+  {
+    if (dataset.type() != Json::objectValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+
+    char name[16];
+    sprintf(name, "%04x,%04x", tag.GetGroup(), tag.GetElement());
+
+    if (!dataset.isMember(name))
+    {
+      return NULL;
+    }
+
+    const Json::Value& value = dataset[name];
+    if (value.type() != Json::objectValue ||
+        !value.isMember("Name") ||
+        !value.isMember("Type") ||
+        !value.isMember("Value") ||
+        value["Name"].type() != Json::stringValue ||
+        value["Type"].type() != Json::stringValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+
+    return &value;
+  }
+
+
+  static const Json::Value& GetSequenceContent(const Json::Value& sequence)
+  {
+    assert(sequence.type() == Json::objectValue);
+    assert(sequence.isMember("Type"));
+    assert(sequence.isMember("Value"));
+
+    const Json::Value& value = sequence["Value"];
+      
+    if (sequence["Type"].asString() != "Sequence" ||
+        value.type() != Json::arrayValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+    else
+    {
+      return value;
+    }
+  }
+
+
+  static bool GetStringInternal(std::string& result,
+                                const Json::Value& tag)
+  {
+    assert(tag.type() == Json::objectValue);
+    assert(tag.isMember("Type"));
+    assert(tag.isMember("Value"));
+
+    const Json::Value& value = tag["Value"];
+      
+    if (tag["Type"].asString() != "String" ||
+        value.type() != Json::stringValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+    else
+    {
+      result = value.asString();
+      return true;
+    }
+  }
+
+
+  const Json::Value* FullOrthancDataset::LookupPath(const DicomPath& path) const
+  {
+    const Json::Value* content = &root_;
+                                  
+    for (unsigned int depth = 0; depth < path.GetPrefixLength(); depth++)
+    {
+      const Json::Value* sequence = AccessTag(*content, path.GetPrefixTag(depth));
+      if (sequence == NULL)
+      {
+        return NULL;
+      }
+
+      const Json::Value& nextContent = GetSequenceContent(*sequence);
+
+      size_t index = path.GetPrefixIndex(depth);
+      if (index >= nextContent.size())
+      {
+        return NULL;
+      }
+      else
+      {
+        content = &nextContent[static_cast<Json::Value::ArrayIndex>(index)];
+      }
+    }
+
+    return AccessTag(*content, path.GetFinalTag());
+  }
+
+
+  void FullOrthancDataset::CheckRoot() const
+  {
+    if (root_.type() != Json::objectValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+  }
+
+
+  FullOrthancDataset::FullOrthancDataset(IOrthancConnection& orthanc,
+                                         const std::string& uri)
+  {
+    IOrthancConnection::RestApiGet(root_, orthanc, uri);
+    CheckRoot();
+  }
+
+
+  FullOrthancDataset::FullOrthancDataset(const std::string& content)
+  {
+    IOrthancConnection::ParseJson(root_, content);
+    CheckRoot();
+  }
+
+
+  bool FullOrthancDataset::GetStringValue(std::string& result,
+                                          const DicomPath& path) const
+  {
+    const Json::Value* value = LookupPath(path);
+
+    if (value == NULL)
+    {
+      return false;
+    }
+    else
+    {
+      return GetStringInternal(result, *value);
+    }
+  }
+
+
+  bool FullOrthancDataset::GetSequenceSize(size_t& size,
+                                           const DicomPath& path) const
+  {
+    const Json::Value* sequence = LookupPath(path);
+
+    if (sequence == NULL)
+    {
+      return false;
+    }
+    else
+    {
+      size = GetSequenceContent(*sequence).size();
+      return true;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,63 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOrthancConnection.h"
+#include "IDicomDataset.h"
+
+#include <json/value.h>
+
+namespace OrthancPlugins
+{
+  class FullOrthancDataset : public IDicomDataset
+  {
+  private:
+    Json::Value   root_;
+
+    const Json::Value* LookupPath(const DicomPath& path) const;
+
+    void CheckRoot() const;
+
+  public:
+    FullOrthancDataset(IOrthancConnection& orthanc,
+                       const std::string& uri);
+
+    FullOrthancDataset(const std::string& content);
+
+    virtual bool GetStringValue(std::string& result,
+                                const DicomPath& path) const;
+
+    virtual bool GetSequenceSize(size_t& size,
+                                 const DicomPath& path) const;
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/IDicomDataset.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,55 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "DicomPath.h"
+
+#include <boost/noncopyable.hpp>
+#include <string>
+
+namespace OrthancPlugins
+{
+  class IDicomDataset : public boost::noncopyable
+  {
+  public:
+    virtual ~IDicomDataset()
+    {
+    }
+
+    virtual bool GetStringValue(std::string& result,
+                                const DicomPath& path) const = 0;
+
+    virtual bool GetSequenceSize(size_t& size,
+                                 const DicomPath& path) const = 0;
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,83 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "IOrthancConnection.h"
+
+#include "OrthancPluginException.h"
+
+#include <json/reader.h>
+
+namespace OrthancPlugins
+{
+  void IOrthancConnection::ParseJson(Json::Value& result,
+                                     const std::string& content)
+  {
+    Json::Reader reader;
+    
+    if (!reader.parse(content, result))
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+  }
+
+
+  void IOrthancConnection::RestApiGet(Json::Value& result,
+                                      IOrthancConnection& orthanc,
+                                      const std::string& uri)
+  {
+    std::string content;
+    orthanc.RestApiGet(content, uri);
+    ParseJson(result, content);
+  }
+
+
+  void IOrthancConnection::RestApiPost(Json::Value& result,
+                                       IOrthancConnection& orthanc,
+                                       const std::string& uri,
+                                       const std::string& body)
+  {
+    std::string content;
+    orthanc.RestApiPost(content, uri, body);
+    ParseJson(result, content);
+  }
+
+
+  void IOrthancConnection::RestApiPut(Json::Value& result,
+                                      IOrthancConnection& orthanc,
+                                      const std::string& uri,
+                                      const std::string& body)
+  {
+    std::string content;
+    orthanc.RestApiPut(content, uri, body);
+    ParseJson(result, content);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,80 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "DicomPath.h"
+
+#include <boost/noncopyable.hpp>
+#include <string>
+#include <json/value.h>
+
+namespace OrthancPlugins
+{
+  class IOrthancConnection : public boost::noncopyable
+  {
+  public:
+    virtual ~IOrthancConnection()
+    {
+    }
+
+    virtual void RestApiGet(std::string& result,
+                            const std::string& uri) = 0;
+
+    virtual void RestApiPost(std::string& result,
+                             const std::string& uri,
+                             const std::string& body) = 0;
+
+    virtual void RestApiPut(std::string& result,
+                            const std::string& uri,
+                            const std::string& body) = 0;
+
+    virtual void RestApiDelete(const std::string& uri) = 0;
+
+    static void ParseJson(Json::Value& result,
+                          const std::string& content);
+
+    static void RestApiGet(Json::Value& result,
+                           IOrthancConnection& orthanc,
+                           const std::string& uri);
+
+    static void RestApiPost(Json::Value& result,
+                            IOrthancConnection& orthanc,
+                            const std::string& uri,
+                            const std::string& body);
+
+    static void RestApiPut(Json::Value& result,
+                           IOrthancConnection& orthanc,
+                           const std::string& uri,
+                           const std::string& body);
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,107 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "OrthancHttpConnection.h"
+
+namespace OrthancPlugins
+{
+  void OrthancHttpConnection::Setup()
+  {
+    url_ = client_.GetUrl();
+
+    // Don't follow 3xx HTTP (avoid redirections to "unsupported.png" in Orthanc)
+    client_.SetRedirectionFollowed(false);  
+  }
+
+
+  OrthancHttpConnection::OrthancHttpConnection() :
+    client_(Orthanc::WebServiceParameters(), "")
+  {
+    Setup();
+  }
+
+
+  OrthancHttpConnection::OrthancHttpConnection(const Orthanc::WebServiceParameters& parameters) :
+    client_(parameters, "")
+  {
+    Setup();
+  }
+
+
+  void OrthancHttpConnection::RestApiGet(std::string& result,
+                                         const std::string& uri)
+  {
+    boost::mutex::scoped_lock lock(mutex_);
+
+    client_.SetMethod(Orthanc::HttpMethod_Get);
+    client_.SetUrl(url_ + uri);
+    client_.ApplyAndThrowException(result);
+  }
+
+
+  void OrthancHttpConnection::RestApiPost(std::string& result,
+                                          const std::string& uri,
+                                          const std::string& body)
+  {
+    boost::mutex::scoped_lock lock(mutex_);
+
+    client_.SetMethod(Orthanc::HttpMethod_Post);
+    client_.SetUrl(url_ + uri);
+    client_.SetBody(body);
+    client_.ApplyAndThrowException(result);
+  }
+
+
+  void OrthancHttpConnection::RestApiPut(std::string& result,
+                                         const std::string& uri,
+                                         const std::string& body)
+  {
+    boost::mutex::scoped_lock lock(mutex_);
+
+    client_.SetMethod(Orthanc::HttpMethod_Put);
+    client_.SetUrl(url_ + uri);
+    client_.SetBody(body);
+    client_.ApplyAndThrowException(result);
+  }
+
+
+  void OrthancHttpConnection::RestApiDelete(const std::string& uri)
+  {
+    boost::mutex::scoped_lock lock(mutex_);
+
+    std::string result;
+
+    client_.SetMethod(Orthanc::HttpMethod_Delete);
+    client_.SetUrl(url_ + uri);
+    client_.ApplyAndThrowException(result);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,75 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOrthancConnection.h"
+
+#if HAS_ORTHANC_EXCEPTION != 1
+#  error The macro HAS_ORTHANC_EXCEPTION must be set to 1 if using this header
+#endif
+
+#include "../../../Core/HttpClient.h"
+
+#include <boost/thread/mutex.hpp>
+
+namespace OrthancPlugins
+{
+  // This class is thread-safe
+  class OrthancHttpConnection : public IOrthancConnection
+  {
+  private:
+    boost::mutex         mutex_;
+    Orthanc::HttpClient  client_;
+    std::string          url_;
+
+    void Setup();
+
+  public:
+    OrthancHttpConnection();
+
+    OrthancHttpConnection(const Orthanc::WebServiceParameters& parameters);
+
+    virtual void RestApiGet(std::string& result,
+                            const std::string& uri);
+
+    virtual void RestApiPost(std::string& result,
+                             const std::string& uri,
+                             const std::string& body);
+
+    virtual void RestApiPut(std::string& result,
+                            const std::string& uri,
+                            const std::string& body);
+
+    virtual void RestApiDelete(const std::string& uri);
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginException.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,100 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#if !defined(HAS_ORTHANC_EXCEPTION)
+#  error The macro HAS_ORTHANC_EXCEPTION must be defined
+#endif
+
+
+#if HAS_ORTHANC_EXCEPTION == 1
+#  include "../../../Core/OrthancException.h"
+#  define ORTHANC_PLUGINS_GET_ERROR_ENUMERATION  ::Orthanc::ErrorCode
+#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)   ::Orthanc::ErrorCode_ ## code
+#  define ORTHANC_PLUGINS_GET_EXCEPTION_CLASS    ::Orthanc::OrthancException
+#else
+#  include <orthanc/OrthancCPlugin.h>
+#  define ORTHANC_PLUGINS_GET_ERROR_ENUMERATION  ::OrthancPluginErrorCode
+#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)   ::OrthancPluginErrorCode_ ## code
+#  define ORTHANC_PLUGINS_GET_EXCEPTION_CLASS    ::OrthancPlugins::PluginException
+#endif
+
+
+#define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
+  throw ORTHANC_PLUGINS_GET_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_GET_ERROR_ENUMERATION>(code));
+
+
+#define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
+  throw ORTHANC_PLUGINS_GET_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
+                                                  
+
+#define ORTHANC_PLUGINS_CHECK_ERROR(code)                           \
+  if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success))              \
+  {                                                                 \
+    ORTHANC_PLUGINS_THROW_EXCEPTION(code);                          \
+  }
+
+
+namespace OrthancPlugins
+{
+#if HAS_ORTHANC_EXCEPTION == 0
+  class PluginException
+  {
+  private:
+    OrthancPluginErrorCode  code_;
+
+  public:
+    explicit PluginException(OrthancPluginErrorCode code) : code_(code)
+    {
+    }
+
+    OrthancPluginErrorCode GetErrorCode() const
+    {
+      return code_;
+    }
+
+    const char* What(OrthancPluginContext* context) const
+    {
+      const char* description = OrthancPluginGetErrorDescription(context, code_);
+      if (description)
+      {
+        return description;
+      }
+      else
+      {
+        return "No description available";
+      }
+    }
+  };
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,156 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "SimplifiedOrthancDataset.h"
+
+#include "OrthancPluginException.h"
+
+namespace OrthancPlugins
+{
+  const Json::Value* SimplifiedOrthancDataset::LookupPath(const DicomPath& path) const
+  {
+    const Json::Value* content = &root_;
+                                  
+    for (unsigned int depth = 0; depth < path.GetPrefixLength(); depth++)
+    {
+      const char* name = path.GetPrefixTag(depth).GetName();
+      if (content->type() != Json::objectValue)
+      {
+        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+      }
+
+      if (!content->isMember(name))
+      {
+        return NULL;
+      }
+
+      const Json::Value& sequence = (*content) [name];
+      if (sequence.type() != Json::arrayValue)
+      {
+        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+      }
+
+      size_t index = path.GetPrefixIndex(depth);
+      if (index >= sequence.size())
+      {
+        return NULL;
+      }
+      else
+      {
+        content = &sequence[static_cast<Json::Value::ArrayIndex>(index)];
+      }
+    }
+
+    const char* name = path.GetFinalTag().GetName();
+
+    if (content->type() != Json::objectValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+    if (!content->isMember(name))
+    {
+      return NULL;
+    }
+    else
+    {
+      return &((*content) [name]);
+    }
+  }
+
+
+  void SimplifiedOrthancDataset::CheckRoot() const
+  {
+    if (root_.type() != Json::objectValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+  }
+
+
+  SimplifiedOrthancDataset::SimplifiedOrthancDataset(IOrthancConnection& orthanc,
+                                                     const std::string& uri)
+  {
+    IOrthancConnection::RestApiGet(root_, orthanc, uri);
+    CheckRoot();
+  }
+
+
+  SimplifiedOrthancDataset::SimplifiedOrthancDataset(const std::string& content)
+  {
+    IOrthancConnection::ParseJson(root_, content);
+    CheckRoot();
+  }
+
+
+  bool SimplifiedOrthancDataset::GetStringValue(std::string& result,
+                                                const DicomPath& path) const
+  {
+    const Json::Value* value = LookupPath(path);
+
+    if (value == NULL)
+    {
+      return false;
+    }
+    else if (value->type() != Json::stringValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+    else
+    {
+      result = value->asString();
+      return true;
+    }
+  }
+
+
+  bool SimplifiedOrthancDataset::GetSequenceSize(size_t& size,
+                                                 const DicomPath& path) const
+  {
+    const Json::Value* sequence = LookupPath(path);
+
+    if (sequence == NULL)
+    {
+      // Inexistent path
+      return false;
+    }
+    else if (sequence->type() != Json::arrayValue)
+    {
+      // Not a sequence
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
+    }
+    else
+    {
+      size = sequence->size();
+      return true;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.h	Fri Dec 16 15:41:20 2016 +0100
@@ -0,0 +1,61 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOrthancConnection.h"
+#include "IDicomDataset.h"
+
+namespace OrthancPlugins
+{
+  class SimplifiedOrthancDataset : public IDicomDataset
+  {
+  private:
+    Json::Value   root_;
+
+    const Json::Value* LookupPath(const DicomPath& path) const;
+
+    void CheckRoot() const;
+
+  public:
+    SimplifiedOrthancDataset(IOrthancConnection& orthanc,
+                             const std::string& uri);
+
+    SimplifiedOrthancDataset(const std::string& content);
+
+    virtual bool GetStringValue(std::string& result,
+                                const DicomPath& path) const;
+
+    virtual bool GetSequenceSize(size_t& size,
+                                 const DicomPath& path) const;
+  };
+}
--- a/Resources/SyncOrthancFolder.py	Wed Dec 14 17:05:41 2016 +0100
+++ b/Resources/SyncOrthancFolder.py	Fri Dec 16 15:41:20 2016 +0100
@@ -50,6 +50,22 @@
     'Core/Toolbox.h',
     'Core/WebServiceParameters.cpp',
     'Core/WebServiceParameters.h',
+    'Plugins/Samples/Common/DicomDatasetReader.cpp',
+    'Plugins/Samples/Common/DicomDatasetReader.h',
+    'Plugins/Samples/Common/DicomPath.cpp',
+    'Plugins/Samples/Common/DicomPath.h',
+    'Plugins/Samples/Common/DicomTag.cpp',
+    'Plugins/Samples/Common/DicomTag.h',
+    'Plugins/Samples/Common/FullOrthancDataset.cpp',
+    'Plugins/Samples/Common/FullOrthancDataset.h',
+    'Plugins/Samples/Common/IDicomDataset.h',
+    'Plugins/Samples/Common/IOrthancConnection.cpp',
+    'Plugins/Samples/Common/IOrthancConnection.h',
+    'Plugins/Samples/Common/OrthancHttpConnection.cpp',
+    'Plugins/Samples/Common/OrthancHttpConnection.h',
+    'Plugins/Samples/Common/OrthancPluginException.h',
+    'Plugins/Samples/Common/SimplifiedOrthancDataset.cpp',
+    'Plugins/Samples/Common/SimplifiedOrthancDataset.h',
     'Resources/CMake/AutoGeneratedCode.cmake',
     'Resources/CMake/BoostConfiguration.cmake',
     'Resources/CMake/Compiler.cmake',