comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 5614:4640b7ae9a11 find-refactoring

moving normalization of constraints into FindRequest
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 09 May 2024 11:59:56 +0200
parents 3f24eb4013d8
children 824a5fb0774e
comparison
equal deleted inserted replaced
5613:f1ce8dd361b7 5614:4640b7ae9a11
297 pos ++; 297 pos ++;
298 } 298 }
299 } 299 }
300 300
301 301
302 class StatelessDatabaseOperations::MainDicomTagsRegistry : public boost::noncopyable
303 {
304 private:
305 class TagInfo
306 {
307 private:
308 ResourceType level_;
309 DicomTagType type_;
310
311 public:
312 TagInfo()
313 {
314 }
315
316 TagInfo(ResourceType level,
317 DicomTagType type) :
318 level_(level),
319 type_(type)
320 {
321 }
322
323 ResourceType GetLevel() const
324 {
325 return level_;
326 }
327
328 DicomTagType GetType() const
329 {
330 return type_;
331 }
332 };
333
334 typedef std::map<DicomTag, TagInfo> Registry;
335
336
337 Registry registry_;
338
339 void LoadTags(ResourceType level)
340 {
341 {
342 const DicomTag* tags = NULL;
343 size_t size;
344
345 ServerToolbox::LoadIdentifiers(tags, size, level);
346
347 for (size_t i = 0; i < size; i++)
348 {
349 if (registry_.find(tags[i]) == registry_.end())
350 {
351 registry_[tags[i]] = TagInfo(level, DicomTagType_Identifier);
352 }
353 else
354 {
355 // These patient-level tags are copied in the study level
356 assert(level == ResourceType_Study &&
357 (tags[i] == DICOM_TAG_PATIENT_ID ||
358 tags[i] == DICOM_TAG_PATIENT_NAME ||
359 tags[i] == DICOM_TAG_PATIENT_BIRTH_DATE));
360 }
361 }
362 }
363
364 {
365 std::set<DicomTag> tags;
366 DicomMap::GetMainDicomTags(tags, level);
367
368 for (std::set<DicomTag>::const_iterator
369 tag = tags.begin(); tag != tags.end(); ++tag)
370 {
371 if (registry_.find(*tag) == registry_.end())
372 {
373 registry_[*tag] = TagInfo(level, DicomTagType_Main);
374 }
375 }
376 }
377 }
378
379 public:
380 MainDicomTagsRegistry()
381 {
382 LoadTags(ResourceType_Patient);
383 LoadTags(ResourceType_Study);
384 LoadTags(ResourceType_Series);
385 LoadTags(ResourceType_Instance);
386 }
387
388 void LookupTag(ResourceType& level,
389 DicomTagType& type,
390 const DicomTag& tag) const
391 {
392 Registry::const_iterator it = registry_.find(tag);
393
394 if (it == registry_.end())
395 {
396 // Default values
397 level = ResourceType_Instance;
398 type = DicomTagType_Generic;
399 }
400 else
401 {
402 level = it->second.GetLevel();
403 type = it->second.GetType();
404 }
405 }
406 };
407
408
409 void StatelessDatabaseOperations::ReadWriteTransaction::LogChange(int64_t internalId, 302 void StatelessDatabaseOperations::ReadWriteTransaction::LogChange(int64_t internalId,
410 ChangeType changeType, 303 ChangeType changeType,
411 ResourceType resourceType, 304 ResourceType resourceType,
412 const std::string& publicId) 305 const std::string& publicId)
413 { 306 {
497 } 390 }
498 391
499 target.push_back(source.GetConstraint(i).ConvertToDatabaseConstraint(level, type)); 392 target.push_back(source.GetConstraint(i).ConvertToDatabaseConstraint(level, type));
500 } 393 }
501 } 394 }
502 }
503
504 void StatelessDatabaseOperations::NormalizeLookup(std::vector<DatabaseConstraint>& target,
505 const FindRequest& findRequest) const
506 {
507 assert(mainDicomTagsRegistry_.get() != NULL);
508
509 target.clear();
510 target.reserve(findRequest.GetDicomTagConstraintsCount());
511
512 for (size_t i = 0; i < findRequest.GetDicomTagConstraintsCount(); i++)
513 {
514 ResourceType level;
515 DicomTagType type;
516
517 mainDicomTagsRegistry_->LookupTag(level, type, findRequest.GetDicomTagConstraint(i).GetTag());
518
519 if (type == DicomTagType_Identifier ||
520 type == DicomTagType_Main)
521 {
522 // Use the fact that patient-level tags are copied at the study level
523 if (level == ResourceType_Patient &&
524 findRequest.GetLevel() != ResourceType_Patient)
525 {
526 level = ResourceType_Study;
527 }
528
529 target.push_back(findRequest.GetDicomTagConstraint(i).ConvertToDatabaseConstraint(level, type));
530 }
531 }
532
533 // TODO-FIND: add metadata constraints
534 } 395 }
535 396
536 397
537 class StatelessDatabaseOperations::Transaction : public boost::noncopyable 398 class StatelessDatabaseOperations::Transaction : public boost::noncopyable
538 { 399 {
3842 3703
3843 3704
3844 void StatelessDatabaseOperations::ExecuteFind(FindResponse& response, 3705 void StatelessDatabaseOperations::ExecuteFind(FindResponse& response,
3845 const FindRequest& request) 3706 const FindRequest& request)
3846 { 3707 {
3847 class IntegratedFind : public ReadOnlyOperationsT3<FindResponse&, const FindRequest&, const std::vector<DatabaseConstraint>&> 3708 class IntegratedFind : public ReadOnlyOperationsT2<FindResponse&, const FindRequest&>
3848 { 3709 {
3849 public: 3710 public:
3850 virtual void ApplyTuple(ReadOnlyTransaction& transaction, 3711 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3851 const Tuple& tuple) ORTHANC_OVERRIDE 3712 const Tuple& tuple) ORTHANC_OVERRIDE
3852 { 3713 {
3853 transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>(), tuple.get<2>()); 3714 transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>());
3854 } 3715 }
3855 }; 3716 };
3856 3717
3857 class FindStage : public ReadOnlyOperationsT3<std::list<std::string>&, const FindRequest&, const std::vector<DatabaseConstraint>&> 3718 class FindStage : public ReadOnlyOperationsT2<std::list<std::string>&, const FindRequest&>
3858 { 3719 {
3859 public: 3720 public:
3860 virtual void ApplyTuple(ReadOnlyTransaction& transaction, 3721 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3861 const Tuple& tuple) ORTHANC_OVERRIDE 3722 const Tuple& tuple) ORTHANC_OVERRIDE
3862 { 3723 {
3863 transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>(), tuple.get<2>()); 3724 transaction.ExecuteFind(tuple.get<0>(), tuple.get<1>());
3864 } 3725 }
3865 }; 3726 };
3866 3727
3867 class ExpandStage : public ReadOnlyOperationsT3<FindResponse&, const FindRequest&, const std::string&> 3728 class ExpandStage : public ReadOnlyOperationsT3<FindResponse&, const FindRequest&, const std::string&>
3868 { 3729 {
3871 const Tuple& tuple) ORTHANC_OVERRIDE 3732 const Tuple& tuple) ORTHANC_OVERRIDE
3872 { 3733 {
3873 transaction.ExecuteExpand(tuple.get<0>(), tuple.get<1>(), tuple.get<2>()); 3734 transaction.ExecuteExpand(tuple.get<0>(), tuple.get<1>(), tuple.get<2>());
3874 } 3735 }
3875 }; 3736 };
3876
3877 std::vector<DatabaseConstraint> normalized;
3878 NormalizeLookup(normalized, request);
3879 3737
3880 if (db_.HasIntegratedFind()) 3738 if (db_.HasIntegratedFind())
3881 { 3739 {
3882 /** 3740 /**
3883 * In this flavor, the "find" and the "expand" phases are 3741 * In this flavor, the "find" and the "expand" phases are
3884 * executed in one single transaction. 3742 * executed in one single transaction.
3885 **/ 3743 **/
3886 IntegratedFind operations; 3744 IntegratedFind operations;
3887 operations.Apply(*this, response, request, normalized); 3745 operations.Apply(*this, response, request);
3888 } 3746 }
3889 else 3747 else
3890 { 3748 {
3891 /** 3749 /**
3892 * In this flavor, the "find" and the "expand" phases for each 3750 * In this flavor, the "find" and the "expand" phases for each
3894 * the compatibility mode equivalent to Orthanc <= 1.12.3. 3752 * the compatibility mode equivalent to Orthanc <= 1.12.3.
3895 **/ 3753 **/
3896 std::list<std::string> identifiers; 3754 std::list<std::string> identifiers;
3897 3755
3898 FindStage find; 3756 FindStage find;
3899 find.Apply(*this, identifiers, request, normalized); 3757 find.Apply(*this, identifiers, request);
3900 3758
3901 ExpandStage expand; 3759 ExpandStage expand;
3902 3760
3903 for (std::list<std::string>::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it) 3761 for (std::list<std::string>::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it)
3904 { 3762 {