1 // Copyright (C) 2024 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 #include "icing/util/scorable_property_set.h"
16
17 #include <cstdint>
18 #include <memory>
19 #include <optional>
20 #include <string>
21 #include <string_view>
22 #include <utility>
23 #include <vector>
24
25 #include "icing/text_classifier/lib3/utils/base/statusor.h"
26 #include "icing/absl_ports/canonical_errors.h"
27 #include "icing/legacy/core/icing-string-util.h"
28 #include "icing/proto/internal/scorable_property_set.pb.h"
29 #include "icing/proto/schema.pb.h"
30 #include "icing/schema/property-util.h"
31 #include "icing/schema/schema-store.h"
32 #include "icing/schema/scorable_property_manager.h"
33 #include "icing/store/document-filter-data.h"
34 #include "icing/util/status-macros.h"
35
36 namespace icing {
37 namespace lib {
38
39 libtextclassifier3::StatusOr<std::unique_ptr<ScorablePropertySet>>
Create(ScorablePropertySetProto && scorable_property_set_proto,SchemaTypeId schema_type_id,const SchemaStore * schema_store)40 ScorablePropertySet::Create(
41 ScorablePropertySetProto&& scorable_property_set_proto,
42 SchemaTypeId schema_type_id, const SchemaStore* schema_store) {
43 ICING_ASSIGN_OR_RETURN(
44 const std::vector<ScorablePropertyManager::ScorablePropertyInfo>*
45 ordered_scorable_property_info,
46 schema_store->GetOrderedScorablePropertyInfo(schema_type_id));
47 if (ordered_scorable_property_info == nullptr ||
48 ordered_scorable_property_info->size() !=
49 scorable_property_set_proto.properties_size()) {
50 return absl_ports::InvalidArgumentError(IcingStringUtil::StringPrintf(
51 "ScorablePropertySetProto data is inconsistent with the schema config "
52 "of type id %d",
53 schema_type_id));
54 }
55 return std::unique_ptr<ScorablePropertySet>(new ScorablePropertySet(
56 std::move(scorable_property_set_proto), schema_type_id, schema_store));
57 }
58
59 libtextclassifier3::StatusOr<std::unique_ptr<ScorablePropertySet>>
Create(const DocumentProto & document,SchemaTypeId schema_type_id,const SchemaStore * schema_store)60 ScorablePropertySet::Create(const DocumentProto& document,
61 SchemaTypeId schema_type_id,
62 const SchemaStore* schema_store) {
63 ICING_ASSIGN_OR_RETURN(
64 const std::vector<ScorablePropertyManager::ScorablePropertyInfo>*
65 ordered_scorable_property_info,
66 schema_store->GetOrderedScorablePropertyInfo(schema_type_id));
67 if (ordered_scorable_property_info == nullptr) {
68 // It should never happen
69 return absl_ports::InternalError(
70 "SchemaStore::ordered_scorable_property_paths returned nullptr");
71 }
72 if (ordered_scorable_property_info->empty()) {
73 return absl_ports::InvalidArgumentError(IcingStringUtil::StringPrintf(
74 "No scorable property defined under the config of type id %d",
75 schema_type_id));
76 }
77
78 ScorablePropertySetProto scorable_property_set_proto_to_build;
79 for (const ScorablePropertyManager::ScorablePropertyInfo&
80 scorable_property_info : *ordered_scorable_property_info) {
81 ScorablePropertyProto* new_property =
82 scorable_property_set_proto_to_build.add_properties();
83
84 if (scorable_property_info.data_type ==
85 PropertyConfigProto::DataType::DOUBLE) {
86 libtextclassifier3::StatusOr<std::vector<double>> content_or =
87 property_util::ExtractPropertyValuesFromDocument<double>(
88 document, scorable_property_info.property_path);
89 if (content_or.ok()) {
90 new_property->mutable_double_values()->Add(
91 content_or.ValueOrDie().begin(), content_or.ValueOrDie().end());
92 }
93 } else if (scorable_property_info.data_type ==
94 PropertyConfigProto::DataType::INT64) {
95 libtextclassifier3::StatusOr<std::vector<int64_t>> content_or =
96 property_util::ExtractPropertyValuesFromDocument<int64_t>(
97 document, scorable_property_info.property_path);
98 if (content_or.ok()) {
99 new_property->mutable_int64_values()->Add(
100 content_or.ValueOrDie().begin(), content_or.ValueOrDie().end());
101 }
102 } else if (scorable_property_info.data_type ==
103 PropertyConfigProto::DataType::BOOLEAN) {
104 libtextclassifier3::StatusOr<std::vector<bool>> content_or =
105 property_util::ExtractPropertyValuesFromDocument<bool>(
106 document, scorable_property_info.property_path);
107 if (content_or.ok()) {
108 new_property->mutable_boolean_values()->Add(
109 content_or.ValueOrDie().begin(), content_or.ValueOrDie().end());
110 }
111 }
112 }
113 return std::unique_ptr<ScorablePropertySet>(
114 new ScorablePropertySet(std::move(scorable_property_set_proto_to_build),
115 schema_type_id, schema_store));
116 }
117
GetScorablePropertyProto(const std::string & property_path) const118 const ScorablePropertyProto* ScorablePropertySet::GetScorablePropertyProto(
119 const std::string& property_path) const {
120 libtextclassifier3::StatusOr<std::optional<int>> index_or =
121 schema_store_->GetScorablePropertyIndex(schema_type_id_, property_path);
122 if (!index_or.ok() || !index_or.ValueOrDie().has_value()) {
123 return nullptr;
124 }
125 return &scorable_property_set_proto_.properties(
126 index_or.ValueOrDie().value());
127 }
128
ScorablePropertySet(ScorablePropertySetProto && scorable_property_set_proto,SchemaTypeId schema_type_id,const SchemaStore * schema_store)129 ScorablePropertySet::ScorablePropertySet(
130 ScorablePropertySetProto&& scorable_property_set_proto,
131 SchemaTypeId schema_type_id, const SchemaStore* schema_store)
132 : scorable_property_set_proto_(std::move(scorable_property_set_proto)),
133 schema_type_id_(schema_type_id),
134 schema_store_(schema_store) {}
135
136 } // namespace lib
137 } // namespace icing
138