Mercurial > hg > orthanc
comparison OrthancServer/OrthancRestApi.cpp @ 315:fc856d175d18
modifications
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 21 Dec 2012 17:18:04 +0100 |
parents | 4f17834a50b6 |
children | d526ac73c886 |
comparison
equal
deleted
inserted
replaced
314:4f17834a50b6 | 315:fc856d175d18 |
---|---|
57 | 57 |
58 | 58 |
59 | 59 |
60 namespace Orthanc | 60 namespace Orthanc |
61 { | 61 { |
62 // TODO IMPROVE MULTITHREADING | |
63 static boost::mutex cacheMutex_; | |
64 | |
65 | |
62 // DICOM SCU ---------------------------------------------------------------- | 66 // DICOM SCU ---------------------------------------------------------------- |
63 | 67 |
64 static void ConnectToModality(DicomUserConnection& connection, | 68 static void ConnectToModality(DicomUserConnection& connection, |
65 const std::string& name) | 69 const std::string& name) |
66 { | 70 { |
825 | 829 |
826 // Raw access to the DICOM tags of an instance ------------------------------ | 830 // Raw access to the DICOM tags of an instance ------------------------------ |
827 | 831 |
828 static void GetRawContent(RestApi::GetCall& call) | 832 static void GetRawContent(RestApi::GetCall& call) |
829 { | 833 { |
830 // TODO IMPROVE MULTITHREADING | 834 boost::mutex::scoped_lock lock(cacheMutex_); |
831 static boost::mutex mutex_; | |
832 boost::mutex::scoped_lock lock(mutex_); | |
833 | 835 |
834 RETRIEVE_CONTEXT(call); | 836 RETRIEVE_CONTEXT(call); |
835 std::string id = call.GetUriComponent("id", ""); | 837 std::string id = call.GetUriComponent("id", ""); |
836 ParsedDicomFile& dicom = context.GetDicomFile(id); | 838 ParsedDicomFile& dicom = context.GetDicomFile(id); |
837 dicom.SendPathValue(call.GetOutput(), call.GetTrailingUri()); | 839 dicom.SendPathValue(call.GetOutput(), call.GetTrailingUri()); |
1096 static void AnonymizeOrModifyInstance(Removals removals, | 1098 static void AnonymizeOrModifyInstance(Removals removals, |
1097 Replacements replacements, | 1099 Replacements replacements, |
1098 bool removePrivateTags, | 1100 bool removePrivateTags, |
1099 RestApi::PostCall& call) | 1101 RestApi::PostCall& call) |
1100 { | 1102 { |
1103 boost::mutex::scoped_lock lock(cacheMutex_); | |
1104 | |
1101 RETRIEVE_CONTEXT(call); | 1105 RETRIEVE_CONTEXT(call); |
1102 | 1106 |
1103 std::string id = call.GetUriComponent("id", ""); | 1107 std::string id = call.GetUriComponent("id", ""); |
1104 ParsedDicomFile& dicom = context.GetDicomFile(id); | 1108 ParsedDicomFile& dicom = context.GetDicomFile(id); |
1105 | 1109 |
1152 | 1156 |
1153 static void ModifySeriesInplace(RestApi::PostCall& call) | 1157 static void ModifySeriesInplace(RestApi::PostCall& call) |
1154 { | 1158 { |
1155 RETRIEVE_CONTEXT(call); | 1159 RETRIEVE_CONTEXT(call); |
1156 | 1160 |
1157 typedef std::list<std::string> Instances; | |
1158 Instances instances; | |
1159 std::string id = call.GetUriComponent("id", ""); | |
1160 context.GetIndex().GetChildInstances(instances, id); | |
1161 | |
1162 if (instances.size() == 0) | |
1163 { | |
1164 return; | |
1165 } | |
1166 | |
1167 Removals removals; | 1161 Removals removals; |
1168 Replacements replacements; | 1162 Replacements replacements; |
1169 bool removePrivateTags; | 1163 bool removePrivateTags; |
1170 | 1164 |
1171 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) | 1165 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) |
1172 { | 1166 { |
1167 boost::mutex::scoped_lock lock(cacheMutex_); | |
1168 | |
1169 typedef std::list<std::string> Instances; | |
1170 Instances instances; | |
1171 std::string id = call.GetUriComponent("id", ""); | |
1172 context.GetIndex().GetChildInstances(instances, id); | |
1173 | |
1174 if (instances.size() == 0) | |
1175 { | |
1176 return; | |
1177 } | |
1178 | |
1179 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); | |
1180 | |
1173 std::string newSeriesId; | 1181 std::string newSeriesId; |
1174 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); | |
1175 | |
1176 for (Instances::const_iterator it = instances.begin(); | 1182 for (Instances::const_iterator it = instances.begin(); |
1177 it != instances.end(); it++) | 1183 it != instances.end(); it++) |
1178 { | 1184 { |
1179 LOG(INFO) << "Modifying instance " << *it; | 1185 LOG(INFO) << "Modifying instance " << *it; |
1180 ParsedDicomFile& dicom = context.GetDicomFile(*it); | 1186 ParsedDicomFile& original = context.GetDicomFile(*it); |
1181 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | 1187 std::auto_ptr<ParsedDicomFile> modified(original.Clone()); |
1182 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); | 1188 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); |
1183 | 1189 |
1184 std::string modifiedInstance; | 1190 std::string modifiedInstance; |
1185 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) | 1191 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) |
1186 { | 1192 { |
1187 LOG(ERROR) << "Error while storing a modified instance " << *it; | 1193 LOG(ERROR) << "Error while storing a modified instance " << *it; |
1188 return; | 1194 return; |
1189 } | 1195 } |
1190 | 1196 |
1191 if (newSeriesId.size() == 0 && | 1197 DicomInstanceHasher modifiedHasher = modified->GetHasher(); |
1192 !context.GetIndex().LookupParent(newSeriesId, modifiedInstance)) | 1198 DicomInstanceHasher originalHasher = original.GetHasher(); |
1193 { | 1199 |
1194 throw OrthancException(ErrorCode_InternalError); | 1200 if (newSeriesId.size() == 0) |
1195 } | 1201 { |
1196 | 1202 assert(id == originalHasher.HashSeries()); |
1197 // TODO for the instances and the series: | 1203 newSeriesId = modifiedHasher.HashSeries(); |
1198 // context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id); | 1204 context.GetIndex().SetMetadata(newSeriesId, MetadataType_ModifiedFrom, id); |
1199 } | 1205 } |
1206 | |
1207 assert(*it == originalHasher.HashInstance()); | |
1208 assert(modifiedInstance == modifiedHasher.HashInstance()); | |
1209 context.GetIndex().SetMetadata(modifiedInstance, MetadataType_ModifiedFrom, *it); | |
1210 } | |
1211 | |
1212 context.GetIndex().LogChange(ChangeType_ModifiedSeries, newSeriesId); | |
1200 | 1213 |
1201 assert(newSeriesId.size() != 0); | 1214 assert(newSeriesId.size() != 0); |
1202 Json::Value result = Json::objectValue; | 1215 Json::Value result = Json::objectValue; |
1203 result["ID"] = newSeriesId; | 1216 result["ID"] = newSeriesId; |
1204 result["Path"] = GetBasePath(ResourceType_Series, newSeriesId); | 1217 result["Path"] = GetBasePath(ResourceType_Series, newSeriesId); |
1212 RETRIEVE_CONTEXT(call); | 1225 RETRIEVE_CONTEXT(call); |
1213 | 1226 |
1214 typedef std::list<std::string> Instances; | 1227 typedef std::list<std::string> Instances; |
1215 typedef std::map<std::string, std::string> SeriesUidMap; | 1228 typedef std::map<std::string, std::string> SeriesUidMap; |
1216 | 1229 |
1217 Instances instances; | |
1218 std::string id = call.GetUriComponent("id", ""); | |
1219 context.GetIndex().GetChildInstances(instances, id); | |
1220 | |
1221 if (instances.size() == 0) | |
1222 { | |
1223 return; | |
1224 } | |
1225 | |
1226 SeriesUidMap seriesUidMap; | 1230 SeriesUidMap seriesUidMap; |
1227 Removals removals; | 1231 Removals removals; |
1228 Replacements replacements; | 1232 Replacements replacements; |
1229 bool removePrivateTags; | 1233 bool removePrivateTags; |
1230 | 1234 |
1231 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) | 1235 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) |
1232 { | 1236 { |
1237 boost::mutex::scoped_lock lock(cacheMutex_); | |
1238 | |
1239 Instances instances; | |
1240 std::string id = call.GetUriComponent("id", ""); | |
1241 context.GetIndex().GetChildInstances(instances, id); | |
1242 | |
1243 if (instances.size() == 0) | |
1244 { | |
1245 return; | |
1246 } | |
1247 | |
1233 std::string newStudyId; | 1248 std::string newStudyId; |
1234 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); | 1249 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); |
1235 | 1250 |
1236 for (Instances::const_iterator it = instances.begin(); | 1251 for (Instances::const_iterator it = instances.begin(); |
1237 it != instances.end(); it++) | 1252 it != instances.end(); it++) |
1238 { | 1253 { |
1239 LOG(INFO) << "Modifying instance " << *it; | 1254 LOG(INFO) << "Modifying instance " << *it; |
1240 ParsedDicomFile& dicom = context.GetDicomFile(*it); | 1255 ParsedDicomFile& original = context.GetDicomFile(*it); |
1241 | 1256 |
1242 std::string seriesId; | 1257 std::string seriesUid; |
1243 if (!dicom.GetTagValue(seriesId, DICOM_TAG_SERIES_INSTANCE_UID)) | 1258 if (!original.GetTagValue(seriesUid, DICOM_TAG_SERIES_INSTANCE_UID)) |
1244 { | 1259 { |
1245 throw OrthancException(ErrorCode_InternalError); | 1260 throw OrthancException(ErrorCode_InternalError); |
1246 } | 1261 } |
1247 | 1262 |
1248 SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesId); | 1263 bool isNewSeries; |
1264 SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesUid); | |
1249 if (it2 == seriesUidMap.end()) | 1265 if (it2 == seriesUidMap.end()) |
1250 { | 1266 { |
1251 std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); | 1267 std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); |
1252 seriesUidMap[seriesId] = newSeriesUid; | 1268 seriesUidMap[seriesUid] = newSeriesUid; |
1253 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = newSeriesUid; | 1269 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = newSeriesUid; |
1270 isNewSeries = true; | |
1254 } | 1271 } |
1255 else | 1272 else |
1256 { | 1273 { |
1257 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; | 1274 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; |
1258 } | 1275 isNewSeries = false; |
1259 | 1276 } |
1260 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | 1277 |
1278 std::auto_ptr<ParsedDicomFile> modified(original.Clone()); | |
1261 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); | 1279 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags); |
1262 | 1280 |
1263 std::string modifiedInstance; | 1281 std::string modifiedInstance; |
1264 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) | 1282 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) |
1265 { | 1283 { |
1266 LOG(ERROR) << "Error while storing a modified instance " << *it; | 1284 LOG(ERROR) << "Error while storing a modified instance " << *it; |
1267 return; | 1285 return; |
1268 } | 1286 } |
1269 | 1287 |
1288 DicomInstanceHasher modifiedHasher = modified->GetHasher(); | |
1289 DicomInstanceHasher originalHasher = original.GetHasher(); | |
1290 | |
1291 if (isNewSeries) | |
1292 { | |
1293 context.GetIndex().SetMetadata | |
1294 (modifiedHasher.HashSeries(), MetadataType_ModifiedFrom, originalHasher.HashSeries()); | |
1295 } | |
1296 | |
1270 if (newStudyId.size() == 0) | 1297 if (newStudyId.size() == 0) |
1271 { | 1298 { |
1272 // TODO FOR instances, studies and series: | 1299 newStudyId = modifiedHasher.HashStudy(); |
1273 // context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id); | 1300 context.GetIndex().SetMetadata(newStudyId, MetadataType_ModifiedFrom, originalHasher.HashStudy()); |
1274 | 1301 } |
1275 std::string newSeriesId; | 1302 |
1276 if (!context.GetIndex().LookupParent(newSeriesId, modifiedInstance) || | 1303 assert(*it == originalHasher.HashInstance()); |
1277 !context.GetIndex().LookupParent(newStudyId, newSeriesId)) | 1304 assert(modifiedInstance == modifiedHasher.HashInstance()); |
1278 { | 1305 context.GetIndex().SetMetadata(modifiedInstance, MetadataType_ModifiedFrom, *it); |
1279 throw OrthancException(ErrorCode_InternalError); | 1306 } |
1280 } | 1307 |
1281 } | 1308 context.GetIndex().LogChange(ChangeType_ModifiedStudy, newStudyId); |
1282 } | |
1283 | 1309 |
1284 assert(newStudyId.size() != 0); | 1310 assert(newStudyId.size() != 0); |
1285 Json::Value result = Json::objectValue; | 1311 Json::Value result = Json::objectValue; |
1286 result["ID"] = newStudyId; | 1312 result["ID"] = newStudyId; |
1287 result["Path"] = GetBasePath(ResourceType_Study, newStudyId); | 1313 result["Path"] = GetBasePath(ResourceType_Study, newStudyId); |