Mercurial > hg > orthanc
comparison OrthancServer/OrthancRestApi.cpp @ 312:1642a354fec8
flexible
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 21 Dec 2012 13:36:50 +0100 |
parents | 26efccdff583 |
children | 60429bb2551e |
comparison
equal
deleted
inserted
replaced
311:26efccdff583 | 312:1642a354fec8 |
---|---|
848 } | 848 } |
849 | 849 |
850 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, | 850 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, |
851 const Removals& removals, | 851 const Removals& removals, |
852 const Replacements& replacements, | 852 const Replacements& replacements, |
853 DicomReplaceMode mode) | 853 DicomReplaceMode mode, |
854 { | 854 bool removePrivateTags) |
855 { | |
856 if (removePrivateTags) | |
857 { | |
858 toModify.RemovePrivateTags(); | |
859 } | |
860 | |
855 for (Removals::const_iterator it = removals.begin(); | 861 for (Removals::const_iterator it = removals.begin(); |
856 it != removals.end(); it++) | 862 it != removals.end(); it++) |
857 { | 863 { |
858 toModify.Remove(*it); | 864 toModify.Remove(*it); |
859 } | 865 } |
918 | 924 |
919 | 925 |
920 static void SetupAnonymization(Removals& removals, | 926 static void SetupAnonymization(Removals& removals, |
921 Replacements& replacements) | 927 Replacements& replacements) |
922 { | 928 { |
923 removals.clear(); | |
924 replacements.clear(); | |
925 | |
926 // This is Table E.1-1 from PS 3.15-2008 - DICOM Part 15: Security and System Management Profiles | 929 // This is Table E.1-1 from PS 3.15-2008 - DICOM Part 15: Security and System Management Profiles |
927 removals.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID | 930 removals.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID |
928 //removals.insert(DicomTag(0x0008, 0x0018)); // SOP Instance UID => set by ReplaceInstanceInternal() | 931 //removals.insert(DicomTag(0x0008, 0x0018)); // SOP Instance UID => set by ReplaceInstanceInternal() |
929 removals.insert(DicomTag(0x0008, 0x0050)); // Accession Number | 932 removals.insert(DicomTag(0x0008, 0x0050)); // Accession Number |
930 removals.insert(DicomTag(0x0008, 0x0080)); // Institution Name | 933 removals.insert(DicomTag(0x0008, 0x0080)); // Institution Name |
990 } | 993 } |
991 | 994 |
992 | 995 |
993 static bool ParseModifyRequest(Removals& removals, | 996 static bool ParseModifyRequest(Removals& removals, |
994 Replacements& replacements, | 997 Replacements& replacements, |
998 bool& removePrivateTags, | |
995 const RestApi::PostCall& call) | 999 const RestApi::PostCall& call) |
996 { | 1000 { |
1001 removePrivateTags = false; | |
997 Json::Value request; | 1002 Json::Value request; |
998 if (call.ParseJsonRequest(request) && | 1003 if (call.ParseJsonRequest(request) && |
999 request.isObject()) | 1004 request.isObject()) |
1000 { | 1005 { |
1001 Json::Value removalsPart = Json::arrayValue; | 1006 Json::Value removalsPart = Json::arrayValue; |
1009 if (request.isMember("Replace")) | 1014 if (request.isMember("Replace")) |
1010 { | 1015 { |
1011 replacementsPart = request["Replace"]; | 1016 replacementsPart = request["Replace"]; |
1012 } | 1017 } |
1013 | 1018 |
1019 if (request.isMember("RemovePrivateTags")) | |
1020 { | |
1021 removePrivateTags = true; | |
1022 } | |
1023 | |
1014 ParseRemovals(removals, removalsPart); | 1024 ParseRemovals(removals, removalsPart); |
1015 ParseReplacements(replacements, replacementsPart); | 1025 ParseReplacements(replacements, replacementsPart); |
1016 | 1026 |
1017 return true; | 1027 return true; |
1018 } | 1028 } |
1033 Json::Value request; | 1043 Json::Value request; |
1034 if (call.ParseJsonRequest(request) && | 1044 if (call.ParseJsonRequest(request) && |
1035 request.isObject()) | 1045 request.isObject()) |
1036 { | 1046 { |
1037 Json::Value keepPart = Json::arrayValue; | 1047 Json::Value keepPart = Json::arrayValue; |
1048 Json::Value removalsPart = Json::arrayValue; | |
1049 Json::Value replacementsPart = Json::objectValue; | |
1050 | |
1038 if (request.isMember("Keep")) | 1051 if (request.isMember("Keep")) |
1039 { | 1052 { |
1040 keepPart = request["Keep"]; | 1053 keepPart = request["Keep"]; |
1041 } | 1054 } |
1042 | 1055 |
1043 if (request.isMember("KeepPrivateTags")) | 1056 if (request.isMember("KeepPrivateTags")) |
1044 { | 1057 { |
1045 removePrivateTags = false; | 1058 removePrivateTags = false; |
1059 } | |
1060 | |
1061 if (request.isMember("Replace")) | |
1062 { | |
1063 replacementsPart = request["Replace"]; | |
1046 } | 1064 } |
1047 | 1065 |
1048 Removals toKeep; | 1066 Removals toKeep; |
1049 ParseRemovals(toKeep, keepPart); | 1067 ParseRemovals(toKeep, keepPart); |
1050 | 1068 |
1053 for (Removals::iterator it = toKeep.begin(); it != toKeep.end(); it++) | 1071 for (Removals::iterator it = toKeep.begin(); it != toKeep.end(); it++) |
1054 { | 1072 { |
1055 removals.erase(*it); | 1073 removals.erase(*it); |
1056 } | 1074 } |
1057 | 1075 |
1076 Removals additionalRemovals; | |
1077 ParseRemovals(additionalRemovals, removalsPart); | |
1078 | |
1079 for (Removals::iterator it = additionalRemovals.begin(); | |
1080 it != additionalRemovals.end(); it++) | |
1081 { | |
1082 removals.erase(*it); | |
1083 } | |
1084 | |
1085 ParseReplacements(replacements, replacementsPart); | |
1086 | |
1058 return true; | 1087 return true; |
1059 } | 1088 } |
1060 else | 1089 else |
1061 { | 1090 { |
1062 return false; | 1091 return false; |
1063 } | 1092 } |
1064 } | 1093 } |
1065 | 1094 |
1066 | 1095 |
1067 static void ModifyInstance(RestApi::PostCall& call) | 1096 static void ModifyInstance(RestApi::PostCall& call) |
1068 { | |
1069 RETRIEVE_CONTEXT(call); | |
1070 | |
1071 std::string id = call.GetUriComponent("id", ""); | |
1072 ParsedDicomFile& dicom = context.GetDicomFile(id); | |
1073 | |
1074 Removals removals; | |
1075 Replacements replacements; | |
1076 | |
1077 if (ParseModifyRequest(removals, replacements, call)) | |
1078 { | |
1079 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | |
1080 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); | |
1081 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id); | |
1082 modified->Answer(call.GetOutput()); | |
1083 } | |
1084 } | |
1085 | |
1086 | |
1087 static void AnonymizeInstance(RestApi::PostCall& call) | |
1088 { | 1097 { |
1089 RETRIEVE_CONTEXT(call); | 1098 RETRIEVE_CONTEXT(call); |
1090 | 1099 |
1091 std::string id = call.GetUriComponent("id", ""); | 1100 std::string id = call.GetUriComponent("id", ""); |
1092 ParsedDicomFile& dicom = context.GetDicomFile(id); | 1101 ParsedDicomFile& dicom = context.GetDicomFile(id); |
1093 | 1102 |
1094 Removals removals; | 1103 Removals removals; |
1095 Replacements replacements; | 1104 Replacements replacements; |
1096 bool removePrivateTags; | 1105 bool removePrivateTags; |
1097 | 1106 |
1107 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) | |
1108 { | |
1109 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | |
1110 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); | |
1111 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id); | |
1112 modified->Answer(call.GetOutput()); | |
1113 } | |
1114 } | |
1115 | |
1116 | |
1117 static void AnonymizeInstance(RestApi::PostCall& call) | |
1118 { | |
1119 RETRIEVE_CONTEXT(call); | |
1120 | |
1121 std::string id = call.GetUriComponent("id", ""); | |
1122 ParsedDicomFile& dicom = context.GetDicomFile(id); | |
1123 | |
1124 Removals removals; | |
1125 Replacements replacements; | |
1126 bool removePrivateTags; | |
1127 | |
1098 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) | 1128 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) |
1099 { | 1129 { |
1100 // Generate random Patient's name | 1130 // Generate random Patient's Name if none is specified |
1101 removals.erase(DicomTag(0x0010, 0x0010)); | 1131 if (replacements.find(DicomTag(0x0010, 0x0010)) == replacements.end()) |
1102 replacements.insert(std::make_pair(DicomTag(0x0010, 0x0010), GeneratePatientName(context))); | 1132 { |
1103 | 1133 replacements.insert(std::make_pair(DicomTag(0x0010, 0x0010), GeneratePatientName(context))); |
1104 // Generate random Patient ID | 1134 } |
1105 removals.erase(DICOM_TAG_PATIENT_ID); | 1135 |
1106 replacements.insert(std::make_pair(DICOM_TAG_PATIENT_ID, | 1136 // Generate random Patient's ID if none is specified |
1107 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient))); | 1137 if (replacements.find(DICOM_TAG_PATIENT_ID) == replacements.end()) |
1138 { | |
1139 replacements.insert(std::make_pair(DICOM_TAG_PATIENT_ID, | |
1140 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient))); | |
1141 } | |
1108 | 1142 |
1109 std::auto_ptr<ParsedDicomFile> anonymized(dicom.Clone()); | 1143 std::auto_ptr<ParsedDicomFile> anonymized(dicom.Clone()); |
1110 | 1144 ReplaceInstanceInternal(*anonymized, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); |
1111 if (removePrivateTags) | |
1112 { | |
1113 anonymized->RemovePrivateTags(); | |
1114 } | |
1115 | |
1116 ReplaceInstanceInternal(*anonymized, removals, replacements, DicomReplaceMode_InsertIfAbsent); | |
1117 context.GetIndex().SetMetadata(id, MetadataType_AnonymizedFrom, id); | 1145 context.GetIndex().SetMetadata(id, MetadataType_AnonymizedFrom, id); |
1118 | 1146 |
1119 anonymized->Answer(call.GetOutput()); | 1147 anonymized->Answer(call.GetOutput()); |
1120 } | 1148 } |
1121 } | 1149 } |
1135 return; | 1163 return; |
1136 } | 1164 } |
1137 | 1165 |
1138 Removals removals; | 1166 Removals removals; |
1139 Replacements replacements; | 1167 Replacements replacements; |
1140 | 1168 bool removePrivateTags; |
1141 if (ParseModifyRequest(removals, replacements, call)) | 1169 |
1170 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) | |
1142 { | 1171 { |
1143 std::string newSeriesId; | 1172 std::string newSeriesId; |
1144 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); | 1173 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); |
1145 | 1174 |
1146 for (Instances::const_iterator it = instances.begin(); | 1175 for (Instances::const_iterator it = instances.begin(); |
1147 it != instances.end(); it++) | 1176 it != instances.end(); it++) |
1148 { | 1177 { |
1149 LOG(INFO) << "Modifying instance " << *it; | 1178 LOG(INFO) << "Modifying instance " << *it; |
1150 ParsedDicomFile& dicom = context.GetDicomFile(*it); | 1179 ParsedDicomFile& dicom = context.GetDicomFile(*it); |
1151 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | 1180 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); |
1152 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); | 1181 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); |
1153 | 1182 |
1154 std::string modifiedInstance; | 1183 std::string modifiedInstance; |
1155 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) | 1184 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) |
1156 { | 1185 { |
1157 LOG(ERROR) << "Error while storing a modified instance " << *it; | 1186 LOG(ERROR) << "Error while storing a modified instance " << *it; |
1191 } | 1220 } |
1192 | 1221 |
1193 SeriesUidMap seriesUidMap; | 1222 SeriesUidMap seriesUidMap; |
1194 Removals removals; | 1223 Removals removals; |
1195 Replacements replacements; | 1224 Replacements replacements; |
1196 | 1225 bool removePrivateTags; |
1197 if (ParseModifyRequest(removals, replacements, call)) | 1226 |
1227 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) | |
1198 { | 1228 { |
1199 std::string newStudyId; | 1229 std::string newStudyId; |
1200 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); | 1230 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); |
1201 | 1231 |
1202 for (Instances::const_iterator it = instances.begin(); | 1232 for (Instances::const_iterator it = instances.begin(); |
1222 { | 1252 { |
1223 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; | 1253 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; |
1224 } | 1254 } |
1225 | 1255 |
1226 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | 1256 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); |
1227 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); | 1257 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); |
1228 | 1258 |
1229 std::string modifiedInstance; | 1259 std::string modifiedInstance; |
1230 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) | 1260 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) |
1231 { | 1261 { |
1232 LOG(ERROR) << "Error while storing a modified instance " << *it; | 1262 LOG(ERROR) << "Error while storing a modified instance " << *it; |