Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 4935:acd3f72e2a21 more-tags
split ExpandResource in 2: read from DB and serialize to json. This will allow us to merge requested tags from both the DB and the file system
author | Alain Mazy <am@osimis.io> |
---|---|
date | Thu, 10 Mar 2022 19:00:43 +0100 |
parents | 94a7b681b340 |
children | 8422e4f99a18 |
comparison
equal
deleted
inserted
replaced
4934:94a7b681b340 | 4935:acd3f72e2a21 |
---|---|
708 { | 708 { |
709 ApplyInternal(NULL, &operations); | 709 ApplyInternal(NULL, &operations); |
710 } | 710 } |
711 | 711 |
712 | 712 |
713 bool StatelessDatabaseOperations::ExpandResource(Json::Value& target, | 713 bool StatelessDatabaseOperations::ExpandResource(ExpandedResource& target, |
714 const std::string& publicId, | 714 const std::string& publicId, |
715 ResourceType level, | 715 ResourceType level, |
716 DicomToJsonFormat format) | 716 DicomToJsonFormat format) |
717 { | 717 { |
718 class Operations : public ReadOnlyOperationsT5< | 718 class Operations : public ReadOnlyOperationsT5< |
719 bool&, Json::Value&, const std::string&, ResourceType, DicomToJsonFormat> | 719 bool&, ExpandedResource&, const std::string&, ResourceType, DicomToJsonFormat> |
720 { | 720 { |
721 private: | 721 private: |
722 static void MainDicomTagsToJson(ReadOnlyTransaction& transaction, | |
723 Json::Value& target, | |
724 int64_t resourceId, | |
725 ResourceType resourceType, | |
726 DicomToJsonFormat format) | |
727 { | |
728 static const char* const MAIN_DICOM_TAGS = "MainDicomTags"; | |
729 static const char* const PATIENT_MAIN_DICOM_TAGS = "PatientMainDicomTags"; | |
730 | |
731 DicomMap tags; | |
732 transaction.GetMainDicomTags(tags, resourceId); | |
733 | |
734 if (resourceType == ResourceType_Study) | |
735 { | |
736 DicomMap t1, t2; | |
737 tags.ExtractStudyInformation(t1); | |
738 tags.ExtractPatientInformation(t2); | |
739 | |
740 target[MAIN_DICOM_TAGS] = Json::objectValue; | |
741 FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], t1, format); | |
742 | |
743 target[PATIENT_MAIN_DICOM_TAGS] = Json::objectValue; | |
744 FromDcmtkBridge::ToJson(target[PATIENT_MAIN_DICOM_TAGS], t2, format); | |
745 } | |
746 else | |
747 { | |
748 target[MAIN_DICOM_TAGS] = Json::objectValue; | |
749 FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], tags, format); | |
750 } | |
751 } | |
752 | |
753 | 722 |
754 static bool LookupStringMetadata(std::string& result, | 723 static bool LookupStringMetadata(std::string& result, |
755 const std::map<MetadataType, std::string>& metadata, | 724 const std::map<MetadataType, std::string>& metadata, |
756 MetadataType type) | 725 MetadataType type) |
757 { | 726 { |
804 { | 773 { |
805 tuple.get<0>() = false; | 774 tuple.get<0>() = false; |
806 } | 775 } |
807 else | 776 else |
808 { | 777 { |
809 Json::Value& target = tuple.get<1>(); | 778 ExpandedResource& target = tuple.get<1>(); |
810 target = Json::objectValue; | 779 |
811 | |
812 // Set information about the parent resource (if it exists) | 780 // Set information about the parent resource (if it exists) |
813 if (type == ResourceType_Patient) | 781 if (type == ResourceType_Patient) |
814 { | 782 { |
815 if (!parent.empty()) | 783 if (!parent.empty()) |
816 { | 784 { |
822 if (parent.empty()) | 790 if (parent.empty()) |
823 { | 791 { |
824 throw OrthancException(ErrorCode_DatabasePlugin); | 792 throw OrthancException(ErrorCode_DatabasePlugin); |
825 } | 793 } |
826 | 794 |
827 switch (type) | 795 target.parentId_ = parent; |
828 { | |
829 case ResourceType_Study: | |
830 target["ParentPatient"] = parent; | |
831 break; | |
832 | |
833 case ResourceType_Series: | |
834 target["ParentStudy"] = parent; | |
835 break; | |
836 | |
837 case ResourceType_Instance: | |
838 target["ParentSeries"] = parent; | |
839 break; | |
840 | |
841 default: | |
842 throw OrthancException(ErrorCode_InternalError); | |
843 } | |
844 } | 796 } |
845 | 797 |
846 // List the children resources | 798 // List the children resources |
847 std::list<std::string> children; | 799 transaction.GetChildrenPublicId(target.childrenIds_, internalId); |
848 transaction.GetChildrenPublicId(children, internalId); | |
849 | |
850 if (type != ResourceType_Instance) | |
851 { | |
852 Json::Value c = Json::arrayValue; | |
853 | |
854 for (std::list<std::string>::const_iterator | |
855 it = children.begin(); it != children.end(); ++it) | |
856 { | |
857 c.append(*it); | |
858 } | |
859 | |
860 switch (type) | |
861 { | |
862 case ResourceType_Patient: | |
863 target["Studies"] = c; | |
864 break; | |
865 | |
866 case ResourceType_Study: | |
867 target["Series"] = c; | |
868 break; | |
869 | |
870 case ResourceType_Series: | |
871 target["Instances"] = c; | |
872 break; | |
873 | |
874 default: | |
875 throw OrthancException(ErrorCode_InternalError); | |
876 } | |
877 } | |
878 | 800 |
879 // Extract the metadata | 801 // Extract the metadata |
880 std::map<MetadataType, std::string> metadata; | 802 transaction.GetAllMetadata(target.metadata_, internalId); |
881 transaction.GetAllMetadata(metadata, internalId); | |
882 | 803 |
883 // Set the resource type | 804 // Set the resource type |
805 target.type_ = type; | |
806 | |
884 switch (type) | 807 switch (type) |
885 { | 808 { |
886 case ResourceType_Patient: | 809 case ResourceType_Patient: |
887 target["Type"] = "Patient"; | 810 case ResourceType_Study: |
888 break; | 811 break; |
889 | 812 |
890 case ResourceType_Study: | |
891 target["Type"] = "Study"; | |
892 break; | |
893 | |
894 case ResourceType_Series: | 813 case ResourceType_Series: |
895 { | 814 { |
896 target["Type"] = "Series"; | |
897 | |
898 int64_t i; | 815 int64_t i; |
899 if (LookupIntegerMetadata(i, metadata, MetadataType_Series_ExpectedNumberOfInstances)) | 816 if (LookupIntegerMetadata(i, target.metadata_, MetadataType_Series_ExpectedNumberOfInstances)) |
900 { | 817 { |
901 target["ExpectedNumberOfInstances"] = static_cast<int>(i); | 818 target.expectedNumberOfInstances_ = static_cast<int>(i); |
902 target["Status"] = EnumerationToString(transaction.GetSeriesStatus(internalId, i)); | 819 target.status_ = EnumerationToString(transaction.GetSeriesStatus(internalId, i)); |
903 } | 820 } |
904 else | 821 else |
905 { | 822 { |
906 target["ExpectedNumberOfInstances"] = Json::nullValue; | 823 target.expectedNumberOfInstances_ = -1; |
907 target["Status"] = EnumerationToString(SeriesStatus_Unknown); | 824 target.status_ = EnumerationToString(SeriesStatus_Unknown); |
908 } | 825 } |
909 | 826 |
910 break; | 827 break; |
911 } | 828 } |
912 | 829 |
913 case ResourceType_Instance: | 830 case ResourceType_Instance: |
914 { | 831 { |
915 target["Type"] = "Instance"; | |
916 | |
917 FileInfo attachment; | 832 FileInfo attachment; |
918 int64_t revision; // ignored | 833 int64_t revision; // ignored |
919 if (!transaction.LookupAttachment(attachment, revision, internalId, FileContentType_Dicom)) | 834 if (!transaction.LookupAttachment(attachment, revision, internalId, FileContentType_Dicom)) |
920 { | 835 { |
921 throw OrthancException(ErrorCode_InternalError); | 836 throw OrthancException(ErrorCode_InternalError); |
922 } | 837 } |
923 | 838 |
924 target["FileSize"] = static_cast<unsigned int>(attachment.GetUncompressedSize()); | 839 target.fileSize_ = static_cast<unsigned int>(attachment.GetUncompressedSize()); |
925 target["FileUuid"] = attachment.GetUuid(); | 840 target.fileUuid_ = attachment.GetUuid(); |
926 | 841 |
927 int64_t i; | 842 int64_t i; |
928 if (LookupIntegerMetadata(i, metadata, MetadataType_Instance_IndexInSeries)) | 843 if (LookupIntegerMetadata(i, target.metadata_, MetadataType_Instance_IndexInSeries)) |
929 { | 844 { |
930 target["IndexInSeries"] = static_cast<int>(i); | 845 target.indexInSeries_ = static_cast<int>(i); |
931 } | 846 } |
932 else | 847 else |
933 { | 848 { |
934 target["IndexInSeries"] = Json::nullValue; | 849 target.indexInSeries_ = -1; |
935 } | 850 } |
936 | 851 |
937 break; | 852 break; |
938 } | 853 } |
939 | 854 |
940 default: | 855 default: |
941 throw OrthancException(ErrorCode_InternalError); | 856 throw OrthancException(ErrorCode_InternalError); |
942 } | 857 } |
943 | 858 |
944 // check the main dicom tags list has not changed since the resource was stored | 859 // check the main dicom tags list has not changed since the resource was stored |
945 std::string resourceMainDicomTagsSignature = DicomMap::GetDefaultMainDicomTagsSignature(type); | 860 target.mainDicomTagsSignature_ = DicomMap::GetDefaultMainDicomTagsSignature(type); |
946 LookupStringMetadata(resourceMainDicomTagsSignature, metadata, MetadataType_MainDicomTagsSignature); | 861 LookupStringMetadata(target.mainDicomTagsSignature_, target.metadata_, MetadataType_MainDicomTagsSignature); |
947 | |
948 if (resourceMainDicomTagsSignature != DicomMap::GetMainDicomTagsSignature(type)) | |
949 { | |
950 OrthancConfiguration::ReaderLock lock; | |
951 if (lock.GetConfiguration().IsInconsistentDicomTagsLogsEnabled()) | |
952 { | |
953 LOG(WARNING) << Orthanc::GetResourceTypeText(type, false , false) << " has been stored with another version of Main Dicom Tags list, you should POST to /" << Orthanc::GetResourceTypeText(type, true, false) << "/" << tuple.get<2>() << "/reconstruct to update the list of tags saved in DB. Some tags might be missing from this answer."; | |
954 } | |
955 } | |
956 | |
957 | 862 |
958 // Record the remaining information | 863 // Record the remaining information |
959 target["ID"] = tuple.get<2>(); | 864 target.id_ = tuple.get<2>(); |
960 MainDicomTagsToJson(transaction, target, internalId, type, tuple.get<4>()); | 865 |
866 // read all tags from DB | |
867 transaction.GetMainDicomTags(target.tags_, internalId); | |
868 | |
869 // MORE_TAGS: TODO: eventualy get parent dicom tags if requested .... | |
961 | 870 |
962 std::string tmp; | 871 std::string tmp; |
963 | 872 |
964 if (LookupStringMetadata(tmp, metadata, MetadataType_AnonymizedFrom)) | 873 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_AnonymizedFrom)) |
965 { | 874 { |
966 target["AnonymizedFrom"] = tmp; | 875 target.anonymizedFrom_ = tmp; |
967 } | 876 } |
968 | 877 |
969 if (LookupStringMetadata(tmp, metadata, MetadataType_ModifiedFrom)) | 878 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_ModifiedFrom)) |
970 { | 879 { |
971 target["ModifiedFrom"] = tmp; | 880 target.modifiedFrom_ = tmp; |
972 } | 881 } |
973 | 882 |
974 if (type == ResourceType_Patient || | 883 if (type == ResourceType_Patient || |
975 type == ResourceType_Study || | 884 type == ResourceType_Study || |
976 type == ResourceType_Series) | 885 type == ResourceType_Series) |
977 { | 886 { |
978 target["IsStable"] = !transaction.GetTransactionContext().IsUnstableResource(internalId); | 887 target.isStable_ = !transaction.GetTransactionContext().IsUnstableResource(internalId); |
979 | 888 |
980 if (LookupStringMetadata(tmp, metadata, MetadataType_LastUpdate)) | 889 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_LastUpdate)) |
981 { | 890 { |
982 target["LastUpdate"] = tmp; | 891 target.lastUpdate_ = tmp; |
983 } | 892 } |
893 } | |
894 else | |
895 { | |
896 target.isStable_ = false; | |
984 } | 897 } |
985 | 898 |
986 tuple.get<0>() = true; | 899 tuple.get<0>() = true; |
987 } | 900 } |
988 } | 901 } |