changeset 1698:d78b87f93bcf

DicomModification use Json::Value
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 09 Oct 2015 12:29:21 +0200
parents 21902c8ba95b
children 8ca0e89798b2
files OrthancServer/DicomModification.cpp OrthancServer/DicomModification.h OrthancServer/LuaScripting.cpp OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/Scheduler/ModifyInstanceCommand.cpp OrthancServer/Scheduler/ModifyInstanceCommand.h
diffstat 6 files changed, 124 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/DicomModification.cpp	Thu Oct 08 14:52:03 2015 +0200
+++ b/OrthancServer/DicomModification.cpp	Fri Oct 09 12:29:21 2015 +0200
@@ -44,13 +44,56 @@
 
 namespace Orthanc
 {
+  void DicomModification::RemoveInternal(const DicomTag& tag)
+  {
+    Replacements::iterator it = replacements_.find(tag);
+
+    if (it != replacements_.end())
+    {
+      delete it->second;
+      replacements_.erase(it);
+    }    
+  }
+
+
+  void DicomModification::ReplaceInternal(const DicomTag& tag,
+                                          const Json::Value& value)
+  {
+    Replacements::iterator it = replacements_.find(tag);
+
+    if (it != replacements_.end())
+    {
+      delete it->second;
+      it->second = NULL;   // In the case of an exception during the clone
+      it->second = new Json::Value(value);  // Clone
+    }
+    else
+    {
+      replacements_[tag] = new Json::Value(value);  // Clone
+    }
+  }
+
+
+  void DicomModification::ClearReplacements()
+  {
+    for (Replacements::iterator it = replacements_.begin();
+         it != replacements_.end(); ++it)
+    {
+      delete it->second;
+    }
+
+    replacements_.clear();
+  }
+
+
   void DicomModification::MarkNotOrthancAnonymization()
   {
     Replacements::iterator it = replacements_.find(DICOM_TAG_DEIDENTIFICATION_METHOD);
 
     if (it != replacements_.end() &&
-        it->second == ORTHANC_DEIDENTIFICATION_METHOD)
+        it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD)
     {
+      delete it->second;
       replacements_.erase(it);
     }
   }
@@ -100,7 +143,7 @@
 
     dicom.Replace(*tag, mapped);
   }
-
+  
   DicomModification::DicomModification()
   {
     removePrivateTags_ = false;
@@ -108,10 +151,15 @@
     allowManualIdentifiers_ = true;
   }
 
