comparison 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
comparison
equal deleted inserted replaced
305:86bb79522f19 306:326d5a4a5af3
840 840
841 841
842 // Modification of DICOM instances ------------------------------------------ 842 // Modification of DICOM instances ------------------------------------------
843 843
844 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, 844 static void ReplaceInstanceInternal(ParsedDicomFile& toModify,
845 const Json::Value& removals,
845 const Json::Value& replacements, 846 const Json::Value& replacements,
846 DicomReplaceMode mode) 847 DicomReplaceMode mode)
847 { 848 {
848 if (!replacements.isObject()) 849 if (!replacements.isObject() ||
850 !removals.isArray())
849 { 851 {
850 throw OrthancException(ErrorCode_BadRequest); 852 throw OrthancException(ErrorCode_BadRequest);
851 } 853 }
852 854
855 for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++)
856 {
857 DicomTag tag = FromDcmtkBridge::ParseTag(removals[i].asString());
858 toModify.Remove(tag);
859 }
860
853 Json::Value::Members members = replacements.getMemberNames(); 861 Json::Value::Members members = replacements.getMemberNames();
854
855 for (size_t i = 0; i < members.size(); i++) 862 for (size_t i = 0; i < members.size(); i++)
856 { 863 {
857 const std::string& name = members[i]; 864 const std::string& name = members[i];
858 std::string value = replacements[name].asString(); 865 std::string value = replacements[name].asString();
859 866
864 // A new SOP instance UID is automatically generated 871 // A new SOP instance UID is automatically generated
865 std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance); 872 std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance);
866 toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent); 873 toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent);
867 } 874 }
868 875
869 876
870 877 static bool ParseModifyRequest(Json::Value& removals,
878 Json::Value& replacements,
879 const RestApi::PostCall& call)
880 {
881 Json::Value request;
882 if (call.ParseJsonRequest(request) &&
883 request.isObject())
884 {
885 removals = Json::arrayValue;
886 replacements = Json::objectValue;
887
888 if (request.isMember("Remove"))
889 {
890 removals = request["Remove"];
891 }
892
893 if (request.isMember("Replace"))
894 {
895 replacements = request["Replace"];
896 }
897
898 return true;
899 }
900 else
901 {
902 return false;
903 }
904 }
871 905
872 906
873 static void ModifyInstance(RestApi::PostCall& call) 907 static void ModifyInstance(RestApi::PostCall& call)
874 { 908 {
875 RETRIEVE_CONTEXT(call); 909 RETRIEVE_CONTEXT(call);
876 910
877 std::string id = call.GetUriComponent("id", ""); 911 std::string id = call.GetUriComponent("id", "");
878 ParsedDicomFile& dicom = context.GetDicomFile(id); 912 ParsedDicomFile& dicom = context.GetDicomFile(id);
879 913
880 Json::Value request; 914 Json::Value removals, replacements;
881 if (call.ParseJsonRequest(request)) 915 if (ParseModifyRequest(removals, replacements, call))
882 { 916 {
883 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); 917 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
884 ReplaceInstanceInternal(*modified, request, DicomReplaceMode_InsertIfAbsent); 918 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
919 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id);
885 modified->Answer(call.GetOutput()); 920 modified->Answer(call.GetOutput());
886 } 921 }
887 922 }
888 /*std::string studyUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); 923
889 std::string seriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); 924
890 modified->Replace(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid); 925 template <enum ResourceType resourceType>
891 modified->Replace(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);*/ 926 static void ModifyInplace(RestApi::PostCall& call)
927 {
928 typedef std::list<std::string> Instances;
929
930 RETRIEVE_CONTEXT(call);
931
932 Instances instances;
933 std::string id = call.GetUriComponent("id", "");
934 context.GetIndex().GetChildInstances(instances, id);
935
936 if (instances.size() == 0)
937 {
938 return;
939 }
940
941 Json::Value removals, replacements;
942 if (ParseModifyRequest(removals, replacements, call))
943 {
944 switch (resourceType)
945 {
946 // DO NOT ADD "break" OR CHANGE THE ORDER BELOW
947 case ResourceType_Patient:
948 replacements["0010-0020"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient);
949
950 case ResourceType_Study:
951 replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
952
953 case ResourceType_Series:
954 replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
955 break;
956
957 default:
958 throw OrthancException(ErrorCode_InternalError);
959 }
960
961 std::string modifiedId;
962 for (Instances::const_iterator it = instances.begin();
963 it != instances.end(); it++)
964 {
965 LOG(INFO) << "Modifying instance " << *it;
966 ParsedDicomFile& dicom = context.GetDicomFile(*it);
967 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
968 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
969
970 if (context.Store(modifiedId, modified->GetDicom()) != StoreStatus_Success)
971 {
972 LOG(ERROR) << "Error while modifying the instance " << *it;
973 return;
974 }
975
976 context.GetIndex().SetMetadata(modifiedId, MetadataType_ModifiedFrom, *it);
977 }
978
979
980 int level;
981 std::string id;
982 switch (resourceType)
983 {
984 case ResourceType_Series: level = 1; break;
985 case ResourceType_Study: level = 2; break;
986 case ResourceType_Patient: level = 3; break;
987 default:
988 throw OrthancException(ErrorCode_InternalError);
989 }
990
991 for (int i = 0; i < level; i++)
992 {
993 if (!context.GetIndex().LookupParent(id, modifiedId))
994 {
995 throw OrthancException(ErrorCode_InternalError);
996 }
997
998 modifiedId = id;
999 }
1000
1001 Json::Value result = Json::objectValue;
1002 result["ID"] = id;
1003 result["Path"] = GetBasePath(resourceType, id);
1004 call.GetOutput().AnswerJson(result);
1005 }
892 } 1006 }
893 1007
894 1008
895 1009
896 // Registration of the various REST handlers -------------------------------- 1010 // Registration of the various REST handlers --------------------------------
947 Register("/modalities/{id}/find-series", DicomFindSeries); 1061 Register("/modalities/{id}/find-series", DicomFindSeries);
948 Register("/modalities/{id}/find", DicomFind); 1062 Register("/modalities/{id}/find", DicomFind);
949 Register("/modalities/{id}/store", DicomStore); 1063 Register("/modalities/{id}/store", DicomStore);
950 1064
951 Register("/instances/{id}/modify", ModifyInstance); 1065 Register("/instances/{id}/modify", ModifyInstance);
1066 Register("/series/{id}/modify", ModifyInplace<ResourceType_Series>);
1067 Register("/studies/{id}/modify", ModifyInplace<ResourceType_Study>);
1068 Register("/patients/{id}/modify", ModifyInplace<ResourceType_Patient>);
952 } 1069 }
953 } 1070 }