diff OrthancServer/OrthancRestApi.cpp @ 306:326d5a4a5af3

modification of instances
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 Dec 2012 16:44:50 +0100
parents 86bb79522f19
children 485db3b07740
line wrap: on
line diff
--- a/OrthancServer/OrthancRestApi.cpp	Thu Dec 20 13:01:46 2012 +0100
+++ b/OrthancServer/OrthancRestApi.cpp	Thu Dec 20 16:44:50 2012 +0100
@@ -842,16 +842,23 @@
   // Modification of DICOM instances ------------------------------------------
 
   static void ReplaceInstanceInternal(ParsedDicomFile& toModify,
+                                      const Json::Value& removals,
                                       const Json::Value& replacements,
                                       DicomReplaceMode mode)
   {
-    if (!replacements.isObject())
+    if (!replacements.isObject() ||
+        !removals.isArray())
     {
       throw OrthancException(ErrorCode_BadRequest);
     }
 
+    for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++)
+    {
+      DicomTag tag = FromDcmtkBridge::ParseTag(removals[i].asString());
+      toModify.Remove(tag);
+    }
+
     Json::Value::Members members = replacements.getMemberNames();
-
     for (size_t i = 0; i < members.size(); i++)
     {
       const std::string& name = members[i];
@@ -866,8 +873,35 @@
     toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent);
   }
 
+ 
+  static bool ParseModifyRequest(Json::Value& removals,
+                                 Json::Value& replacements,
+                                 const RestApi::PostCall& call)
+  {
+    Json::Value request;
+    if (call.ParseJsonRequest(request) &&
+        request.isObject())
+    {
+      removals = Json::arrayValue;
+      replacements = Json::objectValue;
 
-  
+      if (request.isMember("Remove"))
+      {
+        removals = request["Remove"];
+      }
+
+      if (request.isMember("Replace"))
+      {
+        replacements = request["Replace"];
+      }
+
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
 
 
   static void ModifyInstance(RestApi::PostCall& call)
@@ -877,18 +911,98 @@
     std::string id = call.GetUriComponent("id", "");
     ParsedDicomFile& dicom = context.GetDicomFile(id);
     
-    Json::Value request;
-    if (call.ParseJsonRequest(request))
+    Json::Value removals, replacements;
+    if (ParseModifyRequest(removals, replacements, call))
     {
       std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
-      ReplaceInstanceInternal(*modified, request, DicomReplaceMode_InsertIfAbsent);
+      ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
+      context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id);
       modified->Answer(call.GetOutput());
     }
+  }
+
+
+  template <enum ResourceType resourceType>
+  static void ModifyInplace(RestApi::PostCall& call)
+  {
+    typedef std::list<std::string> Instances;
+
+    RETRIEVE_CONTEXT(call);
+    
+    Instances instances;
+    std::string id = call.GetUriComponent("id", "");
+    context.GetIndex().GetChildInstances(instances, id);
+
+    if (instances.size() == 0)
+    {
+      return;
+    }
 
-    /*std::string studyUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
-    std::string seriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
-    modified->Replace(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid);
-    modified->Replace(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);*/
+    Json::Value removals, replacements;
+    if (ParseModifyRequest(removals, replacements, call))
+    {
+      switch (resourceType)
+      {
+        // DO NOT ADD "break" OR CHANGE THE ORDER BELOW
+        case ResourceType_Patient:
+          replacements["0010-0020"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient);
+
+        case ResourceType_Study:
+          replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
+
+        case ResourceType_Series:
+          replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
+          break;
+          
+        default:
+          throw OrthancException(ErrorCode_InternalError);
+      }
+
+      std::string modifiedId;
+      for (Instances::const_iterator it = instances.begin(); 
+           it != instances.end(); it++)
+      {
+        LOG(INFO) << "Modifying instance " << *it;
+        ParsedDicomFile& dicom = context.GetDicomFile(*it);
+        std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
+        ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
+
+        if (context.Store(modifiedId, modified->GetDicom()) != StoreStatus_Success)
+        {
+          LOG(ERROR) << "Error while modifying the instance " << *it;
+          return;
+        }
+
+        context.GetIndex().SetMetadata(modifiedId, MetadataType_ModifiedFrom, *it);
+      }
+
+
+      int level;
+      std::string id;
+      switch (resourceType)
+      {
+        case ResourceType_Series:  level = 1; break;
+        case ResourceType_Study:   level = 2; break;
+        case ResourceType_Patient: level = 3; break;
+        default:
+          throw OrthancException(ErrorCode_InternalError);
+      }
+
+      for (int i = 0; i < level; i++)
+      {
+        if (!context.GetIndex().LookupParent(id, modifiedId))
+        {
+          throw OrthancException(ErrorCode_InternalError);
+        }
+        
+        modifiedId = id;
+      }
+
+      Json::Value result = Json::objectValue;
+      result["ID"] = id;
+      result["Path"] = GetBasePath(resourceType, id);
+      call.GetOutput().AnswerJson(result);
+    }
   }
 
 
@@ -949,5 +1063,8 @@
     Register("/modalities/{id}/store", DicomStore);
 
     Register("/instances/{id}/modify", ModifyInstance);
+    Register("/series/{id}/modify", ModifyInplace<ResourceType_Series>);
+    Register("/studies/{id}/modify", ModifyInplace<ResourceType_Study>);
+    Register("/patients/{id}/modify", ModifyInplace<ResourceType_Patient>);
   }
 }