+  DicomModification::~DicomModification()
+  {
+    ClearReplacements();
+  }
+
   void DicomModification::Keep(const DicomTag& tag)
   {
     removals_.erase(tag);
-    replacements_.erase(tag);
+    RemoveInternal(tag);
 
     if (FromDcmtkBridge::IsPrivateTag(tag))
     {
@@ -124,7 +172,7 @@
   void DicomModification::Remove(const DicomTag& tag)
   {
     removals_.insert(tag);
-    replacements_.erase(tag);
+    RemoveInternal(tag);
     privateTagsToKeep_.erase(tag);
 
     MarkNotOrthancAnonymization();
@@ -136,12 +184,12 @@
   }
 
   void DicomModification::Replace(const DicomTag& tag,
-                                  const std::string& utf8Value,
+                                  const Json::Value& value,
                                   bool safeForAnonymization)
   {
     removals_.erase(tag);
     privateTagsToKeep_.erase(tag);
-    replacements_[tag] = utf8Value;
+    ReplaceInternal(tag, value);
 
     if (!safeForAnonymization)
     {
@@ -149,12 +197,13 @@
     }
   }
 
+
   bool DicomModification::IsReplaced(const DicomTag& tag) const
   {
     return replacements_.find(tag) != replacements_.end();
   }
 
-  const std::string& DicomModification::GetReplacement(const DicomTag& tag) const
+  const Json::Value& DicomModification::GetReplacement(const DicomTag& tag) const
   {
     Replacements::const_iterator it = replacements_.find(tag);
 
@@ -164,10 +213,26 @@
     }
     else
     {
-      return it->second;
+      return *it->second;
     } 
   }
 
+
+  std::string DicomModification::GetReplacementAsString(const DicomTag& tag) const
+  {
+    const Json::Value& json = GetReplacement(tag);
+
+    if (json.type() != Json::stringValue)
+    {
+      throw OrthancException(ErrorCode_BadParameterType);
+    }
+    else
+    {
+      return json.asString();
+    }    
+  }
+
+
   void DicomModification::SetRemovePrivateTags(bool removed)
   {
     removePrivateTags_ = removed;
@@ -192,7 +257,7 @@
   void DicomModification::SetupAnonymization()
   {
     removals_.clear();
-    replacements_.clear();
+    ClearReplacements();
     removePrivateTags_ = true;
     level_ = ResourceType_Patient;
     uidMap_.clear();
@@ -255,15 +320,15 @@
     removals_.insert(DicomTag(0x0010, 0x2000));  // Medical Alerts
 
     // Set the DeidentificationMethod tag
-    replacements_.insert(std::make_pair(DICOM_TAG_DEIDENTIFICATION_METHOD, ORTHANC_DEIDENTIFICATION_METHOD));
+    ReplaceInternal(DICOM_TAG_DEIDENTIFICATION_METHOD, ORTHANC_DEIDENTIFICATION_METHOD);
 
     // Set the PatientIdentityRemoved tag
-    replacements_.insert(std::make_pair(DicomTag(0x0012, 0x0062), "YES"));
+    ReplaceInternal(DicomTag(0x0012, 0x0062), "YES");
 
     // (*) Choose a random patient name and ID
     std::string patientId = FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient);
-    replacements_[DICOM_TAG_PATIENT_ID] = patientId;
-    replacements_[DICOM_TAG_PATIENT_NAME] = patientId;
+    ReplaceInternal(DICOM_TAG_PATIENT_ID, patientId);
+    ReplaceInternal(DICOM_TAG_PATIENT_NAME, patientId);
   }
 
   void DicomModification::Apply(ParsedDicomFile& toModify)
@@ -394,7 +459,7 @@
     for (Replacements::const_iterator it = replacements_.begin(); 
          it != replacements_.end(); ++it)
     {
-      toModify.Replace(it->first, it->second, DicomReplaceMode_InsertIfAbsent);
+      toModify.Replace(it->first, *it->second, DicomReplaceMode_InsertIfAbsent);
     }
 
     // (4) Update the DICOM identifiers
--- a/OrthancServer/DicomModification.h	Thu Oct 08 14:52:03 2015 +0200
+++ b/OrthancServer/DicomModification.h	Fri Oct 09 12:29:21 2015 +0200
@@ -36,7 +36,7 @@
 
 namespace Orthanc
 {
-  class DicomModification
+  class DicomModification : public boost::noncopyable
   {
     /**
      * Process:
@@ -47,7 +47,7 @@
 
   private:
     typedef std::set<DicomTag> SetOfTags;
-    typedef std::map<DicomTag, std::string> Replacements;
+    typedef std::map<DicomTag, Json::Value*> Replacements;
     typedef std::map< std::pair<ResourceType, std::string>, std::string>  UidMap;
 
     SetOfTags removals_;
@@ -63,9 +63,18 @@
 
     void MarkNotOrthancAnonymization();
 
+    void ClearReplacements();
+
+    void RemoveInternal(const DicomTag& tag);
+
+    void ReplaceInternal(const DicomTag& tag,
+                         const Json::Value& value);
+
   public:
     DicomModification();
 
+    ~DicomModification();
+
     void Keep(const DicomTag& tag);
 
     void Remove(const DicomTag& tag);
@@ -73,12 +82,14 @@
     bool IsRemoved(const DicomTag& tag) const;
 
     void Replace(const DicomTag& tag,
-                 const std::string& utf8Value,
+                 const Json::Value& value,   // Encoded using UTF-8
                  bool safeForAnonymization = false);
 
     bool IsReplaced(const DicomTag& tag) const;
 
-    const std::string& GetReplacement(const DicomTag& tag) const;
+    const Json::Value& GetReplacement(const DicomTag& tag) const;
+
+    std::string GetReplacementAsString(const DicomTag& tag) const;
 
     void SetRemovePrivateTags(bool removed);
 
--- a/OrthancServer/LuaScripting.cpp	Thu Oct 08 14:52:03 2015 +0200
+++ b/OrthancServer/LuaScripting.cpp	Fri Oct 09 12:29:21 2015 +0200
@@ -270,10 +270,12 @@
     if (operation == "modify")
     {
       LOG(INFO) << "Lua script to modify resource " << parameters["Resource"].asString();
-      DicomModification modification;
-      OrthancRestApi::ParseModifyRequest(modification, parameters);
+      std::auto_ptr<DicomModification> modification(new DicomModification);
+      OrthancRestApi::ParseModifyRequest(*modification, parameters);
 
-      std::auto_ptr<ModifyInstanceCommand> command(new ModifyInstanceCommand(context_, RequestOrigin_Lua, modification));
+      std::auto_ptr<ModifyInstanceCommand> command
+        (new ModifyInstanceCommand(context_, RequestOrigin_Lua, modification.release()));
+
       return command.release();
     }
 
--- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Thu Oct 08 14:52:03 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Fri Oct 09 12:29:21 2015 +0200
@@ -168,7 +168,7 @@
     // curl http://localhost:8042/instances/6e67da51-d119d6ae-c5667437-87b9a8a5-0f07c49f/anonymize -X POST -d '{"Replace":{"PatientName":"hello","0010-0020":"world"},"Keep":["StudyDescription", "SeriesDescription"],"KeepPrivateTags": null,"Remove":["Modality"]}' > Anonymized.dcm
 
     target.SetupAnonymization();
-    std::string patientName = target.GetReplacement(DICOM_TAG_PATIENT_NAME);
+    std::string patientName = target.GetReplacementAsString(DICOM_TAG_PATIENT_NAME);
 
     Json::Value request;
     if (call.ParseJsonRequest(request) && request.isObject())
--- a/OrthancServer/Scheduler/ModifyInstanceCommand.cpp	Thu Oct 08 14:52:03 2015 +0200
+++ b/OrthancServer/Scheduler/ModifyInstanceCommand.cpp	Fri Oct 09 12:29:21 2015 +0200
@@ -39,28 +39,28 @@
 {
   ModifyInstanceCommand::ModifyInstanceCommand(ServerContext& context,
                                                RequestOrigin origin,
-                                               const DicomModification& modification) :
+                                               DicomModification* modification) :
     context_(context),
     origin_(origin),
     modification_(modification)
   {
-    modification_.SetAllowManualIdentifiers(true);
+    modification_->SetAllowManualIdentifiers(true);
 
-    if (modification_.IsReplaced(DICOM_TAG_PATIENT_ID))
+    if (modification_->IsReplaced(DICOM_TAG_PATIENT_ID))
     {
-      modification_.SetLevel(ResourceType_Patient);
+      modification_->SetLevel(ResourceType_Patient);
     }
-    else if (modification_.IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
+    else if (modification_->IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
     {
-      modification_.SetLevel(ResourceType_Study);
+      modification_->SetLevel(ResourceType_Study);
     }
-    else if (modification_.IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID))
+    else if (modification_->IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID))
     {
-      modification_.SetLevel(ResourceType_Series);
+      modification_->SetLevel(ResourceType_Series);
     }
     else
     {
-      modification_.SetLevel(ResourceType_Instance);
+      modification_->SetLevel(ResourceType_Instance);
     }
 
     if (origin_ != RequestOrigin_Lua)
@@ -71,6 +71,15 @@
   }
 
 
+  ModifyInstanceCommand::~ModifyInstanceCommand()
+  {
+    if (modification_)
+    {
+      delete modification_;
+    }
+  }
+
+
   bool ModifyInstanceCommand::Apply(ListOfStrings& outputs,
                                     const ListOfStrings& inputs)
   {
@@ -88,7 +97,7 @@
           modified.reset(lock.GetDicom().Clone());
         }
 
-        modification_.Apply(*modified);
+        modification_->Apply(*modified);
 
         DicomInstanceToStore toStore;
         assert(origin_ == RequestOrigin_Lua);
--- a/OrthancServer/Scheduler/ModifyInstanceCommand.h	Thu Oct 08 14:52:03 2015 +0200
+++ b/OrthancServer/Scheduler/ModifyInstanceCommand.h	Fri Oct 09 12:29:21 2015 +0200
@@ -43,16 +43,18 @@
   private:
     ServerContext& context_;
     RequestOrigin origin_;
-    DicomModification modification_;
+    DicomModification* modification_;
 
   public:
     ModifyInstanceCommand(ServerContext& context,
                           RequestOrigin origin,
-                          const DicomModification& modification);
+                          DicomModification* modification);  // takes the ownership
+
+    virtual ~ModifyInstanceCommand();
 
     const DicomModification& GetModification() const
     {
-      return modification_;
+      return *modification_;
     }
 
     virtual bool Apply(ListOfStrings& outputs,