Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 5663:3765085693e5 large-queries
merge default -> large-queries
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Thu, 04 Jul 2024 07:40:58 +0200 |
parents | 28cc06e4859a f7adfb22e20e |
children | 5463c3ae3235 |
comparison
equal
deleted
inserted
replaced
5553:28cc06e4859a | 5663:3765085693e5 |
---|---|
1 /** | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
4 * Department, University Hospital of Liege, Belgium | 4 * Department, University Hospital of Liege, Belgium |
5 * Copyright (C) 2017-2024 Osimis S.A., Belgium | 5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium | |
6 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium | 7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
7 * | 8 * |
8 * This program is free software: you can redistribute it and/or | 9 * This program is free software: you can redistribute it and/or |
9 * modify it under the terms of the GNU General Public License as | 10 * modify it under the terms of the GNU General Public License as |
10 * published by the Free Software Foundation, either version 3 of the | 11 * published by the Free Software Foundation, either version 3 of the |
964 | 965 |
965 if (type == ResourceType_Patient || | 966 if (type == ResourceType_Patient || |
966 type == ResourceType_Study || | 967 type == ResourceType_Study || |
967 type == ResourceType_Series) | 968 type == ResourceType_Series) |
968 { | 969 { |
969 target.isStable_ = !transaction.GetTransactionContext().IsUnstableResource(internalId); | 970 target.isStable_ = !transaction.GetTransactionContext().IsUnstableResource(type, internalId); |
970 | 971 |
971 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_LastUpdate)) | 972 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_LastUpdate)) |
972 { | 973 { |
973 target.lastUpdate_ = tmp; | 974 target.lastUpdate_ = tmp; |
974 } | 975 } |
2795 Toolbox::WriteFastJson(result, jsonMetadata); | 2796 Toolbox::WriteFastJson(result, jsonMetadata); |
2796 } | 2797 } |
2797 } | 2798 } |
2798 | 2799 |
2799 | 2800 |
2800 void StatelessDatabaseOperations::ReconstructInstance(const ParsedDicomFile& dicom) | 2801 void StatelessDatabaseOperations::ReconstructInstance(const ParsedDicomFile& dicom, bool limitToThisLevelDicomTags, ResourceType limitToLevel) |
2801 { | 2802 { |
2802 class Operations : public IReadWriteOperations | 2803 class Operations : public IReadWriteOperations |
2803 { | 2804 { |
2804 private: | 2805 private: |
2805 DicomMap summary_; | 2806 DicomMap summary_; |
2806 std::unique_ptr<DicomInstanceHasher> hasher_; | 2807 std::unique_ptr<DicomInstanceHasher> hasher_; |
2808 bool limitToThisLevelDicomTags_; | |
2809 ResourceType limitToLevel_; | |
2807 bool hasTransferSyntax_; | 2810 bool hasTransferSyntax_; |
2808 DicomTransferSyntax transferSyntax_; | 2811 DicomTransferSyntax transferSyntax_; |
2809 | 2812 |
2810 static void ReplaceMetadata(ReadWriteTransaction& transaction, | 2813 static void ReplaceMetadata(ReadWriteTransaction& transaction, |
2811 int64_t instance, | 2814 int64_t instance, |
2843 } | 2846 } |
2844 | 2847 |
2845 } | 2848 } |
2846 | 2849 |
2847 public: | 2850 public: |
2848 explicit Operations(const ParsedDicomFile& dicom) | 2851 explicit Operations(const ParsedDicomFile& dicom, bool limitToThisLevelDicomTags, ResourceType limitToLevel) |
2852 : limitToThisLevelDicomTags_(limitToThisLevelDicomTags), | |
2853 limitToLevel_(limitToLevel) | |
2849 { | 2854 { |
2850 OrthancConfiguration::DefaultExtractDicomSummary(summary_, dicom); | 2855 OrthancConfiguration::DefaultExtractDicomSummary(summary_, dicom); |
2851 hasher_.reset(new DicomInstanceHasher(summary_)); | 2856 hasher_.reset(new DicomInstanceHasher(summary_)); |
2852 hasTransferSyntax_ = dicom.LookupTransferSyntax(transferSyntax_); | 2857 hasTransferSyntax_ = dicom.LookupTransferSyntax(transferSyntax_); |
2853 } | 2858 } |
2871 instance == -1) | 2876 instance == -1) |
2872 { | 2877 { |
2873 throw OrthancException(ErrorCode_InternalError); | 2878 throw OrthancException(ErrorCode_InternalError); |
2874 } | 2879 } |
2875 | 2880 |
2876 transaction.ClearMainDicomTags(patient); | 2881 if (limitToThisLevelDicomTags_) |
2877 transaction.ClearMainDicomTags(study); | |
2878 transaction.ClearMainDicomTags(series); | |
2879 transaction.ClearMainDicomTags(instance); | |
2880 | |
2881 { | 2882 { |
2882 ResourcesContent content(false /* prevent the setting of metadata */); | 2883 ResourcesContent content(false /* prevent the setting of metadata */); |
2883 content.AddResource(patient, ResourceType_Patient, summary_); | 2884 int64_t resource = -1; |
2884 content.AddResource(study, ResourceType_Study, summary_); | 2885 if (limitToLevel_ == ResourceType_Patient) |
2885 content.AddResource(series, ResourceType_Series, summary_); | 2886 { |
2886 content.AddResource(instance, ResourceType_Instance, summary_); | 2887 resource = patient; |
2887 | 2888 } |
2889 else if (limitToLevel_ == ResourceType_Study) | |
2890 { | |
2891 resource = study; | |
2892 } | |
2893 else if (limitToLevel_ == ResourceType_Series) | |
2894 { | |
2895 resource = series; | |
2896 } | |
2897 else if (limitToLevel_ == ResourceType_Instance) | |
2898 { | |
2899 resource = instance; | |
2900 } | |
2901 | |
2902 transaction.ClearMainDicomTags(resource); | |
2903 content.AddResource(resource, limitToLevel_, summary_); | |
2888 transaction.SetResourcesContent(content); | 2904 transaction.SetResourcesContent(content); |
2889 | 2905 ReplaceMetadata(transaction, resource, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(limitToLevel_)); |
2890 ReplaceMetadata(transaction, patient, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 | 2906 } |
2891 ReplaceMetadata(transaction, study, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 | 2907 else |
2892 ReplaceMetadata(transaction, series, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 | 2908 { |
2893 ReplaceMetadata(transaction, instance, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 | 2909 transaction.ClearMainDicomTags(patient); |
2894 | 2910 transaction.ClearMainDicomTags(study); |
2895 SetMainDicomSequenceMetadata(transaction, patient, summary_, ResourceType_Patient); | 2911 transaction.ClearMainDicomTags(series); |
2896 SetMainDicomSequenceMetadata(transaction, study, summary_, ResourceType_Study); | 2912 transaction.ClearMainDicomTags(instance); |
2897 SetMainDicomSequenceMetadata(transaction, series, summary_, ResourceType_Series); | 2913 |
2898 SetMainDicomSequenceMetadata(transaction, instance, summary_, ResourceType_Instance); | 2914 { |
2899 } | 2915 ResourcesContent content(false /* prevent the setting of metadata */); |
2900 | 2916 content.AddResource(patient, ResourceType_Patient, summary_); |
2901 if (hasTransferSyntax_) | 2917 content.AddResource(study, ResourceType_Study, summary_); |
2902 { | 2918 content.AddResource(series, ResourceType_Series, summary_); |
2903 ReplaceMetadata(transaction, instance, MetadataType_Instance_TransferSyntax, GetTransferSyntaxUid(transferSyntax_)); | 2919 content.AddResource(instance, ResourceType_Instance, summary_); |
2904 } | 2920 |
2905 | 2921 transaction.SetResourcesContent(content); |
2906 const DicomValue* value; | 2922 |
2907 if ((value = summary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | 2923 ReplaceMetadata(transaction, patient, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 |
2908 !value->IsNull() && | 2924 ReplaceMetadata(transaction, study, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 |
2909 !value->IsBinary()) | 2925 ReplaceMetadata(transaction, series, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 |
2910 { | 2926 ReplaceMetadata(transaction, instance, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 |
2911 ReplaceMetadata(transaction, instance, MetadataType_Instance_SopClassUid, value->GetContent()); | 2927 |
2912 } | 2928 SetMainDicomSequenceMetadata(transaction, patient, summary_, ResourceType_Patient); |
2913 | 2929 SetMainDicomSequenceMetadata(transaction, study, summary_, ResourceType_Study); |
2914 } | 2930 SetMainDicomSequenceMetadata(transaction, series, summary_, ResourceType_Series); |
2915 }; | 2931 SetMainDicomSequenceMetadata(transaction, instance, summary_, ResourceType_Instance); |
2916 | 2932 } |
2917 Operations operations(dicom); | 2933 |
2934 if (hasTransferSyntax_) | |
2935 { | |
2936 ReplaceMetadata(transaction, instance, MetadataType_Instance_TransferSyntax, GetTransferSyntaxUid(transferSyntax_)); | |
2937 } | |
2938 | |
2939 const DicomValue* value; | |
2940 if ((value = summary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | |
2941 !value->IsNull() && | |
2942 !value->IsBinary()) | |
2943 { | |
2944 ReplaceMetadata(transaction, instance, MetadataType_Instance_SopClassUid, value->GetContent()); | |
2945 } | |
2946 } | |
2947 } | |
2948 }; | |
2949 | |
2950 Operations operations(dicom, limitToThisLevelDicomTags, limitToLevel); | |
2918 Apply(operations); | 2951 Apply(operations); |
2919 } | 2952 } |
2920 | 2953 |
2921 | 2954 |
2922 bool StatelessDatabaseOperations::ReadWriteTransaction::HasReachedMaxStorageSize(uint64_t maximumStorageSize, | 2955 bool StatelessDatabaseOperations::ReadWriteTransaction::HasReachedMaxStorageSize(uint64_t maximumStorageSize, |
3341 } | 3374 } |
3342 | 3375 |
3343 transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */); | 3376 transaction.AddAttachment(instanceId, *it, 0 /* this is the first revision */); |
3344 } | 3377 } |
3345 | 3378 |
3379 ResourcesContent content(true /* new resource, metadata can be set */); | |
3380 | |
3381 // Attach the user-specified metadata (in case of reconstruction, metadata_ contains all past metadata, including the system ones we want to keep) | |
3382 for (MetadataMap::const_iterator | |
3383 it = metadata_.begin(); it != metadata_.end(); ++it) | |
3384 { | |
3385 switch (it->first.first) | |
3386 { | |
3387 case ResourceType_Patient: | |
3388 content.AddMetadata(status.patientId_, it->first.second, it->second); | |
3389 break; | |
3390 | |
3391 case ResourceType_Study: | |
3392 content.AddMetadata(status.studyId_, it->first.second, it->second); | |
3393 break; | |
3394 | |
3395 case ResourceType_Series: | |
3396 content.AddMetadata(status.seriesId_, it->first.second, it->second); | |
3397 break; | |
3398 | |
3399 case ResourceType_Instance: | |
3400 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3401 it->first.second, it->second); | |
3402 break; | |
3403 | |
3404 default: | |
3405 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
3406 } | |
3407 } | |
3408 | |
3346 if (!isReconstruct_) | 3409 if (!isReconstruct_) |
3347 { | 3410 { |
3348 ResourcesContent content(true /* new resource, metadata can be set */); | 3411 // Populate the tags of the newly-created resources |
3349 | 3412 content.AddResource(instanceId, ResourceType_Instance, dicomSummary_); |
3350 // Attach the user-specified metadata (in case of reconstruction, metadata_ contains all past metadata, including the system ones we want to keep) | 3413 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 |
3351 for (MetadataMap::const_iterator | 3414 SetMainDicomSequenceMetadata(content, instanceId, dicomSummary_, ResourceType_Instance); // new in Orthanc 1.11.1 |
3352 it = metadata_.begin(); it != metadata_.end(); ++it) | 3415 |
3353 { | 3416 if (status.isNewSeries_) |
3354 switch (it->first.first) | 3417 { |
3418 content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_); | |
3419 content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 | |
3420 SetMainDicomSequenceMetadata(content, status.seriesId_, dicomSummary_, ResourceType_Series); // new in Orthanc 1.11.1 | |
3421 } | |
3422 | |
3423 if (status.isNewStudy_) | |
3424 { | |
3425 content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_); | |
3426 content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 | |
3427 SetMainDicomSequenceMetadata(content, status.studyId_, dicomSummary_, ResourceType_Study); // new in Orthanc 1.11.1 | |
3428 } | |
3429 | |
3430 if (status.isNewPatient_) | |
3431 { | |
3432 content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_); | |
3433 content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 | |
3434 SetMainDicomSequenceMetadata(content, status.patientId_, dicomSummary_, ResourceType_Patient); // new in Orthanc 1.11.1 | |
3435 } | |
3436 | |
3437 // Attach the auto-computed metadata for the patient/study/series levels | |
3438 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */); | |
3439 content.AddMetadata(status.seriesId_, MetadataType_LastUpdate, now); | |
3440 content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now); | |
3441 content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now); | |
3442 | |
3443 if (status.isNewSeries_) | |
3444 { | |
3445 if (hasExpectedInstances_) | |
3355 { | 3446 { |
3356 case ResourceType_Patient: | 3447 content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances, |
3357 content.AddMetadata(status.patientId_, it->first.second, it->second); | 3448 boost::lexical_cast<std::string>(expectedInstances_)); |
3358 break; | |
3359 | |
3360 case ResourceType_Study: | |
3361 content.AddMetadata(status.studyId_, it->first.second, it->second); | |
3362 break; | |
3363 | |
3364 case ResourceType_Series: | |
3365 content.AddMetadata(status.seriesId_, it->first.second, it->second); | |
3366 break; | |
3367 | |
3368 case ResourceType_Instance: | |
3369 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3370 it->first.second, it->second); | |
3371 break; | |
3372 | |
3373 default: | |
3374 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
3375 } | 3449 } |
3376 } | 3450 |
3377 | 3451 // New in Orthanc 1.9.0 |
3378 if (!isReconstruct_) | 3452 content.AddMetadata(status.seriesId_, MetadataType_RemoteAet, |
3379 { | 3453 origin_.GetRemoteAetC()); |
3380 // Populate the tags of the newly-created resources | 3454 } |
3381 content.AddResource(instanceId, ResourceType_Instance, dicomSummary_); | 3455 // Attach the auto-computed metadata for the instance level, |
3382 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 | 3456 // reflecting these additions into the input metadata map |
3383 SetMainDicomSequenceMetadata(content, instanceId, dicomSummary_, ResourceType_Instance); // new in Orthanc 1.11.1 | 3457 SetInstanceMetadata(content, instanceMetadata_, instanceId, |
3384 | 3458 MetadataType_Instance_ReceptionDate, now); |
3385 if (status.isNewSeries_) | 3459 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_RemoteAet, |
3460 origin_.GetRemoteAetC()); | |
3461 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_Instance_Origin, | |
3462 EnumerationToString(origin_.GetRequestOrigin())); | |
3463 | |
3464 std::string s; | |
3465 | |
3466 if (origin_.LookupRemoteIp(s)) | |
3467 { | |
3468 // New in Orthanc 1.4.0 | |
3469 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3470 MetadataType_Instance_RemoteIp, s); | |
3471 } | |
3472 | |
3473 if (origin_.LookupCalledAet(s)) | |
3474 { | |
3475 // New in Orthanc 1.4.0 | |
3476 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3477 MetadataType_Instance_CalledAet, s); | |
3478 } | |
3479 | |
3480 if (origin_.LookupHttpUsername(s)) | |
3481 { | |
3482 // New in Orthanc 1.4.0 | |
3483 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3484 MetadataType_Instance_HttpUsername, s); | |
3485 } | |
3486 } | |
3487 | |
3488 // Following metadatas are also updated if reconstructing the instance. | |
3489 // They might be missing since they have been introduced along Orthanc versions. | |
3490 | |
3491 if (hasTransferSyntax_) | |
3492 { | |
3493 // New in Orthanc 1.2.0 | |
3494 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3495 MetadataType_Instance_TransferSyntax, | |
3496 GetTransferSyntaxUid(transferSyntax_)); | |
3497 } | |
3498 | |
3499 if (hasPixelDataOffset_) | |
3500 { | |
3501 // New in Orthanc 1.9.1 | |
3502 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3503 MetadataType_Instance_PixelDataOffset, | |
3504 boost::lexical_cast<std::string>(pixelDataOffset_)); | |
3505 | |
3506 // New in Orthanc 1.12.1 | |
3507 if (dicomSummary_.GuessPixelDataValueRepresentation(transferSyntax_) != pixelDataVR_) | |
3508 { | |
3509 // Store the VR of pixel data if it doesn't comply with the standard | |
3510 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3511 MetadataType_Instance_PixelDataVR, | |
3512 EnumerationToString(pixelDataVR_)); | |
3513 } | |
3514 } | |
3515 | |
3516 const DicomValue* value; | |
3517 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | |
3518 !value->IsNull() && | |
3519 !value->IsBinary()) | |
3520 { | |
3521 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3522 MetadataType_Instance_SopClassUid, value->GetContent()); | |
3523 } | |
3524 | |
3525 | |
3526 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
3527 (value = dicomSummary_.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
3528 { | |
3529 if (!value->IsNull() && | |
3530 !value->IsBinary()) | |
3531 { | |
3532 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3533 MetadataType_Instance_IndexInSeries, Toolbox::StripSpaces(value->GetContent())); | |
3534 } | |
3535 } | |
3536 | |
3537 | |
3538 transaction.SetResourcesContent(content); | |
3539 | |
3540 | |
3541 if (!isReconstruct_) // a reconstruct shall not trigger any events | |
3542 { | |
3543 // Check whether the series of this new instance is now completed | |
3544 int64_t expectedNumberOfInstances; | |
3545 if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary_)) | |
3546 { | |
3547 SeriesStatus seriesStatus = transaction.GetSeriesStatus(status.seriesId_, expectedNumberOfInstances); | |
3548 if (seriesStatus == SeriesStatus_Complete) | |
3386 { | 3549 { |
3387 content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_); | 3550 transaction.LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries_); |
3388 content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 | |
3389 SetMainDicomSequenceMetadata(content, status.seriesId_, dicomSummary_, ResourceType_Series); // new in Orthanc 1.11.1 | |
3390 } | 3551 } |
3391 | 3552 } |
3392 if (status.isNewStudy_) | 3553 |
3393 { | 3554 transaction.LogChange(status.seriesId_, ChangeType_NewChildInstance, ResourceType_Series, hashSeries_); |
3394 content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_); | 3555 transaction.LogChange(status.studyId_, ChangeType_NewChildInstance, ResourceType_Study, hashStudy_); |
3395 content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 | 3556 transaction.LogChange(status.patientId_, ChangeType_NewChildInstance, ResourceType_Patient, hashPatient_); |
3396 SetMainDicomSequenceMetadata(content, status.studyId_, dicomSummary_, ResourceType_Study); // new in Orthanc 1.11.1 | 3557 |
3397 } | 3558 // Mark the parent resources of this instance as unstable |
3398 | 3559 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Series, status.seriesId_, hashSeries_); |
3399 if (status.isNewPatient_) | 3560 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Study, status.studyId_, hashStudy_); |
3400 { | 3561 transaction.GetTransactionContext().MarkAsUnstable(ResourceType_Patient, status.patientId_, hashPatient_); |
3401 content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_); | 3562 } |
3402 content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 | 3563 |
3403 SetMainDicomSequenceMetadata(content, status.patientId_, dicomSummary_, ResourceType_Patient); // new in Orthanc 1.11.1 | |
3404 } | |
3405 | |
3406 // Attach the auto-computed metadata for the patient/study/series levels | |
3407 std::string now = SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */); | |
3408 content.AddMetadata(status.seriesId_, MetadataType_LastUpdate, now); | |
3409 content.AddMetadata(status.studyId_, MetadataType_LastUpdate, now); | |
3410 content.AddMetadata(status.patientId_, MetadataType_LastUpdate, now); | |
3411 | |
3412 if (status.isNewSeries_) | |
3413 { | |
3414 if (hasExpectedInstances_) | |
3415 { | |
3416 content.AddMetadata(status.seriesId_, MetadataType_Series_ExpectedNumberOfInstances, | |
3417 boost::lexical_cast<std::string>(expectedInstances_)); | |
3418 } | |
3419 | |
3420 // New in Orthanc 1.9.0 | |
3421 content.AddMetadata(status.seriesId_, MetadataType_RemoteAet, | |
3422 origin_.GetRemoteAetC()); | |
3423 } | |
3424 // Attach the auto-computed metadata for the instance level, | |
3425 // reflecting these additions into the input metadata map | |
3426 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3427 MetadataType_Instance_ReceptionDate, now); | |
3428 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_RemoteAet, | |
3429 origin_.GetRemoteAetC()); | |
3430 SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_Instance_Origin, | |
3431 EnumerationToString(origin_.GetRequestOrigin())); | |
3432 | |
3433 std::string s; | |
3434 | |
3435 if (origin_.LookupRemoteIp(s)) | |
3436 { | |
3437 // New in Orthanc 1.4.0 | |
3438 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3439 MetadataType_Instance_RemoteIp, s); | |
3440 } | |
3441 | |
3442 if (origin_.LookupCalledAet(s)) | |
3443 { | |
3444 // New in Orthanc 1.4.0 | |
3445 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3446 MetadataType_Instance_CalledAet, s); | |
3447 } | |
3448 | |
3449 if (origin_.LookupHttpUsername(s)) | |
3450 { | |
3451 // New in Orthanc 1.4.0 | |
3452 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3453 MetadataType_Instance_HttpUsername, s); | |
3454 } | |
3455 } | |
3456 | |
3457 // Following metadatas are also updated if reconstructing the instance. | |
3458 // They might be missing since they have been introduced along Orthanc versions. | |
3459 | |
3460 if (hasTransferSyntax_) | |
3461 { | |
3462 // New in Orthanc 1.2.0 | |
3463 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3464 MetadataType_Instance_TransferSyntax, | |
3465 GetTransferSyntaxUid(transferSyntax_)); | |
3466 } | |
3467 | |
3468 if (hasPixelDataOffset_) | |
3469 { | |
3470 // New in Orthanc 1.9.1 | |
3471 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3472 MetadataType_Instance_PixelDataOffset, | |
3473 boost::lexical_cast<std::string>(pixelDataOffset_)); | |
3474 | |
3475 // New in Orthanc 1.12.1 | |
3476 if (dicomSummary_.GuessPixelDataValueRepresentation(transferSyntax_) != pixelDataVR_) | |
3477 { | |
3478 // Store the VR of pixel data if it doesn't comply with the standard | |
3479 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3480 MetadataType_Instance_PixelDataVR, | |
3481 EnumerationToString(pixelDataVR_)); | |
3482 } | |
3483 } | |
3484 | |
3485 const DicomValue* value; | |
3486 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_SOP_CLASS_UID)) != NULL && | |
3487 !value->IsNull() && | |
3488 !value->IsBinary()) | |
3489 { | |
3490 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3491 MetadataType_Instance_SopClassUid, value->GetContent()); | |
3492 } | |
3493 | |
3494 | |
3495 if ((value = dicomSummary_.TestAndGetValue(DICOM_TAG_INSTANCE_NUMBER)) != NULL || | |
3496 (value = dicomSummary_.TestAndGetValue(DICOM_TAG_IMAGE_INDEX)) != NULL) | |
3497 { | |
3498 if (!value->IsNull() && | |
3499 !value->IsBinary()) | |
3500 { | |
3501 SetInstanceMetadata(content, instanceMetadata_, instanceId, | |
3502 MetadataType_Instance_IndexInSeries, Toolbox::StripSpaces(value->GetContent())); | |
3503 } | |
3504 } | |
3505 | |
3506 | |
3507 transaction.SetResourcesContent(content); | |
3508 } | |
3509 | |
3510 | |
3511 // Check whether the series of this new instance is now completed | |
3512 int64_t expectedNumberOfInstances; | |
3513 if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary_)) | |
3514 { | |
3515 SeriesStatus seriesStatus = transaction.GetSeriesStatus(status.seriesId_, expectedNumberOfInstances); | |
3516 if (seriesStatus == SeriesStatus_Complete) | |
3517 { | |
3518 transaction.LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries_); | |
3519 } | |
3520 } | |
3521 | |
3522 transaction.LogChange(status.seriesId_, ChangeType_NewChildInstance, ResourceType_Series, hashSeries_); | |
3523 transaction.LogChange(status.studyId_, ChangeType_NewChildInstance, ResourceType_Study, hashStudy_); | |
3524 transaction.LogChange(status.patientId_, ChangeType_NewChildInstance, ResourceType_Patient, hashPatient_); | |
3525 | |
3526 // Mark the parent resources of this instance as unstable | |
3527 transaction.GetTransactionContext().MarkAsUnstable(status.seriesId_, ResourceType_Series, hashSeries_); | |
3528 transaction.GetTransactionContext().MarkAsUnstable(status.studyId_, ResourceType_Study, hashStudy_); | |
3529 transaction.GetTransactionContext().MarkAsUnstable(status.patientId_, ResourceType_Patient, hashPatient_); | |
3530 transaction.GetTransactionContext().SignalAttachmentsAdded(instanceSize); | 3564 transaction.GetTransactionContext().SignalAttachmentsAdded(instanceSize); |
3531 | 3565 storeStatus_ = StoreStatus_Success; |
3532 storeStatus_ = StoreStatus_Success; | |
3533 } | 3566 } |
3534 }; | 3567 }; |
3535 | 3568 |
3536 | 3569 |
3537 Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite, | 3570 Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite, |