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