comparison OrthancServer/OrthancRestApi.cpp @ 308:fbf2b2282086

inplace modification of series and studies
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Dec 2012 10:44:26 +0100
parents 485db3b07740
children 6ab6cdeedf4e
comparison
equal deleted inserted replaced
307:485db3b07740 308:fbf2b2282086
920 modified->Answer(call.GetOutput()); 920 modified->Answer(call.GetOutput());
921 } 921 }
922 } 922 }
923 923
924 924
925 template <enum ResourceType resourceType> 925 static void ModifySeriesInplace(RestApi::PostCall& call)
926 static void ModifyInplace(RestApi::PostCall& call) 926 {
927 { 927 RETRIEVE_CONTEXT(call);
928
928 typedef std::list<std::string> Instances; 929 typedef std::list<std::string> Instances;
929
930 RETRIEVE_CONTEXT(call);
931
932 Instances instances; 930 Instances instances;
933 std::string id = call.GetUriComponent("id", ""); 931 std::string id = call.GetUriComponent("id", "");
934 context.GetIndex().GetChildInstances(instances, id); 932 context.GetIndex().GetChildInstances(instances, id);
935 933
936 if (instances.size() == 0) 934 if (instances.size() == 0)
937 { 935 {
938 return; 936 return;
939 } 937 }
940 938
941 // TODO RECONSTRUCT A HIERARCHY OF UIDs
942
943 Json::Value removals, replacements; 939 Json::Value removals, replacements;
944 if (ParseModifyRequest(removals, replacements, call)) 940 if (ParseModifyRequest(removals, replacements, call))
945 { 941 {
946 switch (resourceType) 942 std::string newSeriesId;
947 { 943 replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
948 // DO NOT ADD "break" OR CHANGE THE ORDER BELOW 944
949 case ResourceType_Patient:
950 replacements["0010-0020"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient);
951
952 case ResourceType_Study:
953 replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
954
955 case ResourceType_Series:
956 replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
957 break;
958
959 default:
960 throw OrthancException(ErrorCode_InternalError);
961 }
962
963 std::string modifiedId;
964 for (Instances::const_iterator it = instances.begin(); 945 for (Instances::const_iterator it = instances.begin();
965 it != instances.end(); it++) 946 it != instances.end(); it++)
966 { 947 {
967 LOG(INFO) << "Modifying instance " << *it; 948 LOG(INFO) << "Modifying instance " << *it;
968 ParsedDicomFile& dicom = context.GetDicomFile(*it); 949 ParsedDicomFile& dicom = context.GetDicomFile(*it);
969 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); 950 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
970 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); 951 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
971 952
972 if (context.Store(modifiedId, modified->GetDicom()) != StoreStatus_Success) 953 std::string modifiedInstance;
973 { 954 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success)
974 LOG(ERROR) << "Error while modifying the instance " << *it; 955 {
956 LOG(ERROR) << "Error while storing a modified instance " << *it;
975 return; 957 return;
976 } 958 }
977 959
978 context.GetIndex().SetMetadata(modifiedId, MetadataType_ModifiedFrom, *it); 960 if (newSeriesId.size() == 0 &&
979 } 961 !context.GetIndex().LookupParent(newSeriesId, modifiedInstance))
980 962 {
981
982 int level;
983 std::string id;
984 switch (resourceType)
985 {
986 case ResourceType_Series: level = 1; break;
987 case ResourceType_Study: level = 2; break;
988 case ResourceType_Patient: level = 3; break;
989 default:
990 throw OrthancException(ErrorCode_InternalError); 963 throw OrthancException(ErrorCode_InternalError);
991 } 964 }
992 965 }
993 for (int i = 0; i < level; i++) 966
994 { 967 assert(newSeriesId.size() != 0);
995 if (!context.GetIndex().LookupParent(id, modifiedId)) 968 Json::Value result = Json::objectValue;
969 result["ID"] = newSeriesId;
970 result["Path"] = GetBasePath(ResourceType_Series, newSeriesId);
971 call.GetOutput().AnswerJson(result);
972 }
973 }
974
975
976 static void ModifyStudyInplace(RestApi::PostCall& call)
977 {
978 RETRIEVE_CONTEXT(call);
979
980 typedef std::list<std::string> Instances;
981 typedef std::map<std::string, std::string> SeriesUidMap;
982
983 Instances instances;
984 std::string id = call.GetUriComponent("id", "");
985 context.GetIndex().GetChildInstances(instances, id);
986
987 if (instances.size() == 0)
988 {
989 return;
990 }
991
992 SeriesUidMap seriesUidMap;
993
994 Json::Value removals, replacements;
995 if (ParseModifyRequest(removals, replacements, call))
996 {
997 std::string newStudyId;
998 replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
999
1000 for (Instances::const_iterator it = instances.begin();
1001 it != instances.end(); it++)
1002 {
1003 LOG(INFO) << "Modifying instance " << *it;
1004 ParsedDicomFile& dicom = context.GetDicomFile(*it);
1005
1006 std::string seriesId;
1007 if (!dicom.GetTagValue(seriesId, DICOM_TAG_SERIES_INSTANCE_UID))
996 { 1008 {
997 throw OrthancException(ErrorCode_InternalError); 1009 throw OrthancException(ErrorCode_InternalError);
998 } 1010 }
999 1011
1000 modifiedId = id; 1012 SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesId);
1001 } 1013 if (it2 == seriesUidMap.end())
1002 1014 {
1015 std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
1016 seriesUidMap[seriesId] = newSeriesUid;
1017 replacements["0020-000e"] = newSeriesUid;
1018 }
1019 else
1020 {
1021 replacements["0020-000e"] = it2->second;
1022 }
1023
1024 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
1025 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
1026
1027 std::string modifiedInstance;
1028 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success)
1029 {
1030 LOG(ERROR) << "Error while storing a modified instance " << *it;
1031 return;
1032 }
1033
1034 if (newStudyId.size() == 0)
1035 {
1036 std::string newSeriesId;
1037 if (!context.GetIndex().LookupParent(newSeriesId, modifiedInstance) ||
1038 !context.GetIndex().LookupParent(newStudyId, newSeriesId))
1039 {
1040 throw OrthancException(ErrorCode_InternalError);
1041 }
1042 }
1043 }
1044
1045 assert(newStudyId.size() != 0);
1003 Json::Value result = Json::objectValue; 1046 Json::Value result = Json::objectValue;
1004 result["ID"] = id; 1047 result["ID"] = newStudyId;
1005 result["Path"] = GetBasePath(resourceType, id); 1048 result["Path"] = GetBasePath(ResourceType_Study, newStudyId);
1006 call.GetOutput().AnswerJson(result); 1049 call.GetOutput().AnswerJson(result);
1007 } 1050 }
1008 } 1051 }
1052
1009 1053
1010 1054
1011 1055
1012 // Registration of the various REST handlers -------------------------------- 1056 // Registration of the various REST handlers --------------------------------
1013 1057
1063 Register("/modalities/{id}/find-series", DicomFindSeries); 1107 Register("/modalities/{id}/find-series", DicomFindSeries);
1064 Register("/modalities/{id}/find", DicomFind); 1108 Register("/modalities/{id}/find", DicomFind);
1065 Register("/modalities/{id}/store", DicomStore); 1109 Register("/modalities/{id}/store", DicomStore);
1066 1110
1067 Register("/instances/{id}/modify", ModifyInstance); 1111 Register("/instances/{id}/modify", ModifyInstance);
1068 Register("/series/{id}/modify", ModifyInplace<ResourceType_Series>); 1112 Register("/series/{id}/modify", ModifySeriesInplace);
1069 Register("/studies/{id}/modify", ModifyInplace<ResourceType_Study>); 1113 Register("/studies/{id}/modify", ModifyStudyInplace);
1070 Register("/patients/{id}/modify", ModifyInplace<ResourceType_Patient>);
1071 } 1114 }
1072 } 1115 }