Mercurial > hg > orthanc
comparison OrthancServer/ServerIndex.cpp @ 200:9c58b2b03cf0
refactoring of read operations
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 27 Nov 2012 16:49:22 +0100 |
parents | dfa2899d9960 |
children | bee20e978835 |
comparison
equal
deleted
inserted
replaced
199:dfa2899d9960 | 200:9c58b2b03cf0 |
---|---|
174 s.BindString(3, flattened.GetElement(i).GetValue().AsString()); | 174 s.BindString(3, flattened.GetElement(i).GetValue().AsString()); |
175 s.Run(); | 175 s.Run(); |
176 } | 176 } |
177 } | 177 } |
178 | 178 |
179 bool ServerIndex::GetMainDicomStringTag(std::string& result, | |
180 const std::string& uuid, | |
181 const DicomTag& tag) | |
182 { | |
183 SQLite::Statement s(db_, SQLITE_FROM_HERE, | |
184 "SELECT * FROM MainDicomTags WHERE uuid=? AND tagGroup=? AND tagElement=?"); | |
185 s.BindString(0, uuid); | |
186 s.BindInt(1, tag.GetGroup()); | |
187 s.BindInt(2, tag.GetElement()); | |
188 if (!s.Step()) | |
189 { | |
190 return false; | |
191 } | |
192 | |
193 result = s.ColumnString(0); | |
194 return true; | |
195 } | |
196 | |
197 bool ServerIndex::GetMainDicomIntTag(int& result, | |
198 const std::string& uuid, | |
199 const DicomTag& tag) | |
200 { | |
201 std::string s; | |
202 if (!GetMainDicomStringTag(s, uuid, tag)) | |
203 { | |
204 return false; | |
205 } | |
206 | |
207 try | |
208 { | |
209 result = boost::lexical_cast<int>(s); | |
210 return true; | |
211 } | |
212 catch (boost::bad_lexical_cast) | |
213 { | |
214 return false; | |
215 } | |
216 } | |
217 | |
218 | |
219 bool ServerIndex::HasInstance(DicomInstanceHasher& hasher) | 179 bool ServerIndex::HasInstance(DicomInstanceHasher& hasher) |
220 { | 180 { |
221 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE dicomInstance=?"); | 181 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE dicomInstance=?"); |
222 s.BindString(0, hasher.GetInstanceUid()); | 182 s.BindString(0, hasher.GetInstanceUid()); |
223 return s.Step(); | 183 return s.Step(); |
302 s.BindString(1, hasher.HashStudy()); | 262 s.BindString(1, hasher.HashStudy()); |
303 s.BindString(2, hasher.GetSeriesUid()); | 263 s.BindString(2, hasher.GetSeriesUid()); |
304 | 264 |
305 const DicomValue* expectedNumberOfInstances; | 265 const DicomValue* expectedNumberOfInstances; |
306 if (//(expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_FRAMES)) != NULL || | 266 if (//(expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_FRAMES)) != NULL || |
307 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || | 267 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || |
308 //(expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL || | 268 //(expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL || |
309 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) | 269 (expectedNumberOfInstances = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) |
310 { | 270 { |
311 s.BindInt(3, boost::lexical_cast<unsigned int>(expectedNumberOfInstances->AsString())); | 271 s.BindInt(3, boost::lexical_cast<unsigned int>(expectedNumberOfInstances->AsString())); |
312 } | 272 } |
313 else | 273 else |
314 { | 274 { |
379 RecordChange("patients", hasher.HashPatient()); | 339 RecordChange("patients", hasher.HashPatient()); |
380 | 340 |
381 DicomMap dicom; | 341 DicomMap dicom; |
382 dicomSummary.ExtractPatientInformation(dicom); | 342 dicomSummary.ExtractPatientInformation(dicom); |
383 StoreMainDicomTags(hasher.HashPatient(), dicom); | 343 StoreMainDicomTags(hasher.HashPatient(), dicom); |
384 } | |
385 | |
386 | |
387 void ServerIndex::GetMainDicomTags(DicomMap& map, | |
388 const std::string& uuid) | |
389 { | |
390 map.Clear(); | |
391 | |
392 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM MainDicomTags WHERE uuid=?"); | |
393 s.BindString(0, uuid); | |
394 while (s.Step()) | |
395 { | |
396 map.SetValue(s.ColumnInt(1), | |
397 s.ColumnInt(2), | |
398 s.ColumnString(3)); | |
399 } | |
400 } | |
401 | |
402 void ServerIndex::MainDicomTagsToJson(Json::Value& target, | |
403 const std::string& uuid) | |
404 { | |
405 DicomMap map; | |
406 GetMainDicomTags(map, uuid); | |
407 target["MainDicomTags"] = Json::objectValue; | |
408 FromDcmtkBridge::ToJson(target["MainDicomTags"], map); | |
409 } | 344 } |
410 | 345 |
411 | 346 |
412 bool ServerIndex::DeleteInternal(Json::Value& target, | 347 bool ServerIndex::DeleteInternal(Json::Value& target, |
413 const std::string& uuid, | 348 const std::string& uuid, |
604 } | 539 } |
605 | 540 |
606 if (isNewSeries) | 541 if (isNewSeries) |
607 { | 542 { |
608 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || | 543 if ((value = dicomSummary.TestAndGetValue(DICOM_TAG_NUMBER_OF_SLICES)) != NULL || |
609 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL) | 544 (value = dicomSummary.TestAndGetValue(DICOM_TAG_IMAGES_IN_ACQUISITION)) != NULL || |
545 (value = dicomSummary.TestAndGetValue(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)) != NULL) | |
610 { | 546 { |
611 db2_->SetMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, value->AsString()); | 547 db2_->SetMetadata(series, MetadataType_Series_ExpectedNumberOfInstances, value->AsString()); |
612 } | 548 } |
613 } | 549 } |
614 | 550 |
735 boost::mutex::scoped_lock scoped_lock(mutex_); | 671 boost::mutex::scoped_lock scoped_lock(mutex_); |
736 return db2_->GetTotalUncompressedSize(); | 672 return db2_->GetTotalUncompressedSize(); |
737 } | 673 } |
738 | 674 |
739 | 675 |
740 | |
741 | |
742 SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) | |
743 { | |
744 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT expectedNumberOfInstances FROM Series WHERE uuid=?"); | |
745 s1.BindString(0, seriesUuid); | |
746 if (!s1.Step() || s1.ColumnIsNull(0)) | |
747 { | |
748 return SeriesStatus_Unknown; | |
749 } | |
750 | |
751 int numberOfInstances = s1.ColumnInt(0); | |
752 if (numberOfInstances < 0) | |
753 { | |
754 return SeriesStatus_Unknown; | |
755 } | |
756 | |
757 std::set<int> instances; | |
758 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT indexInSeries FROM Instances WHERE parentSeries=?"); | |
759 s2.BindString(0, seriesUuid); | |
760 while (s2.Step()) | |
761 { | |
762 int index = s2.ColumnInt(0); | |
763 if (index <= 0 || index > numberOfInstances) | |
764 { | |
765 // Out-of-range instance index | |
766 return SeriesStatus_Inconsistent; | |
767 } | |
768 | |
769 if (instances.find(index) != instances.end()) | |
770 { | |
771 // Twice the same instance index | |
772 return SeriesStatus_Inconsistent; | |
773 } | |
774 | |
775 instances.insert(index); | |
776 } | |
777 | |
778 for (int i = 1; i <= numberOfInstances; i++) | |
779 { | |
780 if (instances.find(i) == instances.end()) | |
781 { | |
782 return SeriesStatus_Missing; | |
783 } | |
784 } | |
785 | |
786 return SeriesStatus_Complete; | |
787 } | |
788 | |
789 | |
790 SeriesStatus ServerIndex::GetSeriesStatus(int id) | 676 SeriesStatus ServerIndex::GetSeriesStatus(int id) |
791 { | 677 { |
792 // Get the expected number of instances in this series (from the metadata) | 678 // Get the expected number of instances in this series (from the metadata) |
793 std::string s = db2_->GetMetadata(id, MetadataType_Series_ExpectedNumberOfInstances); | 679 std::string s = db2_->GetMetadata(id, MetadataType_Series_ExpectedNumberOfInstances); |
794 | 680 |
956 case ResourceType_Series: | 842 case ResourceType_Series: |
957 { | 843 { |
958 result["Type"] = "Series"; | 844 result["Type"] = "Series"; |
959 result["Status"] = ToString(GetSeriesStatus(id)); | 845 result["Status"] = ToString(GetSeriesStatus(id)); |
960 | 846 |
961 std::string n = db2_->GetMetadata(id, MetadataType_Series_ExpectedNumberOfInstances); | 847 int i; |
962 if (n.size() > 0) | 848 if (db2_->GetMetadataAsInteger(i, id, MetadataType_Series_ExpectedNumberOfInstances)) |
963 { | 849 result["ExpectedNumberOfInstances"] = i; |
964 result["ExpectedNumberOfInstances"] = n; | 850 else |
965 } | 851 result["ExpectedNumberOfInstances"] = Json::nullValue; |
852 | |
853 break; | |
854 } | |
855 | |
856 case ResourceType_Instance: | |
857 { | |
858 result["Type"] = "Instance"; | |
859 | |
860 std::string fileUuid; | |
861 uint64_t uncompressedSize; | |
862 if (!db2_->LookupFile(id, AttachedFileType_Dicom, fileUuid, uncompressedSize)) | |
863 { | |
864 throw OrthancException(ErrorCode_InternalError); | |
865 } | |
866 | |
867 result["FileSize"] = static_cast<unsigned int>(uncompressedSize); | |
868 result["FileUuid"] = fileUuid; | |
869 | |
870 int i; | |
871 if (db2_->GetMetadataAsInteger(i, id, MetadataType_Instance_IndexInSeries)) | |
872 result["IndexInSeries"] = i; | |
966 else | 873 else |
967 { | 874 result["IndexInSeries"] = Json::nullValue; |
968 result["ExpectedNumberOfInstances"] = Json::nullValue; | 875 |
969 } | |
970 break; | 876 break; |
971 } | 877 } |
972 | |
973 case ResourceType_Instance: | |
974 result["Type"] = "Instance"; | |
975 break; | |
976 | 878 |
977 default: | 879 default: |
978 throw OrthancException(ErrorCode_InternalError); | 880 throw OrthancException(ErrorCode_InternalError); |
979 } | 881 } |
980 | 882 |
981 // Record the remaining information | 883 // Record the remaining information |
982 result["ID"] = publicId; | 884 result["ID"] = publicId; |
983 MainDicomTagsToJson2(result, id); | 885 MainDicomTagsToJson2(result, id); |
984 | 886 |
985 return true; | 887 return true; |
986 } | |
987 | |
988 | |
989 bool ServerIndex::GetInstance(Json::Value& result, | |
990 const std::string& instanceUuid) | |
991 { | |
992 assert(result.type() == Json::objectValue); | |
993 boost::mutex::scoped_lock scoped_lock(mutex_); | |
994 | |
995 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid, indexInSeries FROM Instances WHERE uuid=?"); | |
996 s.BindString(0, instanceUuid); | |
997 if (!s.Step()) | |
998 { | |
999 return false; | |
1000 } | |
1001 else | |
1002 { | |
1003 result["ID"] = instanceUuid; | |
1004 result["ParentSeries"] = s.ColumnString(0); | |
1005 result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? | |
1006 result["FileUuid"] = s.ColumnString(3); | |
1007 MainDicomTagsToJson(result, instanceUuid); | |
1008 | |
1009 if (s.ColumnIsNull(4)) | |
1010 { | |
1011 result["IndexInSeries"] = Json::nullValue; | |
1012 } | |
1013 else | |
1014 { | |
1015 result["IndexInSeries"] = s.ColumnInt(4); | |
1016 } | |
1017 | |
1018 result["Type"] = "Instance"; | |
1019 | |
1020 return true; | |
1021 } | |
1022 } | |
1023 | |
1024 | |
1025 bool ServerIndex::GetSeries(Json::Value& result, | |
1026 const std::string& seriesUuid) | |
1027 { | |
1028 return LookupResource(result, seriesUuid, ResourceType_Series); | |
1029 | |
1030 assert(result.type() == Json::objectValue); | |
1031 boost::mutex::scoped_lock scoped_lock(mutex_); | |
1032 | |
1033 SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries, expectedNumberOfInstances FROM Series WHERE uuid=?"); | |
1034 s1.BindString(0, seriesUuid); | |
1035 if (!s1.Step()) | |
1036 { | |
1037 return false; | |
1038 } | |
1039 | |
1040 result["ID"] = seriesUuid; | |
1041 result["ParentStudy"] = s1.ColumnString(0); | |
1042 MainDicomTagsToJson(result, seriesUuid); | |
1043 | |
1044 Json::Value instances(Json::arrayValue); | |
1045 SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE parentSeries=?"); | |
1046 s2.BindString(0, seriesUuid); | |
1047 while (s2.Step()) | |
1048 { | |
1049 instances.append(s2.ColumnString(0)); | |
1050 } | |
1051 | |
1052 result["Instances"] = instances; | |
1053 | |
1054 if (s1.ColumnIsNull(2)) | |
1055 { | |
1056 result["ExpectedNumberOfInstances"] = Json::nullValue; | |
1057 } | |
1058 else | |
1059 { | |
1060 result["ExpectedNumberOfInstances"] = s1.ColumnInt(2); | |
1061 } | |
1062 | |
1063 result["Status"] = ToString(GetSeriesStatus(seriesUuid)); | |
1064 result["Type"] = "Series"; | |
1065 | |
1066 return true; | |
1067 } | |
1068 | |
1069 | |
1070 bool ServerIndex::GetStudy(Json::Value& result, | |
1071 const std::string& studyUuid) | |
1072 { | |
1073 return LookupResource(result, studyUuid, ResourceType_Study); | |
1074 } | |
1075 | |
1076 | |
1077 bool ServerIndex::GetPatient(Json::Value& result, | |
1078 const std::string& patientUuid) | |
1079 { | |
1080 return LookupResource(result, patientUuid, ResourceType_Patient); | |
1081 } | 888 } |
1082 | 889 |
1083 | 890 |
1084 bool ServerIndex::GetFile(std::string& fileUuid, | 891 bool ServerIndex::GetFile(std::string& fileUuid, |
1085 CompressionType& compressionType, | 892 CompressionType& compressionType, |