Mercurial > hg > orthanc
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 } |