xref: /aosp_15_r20/external/icing/icing/store/suggestion-result-checker-impl.h (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1 // Copyright (C) 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ICING_STORE_SUGGESTION_RESULT_CHECKER_IMPL_H_
16 #define ICING_STORE_SUGGESTION_RESULT_CHECKER_IMPL_H_
17 
18 #include "icing/schema/section.h"
19 #include "icing/store/document-id.h"
20 #include "icing/store/document-store.h"
21 #include "icing/store/namespace-id.h"
22 #include "icing/store/suggestion-result-checker.h"
23 
24 namespace icing {
25 namespace lib {
26 
27 class SuggestionResultCheckerImpl : public SuggestionResultChecker {
28  public:
SuggestionResultCheckerImpl(const DocumentStore * document_store,const SchemaStore * schema_store,std::unordered_set<NamespaceId> target_namespace_ids,std::unordered_map<NamespaceId,std::unordered_set<DocumentId>> document_id_filter_map,std::unordered_set<SchemaTypeId> target_schema_type_ids,std::unordered_map<SchemaTypeId,SectionIdMask> property_filter_map,std::string target_section,std::unordered_set<DocumentId> search_base,int64_t current_time_ms)29   explicit SuggestionResultCheckerImpl(
30       const DocumentStore* document_store, const SchemaStore* schema_store,
31       std::unordered_set<NamespaceId> target_namespace_ids,
32       std::unordered_map<NamespaceId, std::unordered_set<DocumentId>>
33           document_id_filter_map,
34       std::unordered_set<SchemaTypeId> target_schema_type_ids,
35       std::unordered_map<SchemaTypeId, SectionIdMask> property_filter_map,
36       std::string target_section, std::unordered_set<DocumentId> search_base,
37       int64_t current_time_ms)
38       : document_store_(*document_store),
39         schema_store_(*schema_store),
40         target_namespace_ids_(std::move(target_namespace_ids)),
41         document_id_filter_map_(std::move(document_id_filter_map)),
42         target_schema_type_ids_(std::move(target_schema_type_ids)),
43         property_filter_map_(std::move(property_filter_map)),
44         target_section_(std::move(target_section)),
45         search_base_(std::move(search_base)),
46         current_time_ms_(current_time_ms) {}
47 
MatchesTargetNamespace(NamespaceId namespace_id)48   bool MatchesTargetNamespace(NamespaceId namespace_id) const {
49     return target_namespace_ids_.empty() ||
50            target_namespace_ids_.find(namespace_id) !=
51                target_namespace_ids_.end();
52   }
53 
MatchesTargetDocumentIds(NamespaceId namespace_id,DocumentId document_id)54   bool MatchesTargetDocumentIds(NamespaceId namespace_id,
55                                 DocumentId document_id) const {
56     if (document_id_filter_map_.empty()) {
57       return true;
58     }
59     auto document_ids_itr = document_id_filter_map_.find(namespace_id);
60     // The client doesn't set desired document ids in this namespace, or the
61     // client doesn't want this document.
62     return document_ids_itr == document_id_filter_map_.end() ||
63            document_ids_itr->second.find(document_id) !=
64                document_ids_itr->second.end();
65   }
66 
MatchesTargetSchemaType(SchemaTypeId schema_type_id)67   bool MatchesTargetSchemaType(SchemaTypeId schema_type_id) const {
68     return target_schema_type_ids_.empty() ||
69            target_schema_type_ids_.find(schema_type_id) !=
70                target_schema_type_ids_.end();
71   }
72 
MatchesTargetSection(SchemaTypeId schema_type_id,SectionId section_id)73   bool MatchesTargetSection(SchemaTypeId schema_type_id,
74                             SectionId section_id) const {
75     if (target_section_.empty()) {
76       return true;
77     }
78     auto section_metadata_or =
79         schema_store_.GetSectionMetadata(schema_type_id, section_id);
80     if (!section_metadata_or.ok()) {
81       // cannot find the target section metadata.
82       return false;
83     }
84     const SectionMetadata* section_metadata = section_metadata_or.ValueOrDie();
85     return section_metadata->path == target_section_;
86   }
87 
MatchesSearchBase(DocumentId document_id)88   bool MatchesSearchBase(DocumentId document_id) const {
89     return search_base_.empty() ||
90            search_base_.find(document_id) != search_base_.end();
91   }
92 
MatchesPropertyFilter(SchemaTypeId schema_type_id,SectionId section_id)93   bool MatchesPropertyFilter(SchemaTypeId schema_type_id,
94                              SectionId section_id) const {
95     if (property_filter_map_.empty()) {
96       return true;
97     }
98     auto section_mask_itr = property_filter_map_.find(schema_type_id);
99     return section_mask_itr == property_filter_map_.end() ||
100            (section_mask_itr->second & (UINT64_C(1) << section_id)) != 0;
101   }
102 
BelongsToTargetResults(DocumentId document_id,SectionId section_id)103   bool BelongsToTargetResults(DocumentId document_id,
104                               SectionId section_id) const override {
105     // Get the document filter data first.
106     auto document_filter_data_optional_ =
107         document_store_.GetAliveDocumentFilterData(document_id,
108                                                    current_time_ms_);
109     if (!document_filter_data_optional_) {
110       // The document doesn't exist.
111       return false;
112     }
113     DocumentFilterData document_filter_data =
114         document_filter_data_optional_.value();
115 
116     if (!MatchesTargetNamespace(document_filter_data.namespace_id())) {
117       return false;
118     }
119     if (!MatchesTargetDocumentIds(document_filter_data.namespace_id(),
120                                   document_id)) {
121       return false;
122     }
123     if (!MatchesTargetSchemaType(document_filter_data.schema_type_id())) {
124       return false;
125     }
126     if (!MatchesTargetSection(document_filter_data.schema_type_id(),
127                               section_id)) {
128       return false;
129     }
130     if (!MatchesSearchBase(document_id)) {
131       return false;
132     }
133     if (!MatchesPropertyFilter(document_filter_data.schema_type_id(),
134                                section_id)) {
135       return false;
136     }
137     return true;
138   }
139   const DocumentStore& document_store_;
140   const SchemaStore& schema_store_;
141   std::unordered_set<NamespaceId> target_namespace_ids_;
142   std::unordered_map<NamespaceId, std::unordered_set<DocumentId>>
143       document_id_filter_map_;
144   std::unordered_set<SchemaTypeId> target_schema_type_ids_;
145   std::unordered_map<SchemaTypeId, SectionIdMask> property_filter_map_;
146   std::string target_section_;
147   std::unordered_set<DocumentId> search_base_;
148   int64_t current_time_ms_;
149 };
150 
151 }  // namespace lib
152 }  // namespace icing
153 
154 #endif  // ICING_STORE_SUGGESTION_RESULT_CHECKER_IMPL_H_