# HG changeset patch # User Sebastien Jodogne # Date 1721390542 -7200 # Node ID 95a3802ad13326c1083bf31ca31c8ec9e3f9d81a # Parent b7bf515864a2659230ee2264bc6d76372b72ad06 initial implementation of protobuf for find diff -r b7bf515864a2 -r 95a3802ad133 OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp --- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Fri Jul 19 10:25:03 2024 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Fri Jul 19 14:02:22 2024 +0200 @@ -135,6 +135,136 @@ } + static void Convert(DatabasePluginMessages::DatabaseConstraint& target, + const DatabaseConstraint& source) + { + target.set_level(Convert(source.GetLevel())); + target.set_tag_group(source.GetTag().GetGroup()); + target.set_tag_element(source.GetTag().GetElement()); + target.set_is_identifier_tag(source.IsIdentifier()); + target.set_is_case_sensitive(source.IsCaseSensitive()); + target.set_is_mandatory(source.IsMandatory()); + + target.mutable_values()->Reserve(source.GetValuesCount()); + for (size_t j = 0; j < source.GetValuesCount(); j++) + { + target.add_values(source.GetValue(j)); + } + + switch (source.GetConstraintType()) + { + case ConstraintType_Equal: + target.set_type(DatabasePluginMessages::CONSTRAINT_EQUAL); + break; + + case ConstraintType_SmallerOrEqual: + target.set_type(DatabasePluginMessages::CONSTRAINT_SMALLER_OR_EQUAL); + break; + + case ConstraintType_GreaterOrEqual: + target.set_type(DatabasePluginMessages::CONSTRAINT_GREATER_OR_EQUAL); + break; + + case ConstraintType_Wildcard: + target.set_type(DatabasePluginMessages::CONSTRAINT_WILDCARD); + break; + + case ConstraintType_List: + target.set_type(DatabasePluginMessages::CONSTRAINT_LIST); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + static DatabasePluginMessages::LabelsConstraintType Convert(LabelsConstraint constraint) + { + switch (constraint) + { + case LabelsConstraint_All: + return DatabasePluginMessages::LABELS_CONSTRAINT_ALL; + + case LabelsConstraint_Any: + return DatabasePluginMessages::LABELS_CONSTRAINT_ANY; + + case LabelsConstraint_None: + return DatabasePluginMessages::LABELS_CONSTRAINT_NONE; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + static void Convert(DatabasePluginMessages::Find_Request_ChildrenSpecification& target, + const FindRequest::ChildrenSpecification& source) + { + target.set_retrieve_identifiers(source.IsRetrieveIdentifiers()); + + for (std::set::const_iterator it = source.GetMetadata().begin(); it != source.GetMetadata().end(); ++it) + { + target.add_retrieve_metadata(*it); + } + + for (std::set::const_iterator it = source.GetMainDicomTags().begin(); it != source.GetMainDicomTags().end(); ++it) + { + DatabasePluginMessages::Find_Request_Tag* tag = target.add_retrieve_main_dicom_tags(); + tag->set_group(it->GetGroup()); + tag->set_element(it->GetElement()); + } + } + + + static void Convert(FindResponse::Resource& target, + ResourceType level, + const DatabasePluginMessages::Find_Response_ResourceContent& source) + { + for (int i = 0; i < source.main_dicom_tags().size(); i++) + { + target.AddStringDicomTag(level, source.main_dicom_tags(i).group(), + source.main_dicom_tags(i).element(), source.main_dicom_tags(i).value()); + } + + for (int i = 0; i < source.metadata().size(); i++) + { + target.AddMetadata(level, static_cast(source.metadata(i).key()), source.metadata(i).value()); + } + } + + + static void Convert(FindResponse::Resource& target, + ResourceType level, + const DatabasePluginMessages::Find_Response_ChildrenContent& source) + { + for (int i = 0; i < source.identifiers().size(); i++) + { + target.AddChildIdentifier(level, source.identifiers(i)); + } + + for (int i = 0; i < source.main_dicom_tags().size(); i++) + { + const DicomTag tag(source.main_dicom_tags(i).group(), source.main_dicom_tags(i).element()); + + for (int j = 0; j < source.main_dicom_tags(i).values().size(); j++) + { + target.AddChildrenMainDicomTagValue(level, tag, source.main_dicom_tags(i).values(j)); + } + } + + for (int i = 0; i < source.metadata().size(); i++) + { + MetadataType key = static_cast(source.metadata(i).key()); + + for (int j = 0; j < source.metadata(i).values().size(); j++) + { + target.AddChildrenMetadataValue(level, key, source.metadata(i).values(j)); + } + } + } + + static void Execute(DatabasePluginMessages::Response& response, const OrthancPluginDatabaseV4& database, const DatabasePluginMessages::Request& request) @@ -973,7 +1103,7 @@ return response.is_disk_size_above().result(); } - + virtual void ApplyLookupResources(std::list& resourcesId, std::list* instancesId, // Can be NULL if not needed const DatabaseConstraints& lookup, @@ -997,47 +1127,7 @@ for (size_t i = 0; i < lookup.GetSize(); i++) { - const DatabaseConstraint& source = lookup.GetConstraint(i); - - DatabasePluginMessages::DatabaseConstraint* target = request.mutable_lookup_resources()->add_lookup(); - target->set_level(Convert(source.GetLevel())); - target->set_tag_group(source.GetTag().GetGroup()); - target->set_tag_element(source.GetTag().GetElement()); - target->set_is_identifier_tag(source.IsIdentifier()); - target->set_is_case_sensitive(source.IsCaseSensitive()); - target->set_is_mandatory(source.IsMandatory()); - - target->mutable_values()->Reserve(source.GetValuesCount()); - for (size_t j = 0; j < source.GetValuesCount(); j++) - { - target->add_values(source.GetValue(j)); - } - - switch (source.GetConstraintType()) - { - case ConstraintType_Equal: - target->set_type(DatabasePluginMessages::CONSTRAINT_EQUAL); - break; - - case ConstraintType_SmallerOrEqual: - target->set_type(DatabasePluginMessages::CONSTRAINT_SMALLER_OR_EQUAL); - break; - - case ConstraintType_GreaterOrEqual: - target->set_type(DatabasePluginMessages::CONSTRAINT_GREATER_OR_EQUAL); - break; - - case ConstraintType_Wildcard: - target->set_type(DatabasePluginMessages::CONSTRAINT_WILDCARD); - break; - - case ConstraintType_List: - target->set_type(DatabasePluginMessages::CONSTRAINT_LIST); - break; - - default: - throw OrthancException(ErrorCode_ParameterOutOfRange); - } + Convert(*request.mutable_lookup_resources()->add_lookup(), lookup.GetConstraint(i)); } for (std::set::const_iterator it = labels.begin(); it != labels.end(); ++it) @@ -1045,23 +1135,7 @@ request.mutable_lookup_resources()->add_labels(*it); } - switch (labelsConstraint) - { - case LabelsConstraint_All: - request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_ALL); - break; - - case LabelsConstraint_Any: - request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_ANY); - break; - - case LabelsConstraint_None: - request.mutable_lookup_resources()->set_labels_constraint(DatabasePluginMessages::LABELS_CONSTRAINT_NONE); - break; - - default: - throw OrthancException(ErrorCode_ParameterOutOfRange); - } + request.mutable_lookup_resources()->set_labels_constraint(Convert(labelsConstraint)); DatabasePluginMessages::TransactionResponse response; ExecuteTransaction(response, DatabasePluginMessages::OPERATION_LOOKUP_RESOURCES, request); @@ -1285,8 +1359,170 @@ const FindRequest& request, const Capabilities& capabilities) ORTHANC_OVERRIDE { - // TODO-FIND - throw OrthancException(ErrorCode_NotImplemented); + if (capabilities.HasFindSupport()) + { + DatabasePluginMessages::TransactionRequest dbRequest; + dbRequest.mutable_find()->set_level(Convert(request.GetLevel())); + + if (request.GetOrthancIdentifiers().HasPatientId()) + { + dbRequest.mutable_find()->set_orthanc_id_patient(request.GetOrthancIdentifiers().GetPatientId()); + } + + if (request.GetOrthancIdentifiers().HasStudyId()) + { + dbRequest.mutable_find()->set_orthanc_id_study(request.GetOrthancIdentifiers().GetStudyId()); + } + + if (request.GetOrthancIdentifiers().HasSeriesId()) + { + dbRequest.mutable_find()->set_orthanc_id_series(request.GetOrthancIdentifiers().GetSeriesId()); + } + + if (request.GetOrthancIdentifiers().HasInstanceId()) + { + dbRequest.mutable_find()->set_orthanc_id_instance(request.GetOrthancIdentifiers().GetInstanceId()); + } + + for (size_t i = 0; i < request.GetDicomTagConstraints().GetSize(); i++) + { + Convert(*dbRequest.mutable_find()->add_dicom_tag_constraints(), request.GetDicomTagConstraints().GetConstraint(i)); + } + + if (request.HasLimits()) + { + dbRequest.mutable_find()->mutable_limits()->set_since(request.GetLimitsSince()); + dbRequest.mutable_find()->mutable_limits()->set_count(request.GetLimitsCount()); + } + + for (std::set::const_iterator it = request.GetLabels().begin(); it != request.GetLabels().end(); ++it) + { + dbRequest.mutable_find()->add_labels(*it); + } + + dbRequest.mutable_find()->set_labels_constraint(Convert(request.GetLabelsConstraint())); + + // TODO-FIND: ordering_ + // TODO-FIND: metadataConstraints__ + + dbRequest.mutable_find()->set_retrieve_main_dicom_tags(request.IsRetrieveMainDicomTags()); + dbRequest.mutable_find()->set_retrieve_metadata(request.IsRetrieveMetadata()); + dbRequest.mutable_find()->set_retrieve_labels(request.IsRetrieveLabels()); + dbRequest.mutable_find()->set_retrieve_attachments(request.IsRetrieveAttachments()); + dbRequest.mutable_find()->set_retrieve_parent_identifier(request.IsRetrieveParentIdentifier()); + dbRequest.mutable_find()->set_retrieve_at_least_one_instance(request.IsRetrieveOneInstanceIdentifier()); + + if (request.GetLevel() == ResourceType_Study || + request.GetLevel() == ResourceType_Series || + request.GetLevel() == ResourceType_Instance) + { + dbRequest.mutable_find()->mutable_parent_patient()->set_retrieve_main_dicom_tags(request.GetParentSpecification(ResourceType_Patient).IsRetrieveMainDicomTags()); + dbRequest.mutable_find()->mutable_parent_patient()->set_retrieve_metadata(request.GetParentSpecification(ResourceType_Patient).IsRetrieveMetadata()); + } + + if (request.GetLevel() == ResourceType_Series || + request.GetLevel() == ResourceType_Instance) + { + dbRequest.mutable_find()->mutable_parent_study()->set_retrieve_main_dicom_tags(request.GetParentSpecification(ResourceType_Study).IsRetrieveMainDicomTags()); + dbRequest.mutable_find()->mutable_parent_study()->set_retrieve_metadata(request.GetParentSpecification(ResourceType_Study).IsRetrieveMetadata()); + } + + if (request.GetLevel() == ResourceType_Instance) + { + dbRequest.mutable_find()->mutable_parent_series()->set_retrieve_main_dicom_tags(request.GetParentSpecification(ResourceType_Series).IsRetrieveMainDicomTags()); + dbRequest.mutable_find()->mutable_parent_series()->set_retrieve_metadata(request.GetParentSpecification(ResourceType_Series).IsRetrieveMetadata()); + } + + if (request.GetLevel() == ResourceType_Patient) + { + Convert(*dbRequest.mutable_find()->mutable_children_studies(), request.GetChildrenSpecification(ResourceType_Study)); + } + + if (request.GetLevel() == ResourceType_Patient || + request.GetLevel() == ResourceType_Study) + { + Convert(*dbRequest.mutable_find()->mutable_children_series(), request.GetChildrenSpecification(ResourceType_Series)); + } + + if (request.GetLevel() == ResourceType_Patient || + request.GetLevel() == ResourceType_Study || + request.GetLevel() == ResourceType_Series) + { + Convert(*dbRequest.mutable_find()->mutable_children_instances(), request.GetChildrenSpecification(ResourceType_Instance)); + } + + DatabasePluginMessages::TransactionResponse dbResponse; + ExecuteTransaction(dbResponse, DatabasePluginMessages::OPERATION_FIND, dbRequest); + + for (int i = 0; i < dbResponse.find().size(); i++) + { + const DatabasePluginMessages::Find_Response& source = dbResponse.find(i); + + std::unique_ptr target( + new FindResponse::Resource(request.GetLevel(), source.internal_id(), source.public_id())); + + if (request.IsRetrieveParentIdentifier()) + { + target->SetParentIdentifier(source.parent_public_id()); + } + + for (int i = 0; i < source.labels().size(); i++) + { + target->AddLabel(source.labels(i)); + } + + for (int i = 0; i < source.attachments().size(); i++) + { + target->AddAttachment(Convert(source.attachments(i))); + } + + Convert(*target, ResourceType_Patient, source.patient_content()); + + if (request.GetLevel() == ResourceType_Study || + request.GetLevel() == ResourceType_Series || + request.GetLevel() == ResourceType_Instance) + { + Convert(*target, ResourceType_Study, source.study_content()); + } + + if (request.GetLevel() == ResourceType_Series || + request.GetLevel() == ResourceType_Instance) + { + Convert(*target, ResourceType_Series, source.series_content()); + } + + if (request.GetLevel() == ResourceType_Instance) + { + Convert(*target, ResourceType_Instance, source.instance_content()); + } + + if (request.GetLevel() == ResourceType_Patient) + { + Convert(*target, ResourceType_Patient, source.children_studies_content()); + } + + if (request.GetLevel() == ResourceType_Patient || + request.GetLevel() == ResourceType_Study) + { + Convert(*target, ResourceType_Study, source.children_series_content()); + } + + if (request.GetLevel() == ResourceType_Patient || + request.GetLevel() == ResourceType_Study || + request.GetLevel() == ResourceType_Series) + { + Convert(*target, ResourceType_Series, source.children_instances_content()); + } + + response.Add(target.release()); + } + + throw OrthancException(ErrorCode_NotImplemented); + } + else + { + throw OrthancException(ErrorCode_NotImplemented); + } } @@ -1294,9 +1530,16 @@ const Capabilities& capabilities, const FindRequest& request) ORTHANC_OVERRIDE { - // TODO-FIND - Compatibility::GenericFind find(*this); - find.ExecuteFind(identifiers, capabilities, request); + if (capabilities.HasFindSupport()) + { + // The integrated version of "ExecuteFind()" should have been called + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + Compatibility::GenericFind find(*this); + find.ExecuteFind(identifiers, capabilities, request); + } } @@ -1305,9 +1548,16 @@ const FindRequest& request, const std::string& identifier) ORTHANC_OVERRIDE { - // TODO-FIND - Compatibility::GenericFind find(*this); - find.ExecuteExpand(response, capabilities, request, identifier); + if (capabilities.HasFindSupport()) + { + // The integrated version of "ExecuteFind()" should have been called + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + Compatibility::GenericFind find(*this); + find.ExecuteExpand(response, capabilities, request, identifier); + } } }; @@ -1397,6 +1647,9 @@ dbCapabilities_.SetAtomicIncrementGlobalProperty(systemInfo.supports_increment_global_property()); dbCapabilities_.SetUpdateAndGetStatistics(systemInfo.has_update_and_get_statistics()); dbCapabilities_.SetMeasureLatency(systemInfo.has_measure_latency()); + dbCapabilities_.SetHasFindSupport(systemInfo.supports_find()); + + printf(">>> %d\n", dbCapabilities_.HasFindSupport()); } open_ = true; @@ -1527,6 +1780,6 @@ bool OrthancPluginDatabaseV4::HasIntegratedFind() const { - return false; // TODO-FIND + return dbCapabilities_.HasFindSupport(); } } diff -r b7bf515864a2 -r 95a3802ad133 OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h --- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Fri Jul 19 10:25:03 2024 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Fri Jul 19 14:02:22 2024 +0200 @@ -121,7 +121,7 @@ #define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER 1 #define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER 12 -#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 4 +#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 5 #if !defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) diff -r b7bf515864a2 -r 95a3802ad133 OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto --- a/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Fri Jul 19 10:25:03 2024 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Fri Jul 19 14:02:22 2024 +0200 @@ -141,6 +141,7 @@ bool supports_increment_global_property = 5; bool has_update_and_get_statistics = 6; bool has_measure_latency = 7; + bool supports_find = 8; // New in Orthanc 1.12.5 } } @@ -288,11 +289,12 @@ OPERATION_GET_CHILDREN_METADATA = 42; OPERATION_GET_LAST_CHANGE_INDEX = 43; OPERATION_LOOKUP_RESOURCE_AND_PARENT = 44; - OPERATION_ADD_LABEL = 45; // New in Orthanc 1.12.0 - OPERATION_REMOVE_LABEL = 46; // New in Orthanc 1.12.0 - OPERATION_LIST_LABELS = 47; // New in Orthanc 1.12.0 - OPERATION_INCREMENT_GLOBAL_PROPERTY = 48; // New in Orthanc 1.12.3 - OPERATION_UPDATE_AND_GET_STATISTICS = 49; // New in Orthanc 1.12.3 + OPERATION_ADD_LABEL = 45; // New in Orthanc 1.12.0 + OPERATION_REMOVE_LABEL = 46; // New in Orthanc 1.12.0 + OPERATION_LIST_LABELS = 47; // New in Orthanc 1.12.0 + OPERATION_INCREMENT_GLOBAL_PROPERTY = 48; // New in Orthanc 1.12.3 + OPERATION_UPDATE_AND_GET_STATISTICS = 49; // New in Orthanc 1.12.3 + OPERATION_FIND = 50; // New in Orthanc 1.12.5 } message Rollback { @@ -824,6 +826,99 @@ } } +message Find { // New in Orthanc 1.12.5 + message Request { // This corresponds to "FindRequest" in C++ + message Tag { + uint32 group = 1; + uint32 element = 2; + } + message Limits { + uint64 since = 1; + uint64 count = 2; + } + message ParentSpecification { + bool retrieve_main_dicom_tags = 1; + bool retrieve_metadata = 2; + } + message ChildrenSpecification { + bool retrieve_identifiers = 1; + repeated int32 retrieve_metadata = 2; + repeated Tag retrieve_main_dicom_tags = 3; + } + + // Part 1 of the request: Constraints + ResourceType level = 1; + string orthanc_id_patient = 2; // optional - GetOrthancIdentifiers().GetPatientId(); + string orthanc_id_study = 3; // optional - GetOrthancIdentifiers().GetStudyId(); + string orthanc_id_series = 4; // optional - GetOrthancIdentifiers().GetSeriesId(); + string orthanc_id_instance = 5; // optional - GetOrthancIdentifiers().GetInstanceId(); + repeated DatabaseConstraint dicom_tag_constraints = 6; + Limits limits = 7; // optional + repeated string labels = 8; + LabelsConstraintType labels_constraint = 9; + + // TODO-FIND: ordering_ + // TODO-FIND: metadataConstraints_ + + // Part 2 of the request: What is to be retrieved + bool retrieve_main_dicom_tags = 100; + bool retrieve_metadata = 101; + bool retrieve_labels = 102; + bool retrieve_attachments = 103; + bool retrieve_parent_identifier = 104; + bool retrieve_at_least_one_instance = 105; + ParentSpecification parent_patient = 106; + ParentSpecification parent_study = 107; + ParentSpecification parent_series = 108; + ChildrenSpecification children_studies = 109; + ChildrenSpecification children_series = 110; + ChildrenSpecification children_instances = 111; + } + + message Response { // This corresponds to "FindResponse" in C++ + message Tag { + uint32 group = 1; + uint32 element = 2; + string value = 3; + } + message Metadata { + int32 key = 1; + string value = 2; + } + message MultipleTags { + uint32 group = 1; + uint32 element = 2; + repeated string values = 3; + } + message MultipleMetadata { + int32 key = 1; + repeated string values = 2; + } + message ResourceContent { + repeated Tag main_dicom_tags = 1; + repeated Metadata metadata = 2; + } + message ChildrenContent { + repeated string identifiers = 1; + repeated MultipleTags main_dicom_tags = 2; + repeated MultipleMetadata metadata = 3; + } + + int64 internal_id = 1; + string public_id = 2; + string parent_public_id = 3; // optional + repeated string labels = 4; + repeated FileInfo attachments = 5; + ResourceContent patient_content = 6; + ResourceContent study_content = 7; + ResourceContent series_content = 8; + ResourceContent instance_content = 9; + ChildrenContent children_studies_content = 10; + ChildrenContent children_series_content = 11; + ChildrenContent children_instances_content = 12; + } +} + message TransactionRequest { sfixed64 transaction = 1; TransactionOperation operation = 2; @@ -878,6 +973,7 @@ ListLabels.Request list_labels = 147; IncrementGlobalProperty.Request increment_global_property = 148; UpdateAndGetStatistics.Request update_and_get_statistics = 149; + Find.Request find = 150; } message TransactionResponse { @@ -931,6 +1027,7 @@ ListLabels.Response list_labels = 147; IncrementGlobalProperty.Response increment_global_property = 148; UpdateAndGetStatistics.Response update_and_get_statistics = 149; + repeated Find.Response find = 150; // One message per found resources } enum RequestType { diff -r b7bf515864a2 -r 95a3802ad133 OrthancServer/Sources/Database/FindRequest.h --- a/OrthancServer/Sources/Database/FindRequest.h Fri Jul 19 10:25:03 2024 +0200 +++ b/OrthancServer/Sources/Database/FindRequest.h Fri Jul 19 14:02:22 2024 +0200 @@ -233,13 +233,15 @@ ResourceType level_; // The level of the response (the filtering on tags, labels and metadata also happens at this level) OrthancIdentifiers orthancIdentifiers_; // The response must belong to this Orthanc resources hierarchy DatabaseConstraints dicomTagConstraints_; // All tags filters (note: the order is not important) - std::deque /* TODO-FIND */ metadataConstraints_; // All metadata filters (note: the order is not important) bool hasLimits_; uint64_t limitsSince_; uint64_t limitsCount_; std::set labels_; LabelsConstraint labelsConstraint_; + + // TODO-FIND std::deque ordering_; // The ordering criteria (note: the order is important !) + std::deque /* TODO-FIND */ metadataConstraints_; // All metadata filters (note: the order is not important) bool retrieveMainDicomTags_; bool retrieveMetadata_; @@ -314,9 +316,11 @@ uint64_t GetLimitsCount() const; - void AddOrdering(const DicomTag& tag, OrderingDirection direction); + void AddOrdering(const DicomTag& tag, + OrderingDirection direction); - void AddOrdering(MetadataType metadataType, OrderingDirection direction); + void AddOrdering(MetadataType metadataType, + OrderingDirection direction); const std::deque& GetOrdering() const { diff -r b7bf515864a2 -r 95a3802ad133 OrthancServer/Sources/Database/IDatabaseWrapper.h --- a/OrthancServer/Sources/Database/IDatabaseWrapper.h Fri Jul 19 10:25:03 2024 +0200 +++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h Fri Jul 19 14:02:22 2024 +0200 @@ -54,6 +54,7 @@ bool hasAtomicIncrementGlobalProperty_; bool hasUpdateAndGetStatistics_; bool hasMeasureLatency_; + bool hasFindSupport_; public: Capabilities() : @@ -62,7 +63,8 @@ hasLabelsSupport_(false), hasAtomicIncrementGlobalProperty_(false), hasUpdateAndGetStatistics_(false), - hasMeasureLatency_(false) + hasMeasureLatency_(false), + hasFindSupport_(false) { } @@ -125,6 +127,16 @@ { return hasMeasureLatency_; } + + void SetHasFindSupport(bool value) + { + hasFindSupport_ = value; + } + + bool HasFindSupport() const + { + return hasFindSupport_; + } };