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,