comparison OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp @ 5758:ca06dde85358 large-queries

merged find-refactoring -> large-queries
author Alain Mazy <am@orthanc.team>
date Thu, 05 Sep 2024 18:52:27 +0200
parents 5463c3ae3235 95a3802ad133
children 0b44920843b5
comparison
equal deleted inserted replaced
5757:5463c3ae3235 5758:ca06dde85358
29 #endif 29 #endif
30 30
31 #include "../../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h" 31 #include "../../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h"
32 #include "../../../OrthancFramework/Sources/Logging.h" 32 #include "../../../OrthancFramework/Sources/Logging.h"
33 #include "../../../OrthancFramework/Sources/OrthancException.h" 33 #include "../../../OrthancFramework/Sources/OrthancException.h"
34 #include "../../Sources/Database/Compatibility/GenericFind.h"
34 #include "../../Sources/Database/ResourcesContent.h" 35 #include "../../Sources/Database/ResourcesContent.h"
35 #include "../../Sources/Database/VoidDatabaseListener.h" 36 #include "../../Sources/Database/VoidDatabaseListener.h"
36 #include "../../Sources/ServerToolbox.h" 37 #include "../../Sources/ServerToolbox.h"
37 #include "PluginsEnumerations.h" 38 #include "PluginsEnumerations.h"
38 39
132 source.series_instance_uid(), 133 source.series_instance_uid(),
133 source.sop_instance_uid()); 134 source.sop_instance_uid());
134 } 135 }
135 136
136 137
138 static void Convert(DatabasePluginMessages::DatabaseConstraint& target,
139 const DatabaseConstraint& source)
140 {
141 target.set_level(Convert(source.GetLevel()));
142 target.set_tag_group(source.GetTag().GetGroup());
143 target.set_tag_element(source.GetTag().GetElement());
144 target.set_is_identifier_tag(source.IsIdentifier());
145 target.set_is_case_sensitive(source.IsCaseSensitive());
146 target.set_is_mandatory(source.IsMandatory());
147
148 target.mutable_values()->Reserve(source.GetValuesCount());
149 for (size_t j = 0; j < source.GetValuesCount(); j++)
150 {
151 target.add_values(source.GetValue(j));
152 }
153
154 switch (source.GetConstraintType())
155 {
156 case ConstraintType_Equal:
157 target.set_type(DatabasePluginMessages::CONSTRAINT_EQUAL);
158 break;
159
160 case ConstraintType_SmallerOrEqual:
161 target.set_type(DatabasePluginMessages::CONSTRAINT_SMALLER_OR_EQUAL);
162 break;
163
164 case ConstraintType_GreaterOrEqual:
165 target.set_type(DatabasePluginMessages::CONSTRAINT_GREATER_OR_EQUAL);
166 break;
167
168 case ConstraintType_Wildcard:
169 target.set_type(DatabasePluginMessages::CONSTRAINT_WILDCARD);
170 break;
171
172 case ConstraintType_List:
173 target.set_type(DatabasePluginMessages::CONSTRAINT_LIST);
174 break;
175
176 default:
177 throw OrthancException(ErrorCode_ParameterOutOfRange);
178 }
179 }
180
181
182 static DatabasePluginMessages::LabelsConstraintType Convert(LabelsConstraint constraint)
183 {
184 switch (constraint)
185 {
186 case LabelsConstraint_All:
187 return DatabasePluginMessages::LABELS_CONSTRAINT_ALL;
188
189 case LabelsConstraint_Any:
190 return DatabasePluginMessages::LABELS_CONSTRAINT_ANY;
191
192 case LabelsConstraint_None:
193 return DatabasePluginMessages::LABELS_CONSTRAINT_NONE;
194
195 default:
196 throw OrthancException(ErrorCode_ParameterOutOfRange);
197 }
198 }
199
200
201 static void Convert(DatabasePluginMessages::Find_Request_ChildrenSpecification& target,
202 const FindRequest::ChildrenSpecification& source)
203 {
204 target.set_retrieve_identifiers(source.IsRetrieveIdentifiers());
205
206 for (std::set<MetadataType>::const_iterator it = source.GetMetadata().begin(); it != source.GetMetadata().end(); ++it)
207 {
208 target.add_retrieve_metadata(*it);
209 }
210
211 for (std::set<DicomTag>::const_iterator it = source.GetMainDicomTags().begin(); it != source.GetMainDicomTags().end(); ++it)
212 {
213 DatabasePluginMessages::Find_Request_Tag* tag = target.add_retrieve_main_dicom_tags();
214 tag->set_group(it->GetGroup());
215 tag->set_element(it->GetElement());
216 }
217 }
218
219
220 static void Convert(FindResponse::Resource& target,
221 ResourceType level,
222 const DatabasePluginMessages::Find_Response_ResourceContent& source)
223 {
224 for (int i = 0; i < source.main_dicom_tags().size(); i++)
225 {
226 target.AddStringDicomTag(level, source.main_dicom_tags(i).group(),
227 source.main_dicom_tags(i).element(), source.main_dicom_tags(i).value());
228 }
229
230 for (int i = 0; i < source.metadata().size(); i++)
231 {
232 target.AddMetadata(level, static_cast<MetadataType>(source.metadata(i).key()), source.metadata(i).value());
233 }
234 }
235
236
237 static void Convert(FindResponse::Resource& target,
238 ResourceType level,
239 const DatabasePluginMessages::Find_Response_ChildrenContent& source)
240 {
241 for (int i = 0; i < source.identifiers().size(); i++)
242 {
243 target.AddChildIdentifier(level, source.identifiers(i));
244 }
245
246 for (int i = 0; i < source.main_dicom_tags().size(); i++)
247 {
248 const DicomTag tag(source.main_dicom_tags(i).group(), source.main_dicom_tags(i).element());
249
250 for (int j = 0; j < source.main_dicom_tags(i).values().size(); j++)
251 {
252 target.AddChildrenMainDicomTagValue(level, tag, source.main_dicom_tags(i).values(j));
253 }
254 }
255
256 for (int i = 0; i < source.metadata().size(); i++)
257 {
258 MetadataType key = static_cast<MetadataType>(source.metadata(i).key());
259
260 for (int j = 0; j < source.metadata(i).values().size(); j++)
261 {
262 target.AddChildrenMetadataValue(level, key, source.metadata(i).values(j));
263 }
264 }
265 }
266
267
137 static void Execute(DatabasePluginMessages::Response& response, 268 static void Execute(DatabasePluginMessages::Response& response,
138 const OrthancPluginDatabaseV4& database, 269 const OrthancPluginDatabaseV4& database,
139 const DatabasePluginMessages::Request& request) 270 const DatabasePluginMessages::Request& request)
140 { 271 {
141 std::string requestSerialized; 272 std::string requestSerialized;
997 ExecuteTransaction(response, DatabasePluginMessages::OPERATION_IS_DISK_SIZE_ABOVE, request); 1128 ExecuteTransaction(response, DatabasePluginMessages::OPERATION_IS_DISK_SIZE_ABOVE, request);
998 1129
999 return response.is_disk_size_above().result(); 1130 return response.is_disk_size_above().result();
1000 } 1131 }
1001 1132
1002 1133
1003 virtual void ApplyLookupResources(std::list<std::string>& resourcesId, 1134 virtual void ApplyLookupResources(std::list<std::string>& resourcesId,
1004 std::list<std::string>* instancesId, // Can be NULL if not needed 1135 std::list<std::string>* instancesId, // Can be NULL if not needed
1005 const std::vector<DatabaseConstraint>& lookup, 1136 const DatabaseConstraints& lookup,
1006 ResourceType queryLevel, 1137 ResourceType queryLevel,
1007 const std::set<std::string>& labels, 1138 const std::set<std::string>& labels,
1008 LabelsConstraint labelsConstraint, 1139 LabelsConstraint labelsConstraint,
1009 uint32_t limit) ORTHANC_OVERRIDE 1140 uint32_t limit) ORTHANC_OVERRIDE
1010 { 1141 {
1017 DatabasePluginMessages::TransactionRequest request; 1148 DatabasePluginMessages::TransactionRequest request;
1018 request.mutable_lookup_resources()->set_query_level(Convert(queryLevel)); 1149 request.mutable_lookup_resources()->set_query_level(Convert(queryLevel));
1019 request.mutable_lookup_resources()->set_limit(limit); 1150 request.mutable_lookup_resources()->set_limit(limit);
1020 request.mutable_lookup_resources()->set_retrieve_instances_ids(instancesId != NULL); 1151 request.mutable_lookup_resources()->set_retrieve_instances_ids(instancesId != NULL);
1021 1152
1022 request.mutable_lookup_resources()->mutable_lookup()->Reserve(lookup.size()); 1153 request.mutable_lookup_resources()->mutable_lookup()->Reserve(lookup.GetSize());
1023 1154
1024 for (size_t i = 0; i < lookup.size(); i++) 1155 for (size_t i = 0; i < lookup.GetSize(); i++)
1025 { 1156 {
1026 DatabasePluginMessages::DatabaseConstraint* constraint = request.mutable_lookup_resources()->add_lookup(); 1157 Convert(*request.mutable_lookup_resources()->add_lookup(), lookup.GetConstraint(i));
1027 constraint->set_level(Convert(lookup[i].GetLevel()));
1028 constraint->set_tag_group(lookup[i].GetTag().GetGroup());
1029 constraint->set_tag_element(lookup[i].GetTag().GetElement());
1030 constraint->set_is_identifier_tag(lookup[i].IsIdentifier());
1031 constraint->set_is_case_sensitive(lookup[i].IsCaseSensitive());
1032 constraint->set_is_mandatory(lookup[i].IsMandatory());
1033
1034 constraint->mutable_values()->Reserve(lookup[i].GetValuesCount());
1035 for (size_t j = 0; j < lookup[i].GetValuesCount(); j++)
1036 {
1037 constraint->add_values(lookup[i].GetValue(j));
1038 }
1039
1040 switch (lookup[i].GetConstraintType())
1041 {
1042 case ConstraintType_Equal:
1043 constraint->set_type(DatabasePluginMessages::CONSTRAINT_EQUAL);
1044 break;
1045
1046 case ConstraintType_SmallerOrEqual:
1047 constraint->set_type(DatabasePluginMessages::CONSTRAINT_SMALLER_OR_EQUAL);
1048 break;
1049
1050 case ConstraintType_GreaterOrEqual:
1051 constraint->set_type(DatabasePluginMessages::CONSTRAINT_GREATER_OR_EQUAL);
1052 break;
1053
1054 case ConstraintType_Wildcard:
1055 constraint->set_type(DatabasePluginMessages::CONSTRAINT_WILDCARD);
1056 break;
1057
1058 case ConstraintType_List:
1059 constraint->set_type(DatabasePluginMessages::CONSTRAINT_LIST);
1060 break;
1061
1062 default:
1063 throw OrthancException(ErrorCode_ParameterOutOfRange);
1064 }
1065 } 1158 }
1066 1159
1067 for (std::set<std::string>::const_iterator it = labels.begin(); it != labels.end(); ++it) 1160 for (std::set<std::string>::const_iterator it = labels.begin(); it != labels.end(); ++it)
1068 { 1161 {
1069 request.mutable_lookup_resources()->add_labels(*it); 1162 request.mutable_lookup_resources()->add_labels(*it);
1070 } 1163 }
1071 1164
1072 switch (labelsConstraint) 1165 request.mutable_lookup_resources()->set_labels_constraint(Convert(labelsConstraint));
1073 {
1074 case LabelsConstraint_All:
1075 request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_ALL);
1076 break;
1077
1078 case LabelsConstraint_Any:
1079 request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_ANY);
1080 break;
1081
1082 case LabelsConstraint_None:
1083 request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_NONE);
1084 break;
1085
1086 default:
1087 throw OrthancException(ErrorCode_ParameterOutOfRange);
1088 }
1089 1166
1090 DatabasePluginMessages::TransactionResponse response; 1167 DatabasePluginMessages::TransactionResponse response;
1091 ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_RESOURCES, request); 1168 ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_RESOURCES, request);
1092 1169
1093 for (int i = 0; i < response.lookup_resources().resources_ids().size(); i++) 1170 for (int i = 0; i < response.lookup_resources().resources_ids().size(); i++)
1301 1378
1302 virtual void ListAllLabels(std::set<std::string>& target) ORTHANC_OVERRIDE 1379 virtual void ListAllLabels(std::set<std::string>& target) ORTHANC_OVERRIDE
1303 { 1380 {
1304 ListLabelsInternal(target, false, -1); 1381 ListLabelsInternal(target, false, -1);
1305 } 1382 }
1383
1384
1385 virtual void ExecuteFind(FindResponse& response,
1386 const FindRequest& request,
1387 const Capabilities& capabilities) ORTHANC_OVERRIDE
1388 {
1389 if (capabilities.HasFindSupport())
1390 {
1391 DatabasePluginMessages::TransactionRequest dbRequest;
1392 dbRequest.mutable_find()->set_level(Convert(request.GetLevel()));
1393
1394 if (request.GetOrthancIdentifiers().HasPatientId())
1395 {
1396 dbRequest.mutable_find()->set_orthanc_id_patient(request.GetOrthancIdentifiers().GetPatientId());
1397 }
1398
1399 if (request.GetOrthancIdentifiers().HasStudyId())
1400 {
1401 dbRequest.mutable_find()->set_orthanc_id_study(request.GetOrthancIdentifiers().GetStudyId());
1402 }
1403
1404 if (request.GetOrthancIdentifiers().HasSeriesId())
1405 {
1406 dbRequest.mutable_find()->set_orthanc_id_series(request.GetOrthancIdentifiers().GetSeriesId());
1407 }
1408
1409 if (request.GetOrthancIdentifiers().HasInstanceId())
1410 {
1411 dbRequest.mutable_find()->set_orthanc_id_instance(request.GetOrthancIdentifiers().GetInstanceId());
1412 }
1413
1414 for (size_t i = 0; i < request.GetDicomTagConstraints().GetSize(); i++)
1415 {
1416 Convert(*dbRequest.mutable_find()->add_dicom_tag_constraints(), request.GetDicomTagConstraints().GetConstraint(i));
1417 }
1418
1419 if (request.HasLimits())
1420 {
1421 dbRequest.mutable_find()->mutable_limits()->set_since(request.GetLimitsSince());
1422 dbRequest.mutable_find()->mutable_limits()->set_count(request.GetLimitsCount());
1423 }
1424
1425 for (std::set<std::string>::const_iterator it = request.GetLabels().begin(); it != request.GetLabels().end(); ++it)
1426 {
1427 dbRequest.mutable_find()->add_labels(*it);
1428 }
1429
1430 dbRequest.mutable_find()->set_labels_constraint(Convert(request.GetLabelsConstraint()));
1431
1432 // TODO-FIND: ordering_
1433 // TODO-FIND: metadataConstraints__
1434
1435 dbRequest.mutable_find()->set_retrieve_main_dicom_tags(request.IsRetrieveMainDicomTags());
1436 dbRequest.mutable_find()->set_retrieve_metadata(request.IsRetrieveMetadata());
1437 dbRequest.mutable_find()->set_retrieve_labels(request.IsRetrieveLabels());
1438 dbRequest.mutable_find()->set_retrieve_attachments(request.IsRetrieveAttachments());
1439 dbRequest.mutable_find()->set_retrieve_parent_identifier(request.IsRetrieveParentIdentifier());
1440 dbRequest.mutable_find()->set_retrieve_at_least_one_instance(request.IsRetrieveOneInstanceIdentifier());
1441
1442 if (request.GetLevel() == ResourceType_Study ||
1443 request.GetLevel() == ResourceType_Series ||
1444 request.GetLevel() == ResourceType_Instance)
1445 {
1446 dbRequest.mutable_find()->mutable_parent_patient()->set_retrieve_main_dicom_tags(request.GetParentSpecification(ResourceType_Patient).IsRetrieveMainDicomTags());
1447 dbRequest.mutable_find()->mutable_parent_patient()->set_retrieve_metadata(request.GetParentSpecification(ResourceType_Patient).IsRetrieveMetadata());
1448 }
1449
1450 if (request.GetLevel() == ResourceType_Series ||
1451 request.GetLevel() == ResourceType_Instance)
1452 {
1453 dbRequest.mutable_find()->mutable_parent_study()->set_retrieve_main_dicom_tags(request.GetParentSpecification(ResourceType_Study).IsRetrieveMainDicomTags());
1454 dbRequest.mutable_find()->mutable_parent_study()->set_retrieve_metadata(request.GetParentSpecification(ResourceType_Study).IsRetrieveMetadata());
1455 }
1456
1457 if (request.GetLevel() == ResourceType_Instance)
1458 {
1459 dbRequest.mutable_find()->mutable_parent_series()->set_retrieve_main_dicom_tags(request.GetParentSpecification(ResourceType_Series).IsRetrieveMainDicomTags());
1460 dbRequest.mutable_find()->mutable_parent_series()->set_retrieve_metadata(request.GetParentSpecification(ResourceType_Series).IsRetrieveMetadata());
1461 }
1462
1463 if (request.GetLevel() == ResourceType_Patient)
1464 {
1465 Convert(*dbRequest.mutable_find()->mutable_children_studies(), request.GetChildrenSpecification(ResourceType_Study));
1466 }
1467
1468 if (request.GetLevel() == ResourceType_Patient ||
1469 request.GetLevel() == ResourceType_Study)
1470 {
1471 Convert(*dbRequest.mutable_find()->mutable_children_series(), request.GetChildrenSpecification(ResourceType_Series));
1472 }
1473
1474 if (request.GetLevel() == ResourceType_Patient ||
1475 request.GetLevel() == ResourceType_Study ||
1476 request.GetLevel() == ResourceType_Series)
1477 {
1478 Convert(*dbRequest.mutable_find()->mutable_children_instances(), request.GetChildrenSpecification(ResourceType_Instance));
1479 }
1480
1481 DatabasePluginMessages::TransactionResponse dbResponse;
1482 ExecuteTransaction(dbResponse, DatabasePluginMessages::OPERATION_FIND, dbRequest);
1483
1484 for (int i = 0; i < dbResponse.find().size(); i++)
1485 {
1486 const DatabasePluginMessages::Find_Response& source = dbResponse.find(i);
1487
1488 std::unique_ptr<FindResponse::Resource> target(
1489 new FindResponse::Resource(request.GetLevel(), source.internal_id(), source.public_id()));
1490
1491 if (request.IsRetrieveParentIdentifier())
1492 {
1493 target->SetParentIdentifier(source.parent_public_id());
1494 }
1495
1496 for (int i = 0; i < source.labels().size(); i++)
1497 {
1498 target->AddLabel(source.labels(i));
1499 }
1500
1501 for (int i = 0; i < source.attachments().size(); i++)
1502 {
1503 target->AddAttachment(Convert(source.attachments(i)));
1504 }
1505
1506 Convert(*target, ResourceType_Patient, source.patient_content());
1507
1508 if (request.GetLevel() == ResourceType_Study ||
1509 request.GetLevel() == ResourceType_Series ||
1510 request.GetLevel() == ResourceType_Instance)
1511 {
1512 Convert(*target, ResourceType_Study, source.study_content());
1513 }
1514
1515 if (request.GetLevel() == ResourceType_Series ||
1516 request.GetLevel() == ResourceType_Instance)
1517 {
1518 Convert(*target, ResourceType_Series, source.series_content());
1519 }
1520
1521 if (request.GetLevel() == ResourceType_Instance)
1522 {
1523 Convert(*target, ResourceType_Instance, source.instance_content());
1524 }
1525
1526 if (request.GetLevel() == ResourceType_Patient)
1527 {
1528 Convert(*target, ResourceType_Patient, source.children_studies_content());
1529 }
1530
1531 if (request.GetLevel() == ResourceType_Patient ||
1532 request.GetLevel() == ResourceType_Study)
1533 {
1534 Convert(*target, ResourceType_Study, source.children_series_content());
1535 }
1536
1537 if (request.GetLevel() == ResourceType_Patient ||
1538 request.GetLevel() == ResourceType_Study ||
1539 request.GetLevel() == ResourceType_Series)
1540 {
1541 Convert(*target, ResourceType_Series, source.children_instances_content());
1542 }
1543
1544 response.Add(target.release());
1545 }
1546
1547 throw OrthancException(ErrorCode_NotImplemented);
1548 }
1549 else
1550 {
1551 throw OrthancException(ErrorCode_NotImplemented);
1552 }
1553 }
1554
1555
1556 virtual void ExecuteFind(std::list<std::string>& identifiers,
1557 const Capabilities& capabilities,
1558 const FindRequest& request) ORTHANC_OVERRIDE
1559 {
1560 if (capabilities.HasFindSupport())
1561 {
1562 // The integrated version of "ExecuteFind()" should have been called
1563 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1564 }
1565 else
1566 {
1567 Compatibility::GenericFind find(*this);
1568 find.ExecuteFind(identifiers, capabilities, request);
1569 }
1570 }
1571
1572
1573 virtual void ExecuteExpand(FindResponse& response,
1574 const Capabilities& capabilities,
1575 const FindRequest& request,
1576 const std::string& identifier) ORTHANC_OVERRIDE
1577 {
1578 if (capabilities.HasFindSupport())
1579 {
1580 // The integrated version of "ExecuteFind()" should have been called
1581 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1582 }
1583 else
1584 {
1585 Compatibility::GenericFind find(*this);
1586 find.ExecuteExpand(response, capabilities, request, identifier);
1587 }
1588 }
1306 }; 1589 };
1307 1590
1308 1591
1309 OrthancPluginDatabaseV4::OrthancPluginDatabaseV4(SharedLibrary& library, 1592 OrthancPluginDatabaseV4::OrthancPluginDatabaseV4(SharedLibrary& library,
1310 PluginsErrorDictionary& errorDictionary, 1593 PluginsErrorDictionary& errorDictionary,
1390 dbCapabilities_.SetLabelsSupport(systemInfo.supports_labels()); 1673 dbCapabilities_.SetLabelsSupport(systemInfo.supports_labels());
1391 dbCapabilities_.SetAtomicIncrementGlobalProperty(systemInfo.supports_increment_global_property()); 1674 dbCapabilities_.SetAtomicIncrementGlobalProperty(systemInfo.supports_increment_global_property());
1392 dbCapabilities_.SetUpdateAndGetStatistics(systemInfo.has_update_and_get_statistics()); 1675 dbCapabilities_.SetUpdateAndGetStatistics(systemInfo.has_update_and_get_statistics());
1393 dbCapabilities_.SetMeasureLatency(systemInfo.has_measure_latency()); 1676 dbCapabilities_.SetMeasureLatency(systemInfo.has_measure_latency());
1394 dbCapabilities_.SetHasExtendedChanges(systemInfo.has_extended_changes()); 1677 dbCapabilities_.SetHasExtendedChanges(systemInfo.has_extended_changes());
1678 dbCapabilities_.SetHasFindSupport(systemInfo.supports_find());
1395 } 1679 }
1396 1680
1397 open_ = true; 1681 open_ = true;
1398 } 1682 }
1399 1683
1516 else 1800 else
1517 { 1801 {
1518 return dbCapabilities_; 1802 return dbCapabilities_;
1519 } 1803 }
1520 } 1804 }
1805
1806
1807 bool OrthancPluginDatabaseV4::HasIntegratedFind() const
1808 {
1809 return dbCapabilities_.HasFindSupport();
1810 }
1521 } 1811 }