Mercurial > hg > orthanc
comparison OrthancServer/ServerJobs/MergeStudyJob.cpp @ 3941:771dbd9eb3bd transcoding
class CleaningInstancesJob to share cleaning code by merge/split jobs
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 18 May 2020 18:20:19 +0200 |
parents | 3661e2a72482 |
children |
comparison
equal
deleted
inserted
replaced
3940:3661e2a72482 | 3941:771dbd9eb3bd |
---|---|
46 // Generate a target SeriesInstanceUID for this series | 46 // Generate a target SeriesInstanceUID for this series |
47 seriesUidMap_[series] = FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series); | 47 seriesUidMap_[series] = FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Series); |
48 | 48 |
49 // Add all the instances of the series as to be processed | 49 // Add all the instances of the series as to be processed |
50 std::list<std::string> instances; | 50 std::list<std::string> instances; |
51 context_.GetIndex().GetChildren(instances, series); | 51 GetContext().GetIndex().GetChildren(instances, series); |
52 | 52 |
53 for (std::list<std::string>::const_iterator | 53 for (std::list<std::string>::const_iterator |
54 it = instances.begin(); it != instances.end(); ++it) | 54 it = instances.begin(); it != instances.end(); ++it) |
55 { | 55 { |
56 AddInstance(*it); | 56 AddInstance(*it); |
66 "Cannot merge a study into the same study: " + study); | 66 "Cannot merge a study into the same study: " + study); |
67 } | 67 } |
68 else | 68 else |
69 { | 69 { |
70 std::list<std::string> series; | 70 std::list<std::string> series; |
71 context_.GetIndex().GetChildren(series, study); | 71 GetContext().GetIndex().GetChildren(series, study); |
72 | 72 |
73 for (std::list<std::string>::const_iterator | 73 for (std::list<std::string>::const_iterator |
74 it = series.begin(); it != series.end(); ++it) | 74 it = series.begin(); it != series.end(); ++it) |
75 { | 75 { |
76 AddSourceSeriesInternal(*it); | 76 AddSourceSeriesInternal(*it); |
93 | 93 |
94 std::unique_ptr<ParsedDicomFile> modified; | 94 std::unique_ptr<ParsedDicomFile> modified; |
95 | 95 |
96 try | 96 try |
97 { | 97 { |
98 ServerContext::DicomCacheLocker locker(context_, instance); | 98 ServerContext::DicomCacheLocker locker(GetContext(), instance); |
99 modified.reset(locker.GetDicom().Clone(true)); | 99 modified.reset(locker.GetDicom().Clone(true)); |
100 } | 100 } |
101 catch (OrthancException&) | 101 catch (OrthancException&) |
102 { | 102 { |
103 LOG(WARNING) << "An instance was removed after the job was issued: " << instance; | 103 LOG(WARNING) << "An instance was removed after the job was issued: " << instance; |
149 DicomInstanceToStore toStore; | 149 DicomInstanceToStore toStore; |
150 toStore.SetOrigin(origin_); | 150 toStore.SetOrigin(origin_); |
151 toStore.SetParsedDicomFile(*modified); | 151 toStore.SetParsedDicomFile(*modified); |
152 | 152 |
153 std::string modifiedInstance; | 153 std::string modifiedInstance; |
154 if (context_.Store(modifiedInstance, toStore, | 154 if (GetContext().Store(modifiedInstance, toStore, |
155 StoreInstanceMode_Default) != StoreStatus_Success) | 155 StoreInstanceMode_Default) != StoreStatus_Success) |
156 { | 156 { |
157 LOG(ERROR) << "Error while storing a modified instance " << instance; | 157 LOG(ERROR) << "Error while storing a modified instance " << instance; |
158 return false; | 158 return false; |
159 } | 159 } |
160 | 160 |
161 return true; | 161 return true; |
162 } | 162 } |
163 | 163 |
164 | 164 |
165 bool MergeStudyJob::HandleTrailingStep() | |
166 { | |
167 if (!keepSource_) | |
168 { | |
169 const size_t n = GetInstancesCount(); | |
170 | |
171 for (size_t i = 0; i < n; i++) | |
172 { | |
173 Json::Value tmp; | |
174 context_.DeleteResource(tmp, GetInstance(i), ResourceType_Instance); | |
175 } | |
176 } | |
177 | |
178 return true; | |
179 } | |
180 | |
181 | |
182 MergeStudyJob::MergeStudyJob(ServerContext& context, | 165 MergeStudyJob::MergeStudyJob(ServerContext& context, |
183 const std::string& targetStudy) : | 166 const std::string& targetStudy) : |
184 context_(context), | 167 CleaningInstancesJob(context, false /* by default, remove source instances */), |
185 keepSource_(false), | |
186 targetStudy_(targetStudy) | 168 targetStudy_(targetStudy) |
187 { | 169 { |
188 /** | 170 /** |
189 * Check the validity of the input ID | 171 * Check the validity of the input ID |
190 **/ | 172 **/ |
191 | 173 |
192 ResourceType type; | 174 ResourceType type; |
193 | 175 |
194 if (!context_.GetIndex().LookupResourceType(type, targetStudy) || | 176 if (!GetContext().GetIndex().LookupResourceType(type, targetStudy) || |
195 type != ResourceType_Study) | 177 type != ResourceType_Study) |
196 { | 178 { |
197 throw OrthancException(ErrorCode_UnknownResource, | 179 throw OrthancException(ErrorCode_UnknownResource, |
198 "Cannot merge into an unknown study: " + targetStudy); | 180 "Cannot merge into an unknown study: " + targetStudy); |
199 } | 181 } |
206 | 188 |
207 DicomTag::AddTagsForModule(removals_, DicomModule_Patient); | 189 DicomTag::AddTagsForModule(removals_, DicomModule_Patient); |
208 DicomTag::AddTagsForModule(removals_, DicomModule_Study); | 190 DicomTag::AddTagsForModule(removals_, DicomModule_Study); |
209 | 191 |
210 std::list<std::string> instances; | 192 std::list<std::string> instances; |
211 context_.GetIndex().GetChildInstances(instances, targetStudy); | 193 GetContext().GetIndex().GetChildInstances(instances, targetStudy); |
212 | 194 |
213 if (instances.empty()) | 195 if (instances.empty()) |
214 { | 196 { |
215 throw OrthancException(ErrorCode_UnknownResource); | 197 throw OrthancException(ErrorCode_UnknownResource); |
216 } | 198 } |
217 | 199 |
218 DicomMap dicom; | 200 DicomMap dicom; |
219 | 201 |
220 { | 202 { |
221 ServerContext::DicomCacheLocker locker(context_, instances.front()); | 203 ServerContext::DicomCacheLocker locker(GetContext(), instances.front()); |
222 locker.GetDicom().ExtractDicomSummary(dicom); | 204 locker.GetDicom().ExtractDicomSummary(dicom); |
223 } | 205 } |
224 | 206 |
225 const std::set<DicomTag> moduleTags = removals_; | 207 const std::set<DicomTag> moduleTags = removals_; |
226 for (std::set<DicomTag>::const_iterator it = moduleTags.begin(); | 208 for (std::set<DicomTag>::const_iterator it = moduleTags.begin(); |
264 | 246 |
265 if (IsStarted()) | 247 if (IsStarted()) |
266 { | 248 { |
267 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 249 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
268 } | 250 } |
269 else if (!context_.GetIndex().LookupResourceType(level, studyOrSeries)) | 251 else if (!GetContext().GetIndex().LookupResourceType(level, studyOrSeries)) |
270 { | 252 { |
271 throw OrthancException(ErrorCode_UnknownResource, | 253 throw OrthancException(ErrorCode_UnknownResource, |
272 "Cannot find this resource: " + studyOrSeries); | 254 "Cannot find this resource: " + studyOrSeries); |
273 } | 255 } |
274 else | 256 else |
299 | 281 |
300 if (IsStarted()) | 282 if (IsStarted()) |
301 { | 283 { |
302 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 284 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
303 } | 285 } |
304 else if (!context_.GetIndex().LookupParent(parent, series, ResourceType_Study)) | 286 else if (!GetContext().GetIndex().LookupParent(parent, series, ResourceType_Study)) |
305 { | 287 { |
306 throw OrthancException(ErrorCode_UnknownResource, | 288 throw OrthancException(ErrorCode_UnknownResource, |
307 "This resource is not a series: " + series); | 289 "This resource is not a series: " + series); |
308 } | 290 } |
309 else if (parent == targetStudy_) | 291 else if (parent == targetStudy_) |
325 | 307 |
326 if (IsStarted()) | 308 if (IsStarted()) |
327 { | 309 { |
328 throw OrthancException(ErrorCode_BadSequenceOfCalls); | 310 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
329 } | 311 } |
330 else if (!context_.GetIndex().LookupResourceType(actualLevel, study) || | 312 else if (!GetContext().GetIndex().LookupResourceType(actualLevel, study) || |
331 actualLevel != ResourceType_Study) | 313 actualLevel != ResourceType_Study) |
332 { | 314 { |
333 throw OrthancException(ErrorCode_UnknownResource, | 315 throw OrthancException(ErrorCode_UnknownResource, |
334 "This resource is not a study: " + study); | 316 "This resource is not a study: " + study); |
335 } | 317 } |
338 AddSourceStudyInternal(study); | 320 AddSourceStudyInternal(study); |
339 } | 321 } |
340 } | 322 } |
341 | 323 |
342 | 324 |
343 void MergeStudyJob::SetKeepSource(bool keep) | |
344 { | |
345 if (IsStarted()) | |
346 { | |
347 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
348 } | |
349 | |
350 keepSource_ = keep; | |
351 } | |
352 | |
353 | |
354 void MergeStudyJob::GetPublicContent(Json::Value& value) | 325 void MergeStudyJob::GetPublicContent(Json::Value& value) |
355 { | 326 { |
356 SetOfInstancesJob::GetPublicContent(value); | 327 CleaningInstancesJob::GetPublicContent(value); |
357 value["TargetStudy"] = targetStudy_; | 328 value["TargetStudy"] = targetStudy_; |
358 } | 329 } |
359 | 330 |
360 | 331 |
361 static const char* KEEP_SOURCE = "KeepSource"; | |
362 static const char* TARGET_STUDY = "TargetStudy"; | 332 static const char* TARGET_STUDY = "TargetStudy"; |
363 static const char* REPLACEMENTS = "Replacements"; | 333 static const char* REPLACEMENTS = "Replacements"; |
364 static const char* REMOVALS = "Removals"; | 334 static const char* REMOVALS = "Removals"; |
365 static const char* SERIES_UID_MAP = "SeriesUIDMap"; | 335 static const char* SERIES_UID_MAP = "SeriesUIDMap"; |
366 static const char* ORIGIN = "Origin"; | 336 static const char* ORIGIN = "Origin"; |
367 | 337 |
368 | 338 |
369 MergeStudyJob::MergeStudyJob(ServerContext& context, | 339 MergeStudyJob::MergeStudyJob(ServerContext& context, |
370 const Json::Value& serialized) : | 340 const Json::Value& serialized) : |
371 SetOfInstancesJob(serialized), // (*) | 341 CleaningInstancesJob(context, serialized, |
372 context_(context) | 342 false /* by default, remove source instances */) // (*) |
373 { | 343 { |
374 if (!HasTrailingStep()) | 344 if (!HasTrailingStep()) |
375 { | 345 { |
376 // Should have been set by (*) | 346 // Should have been set by (*) |
377 throw OrthancException(ErrorCode_InternalError); | 347 throw OrthancException(ErrorCode_InternalError); |
378 } | 348 } |
379 | 349 |
380 keepSource_ = SerializationToolbox::ReadBoolean(serialized, KEEP_SOURCE); | |
381 targetStudy_ = SerializationToolbox::ReadString(serialized, TARGET_STUDY); | 350 targetStudy_ = SerializationToolbox::ReadString(serialized, TARGET_STUDY); |
382 SerializationToolbox::ReadMapOfTags(replacements_, serialized, REPLACEMENTS); | 351 SerializationToolbox::ReadMapOfTags(replacements_, serialized, REPLACEMENTS); |
383 SerializationToolbox::ReadSetOfTags(removals_, serialized, REMOVALS); | 352 SerializationToolbox::ReadSetOfTags(removals_, serialized, REMOVALS); |
384 SerializationToolbox::ReadMapOfStrings(seriesUidMap_, serialized, SERIES_UID_MAP); | 353 SerializationToolbox::ReadMapOfStrings(seriesUidMap_, serialized, SERIES_UID_MAP); |
385 origin_ = DicomInstanceOrigin(serialized[ORIGIN]); | 354 origin_ = DicomInstanceOrigin(serialized[ORIGIN]); |
386 } | 355 } |
387 | 356 |
388 | 357 |
389 bool MergeStudyJob::Serialize(Json::Value& target) | 358 bool MergeStudyJob::Serialize(Json::Value& target) |
390 { | 359 { |
391 if (!SetOfInstancesJob::Serialize(target)) | 360 if (!CleaningInstancesJob::Serialize(target)) |
392 { | 361 { |
393 return false; | 362 return false; |
394 } | 363 } |
395 else | 364 else |
396 { | 365 { |
397 target[KEEP_SOURCE] = keepSource_; | |
398 target[TARGET_STUDY] = targetStudy_; | 366 target[TARGET_STUDY] = targetStudy_; |
399 SerializationToolbox::WriteMapOfTags(target, replacements_, REPLACEMENTS); | 367 SerializationToolbox::WriteMapOfTags(target, replacements_, REPLACEMENTS); |
400 SerializationToolbox::WriteSetOfTags(target, removals_, REMOVALS); | 368 SerializationToolbox::WriteSetOfTags(target, removals_, REMOVALS); |
401 SerializationToolbox::WriteMapOfStrings(target, seriesUidMap_, SERIES_UID_MAP); | 369 SerializationToolbox::WriteMapOfStrings(target, seriesUidMap_, SERIES_UID_MAP); |
402 origin_.Serialize(target[ORIGIN]); | 370 origin_.Serialize(target[ORIGIN]); |