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);