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 }