• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/expand/stemming/stemming-expander.h"
16 
17 #include <memory>
18 #include <string>
19 #include <string_view>
20 #include <utility>
21 #include <vector>
22 
23 #include "icing/text_classifier/lib3/utils/base/statusor.h"
24 #include "icing/absl_ports/mutex.h"
25 #include "icing/expand/expander.h"
26 #include "icing/expand/stemming/stemmer-factory.h"
27 #include "icing/expand/stemming/stemmer.h"
28 #include "icing/util/status-macros.h"
29 
30 namespace icing {
31 namespace lib {
32 
33 /*static*/ libtextclassifier3::StatusOr<std::unique_ptr<StemmingExpander>>
Create(std::string language_code)34 StemmingExpander::Create(std::string language_code) {
35   ICING_ASSIGN_OR_RETURN(std::unique_ptr<Stemmer> stemmer,
36                          stemmer_factory::Create(language_code));
37 
38   return std::unique_ptr<StemmingExpander>(
39       new StemmingExpander(std::move(language_code), std::move(stemmer)));
40 }
41 
Expand(std::string_view term) const42 std::vector<ExpandedTerm> StemmingExpander::Expand(
43     std::string_view term) const {
44   std::vector<ExpandedTerm> result;
45   // Add the original term.
46   result.emplace_back(std::string(term), /*is_stemmed_term=*/false);
47 
48   libtextclassifier3::StatusOr<std::unique_ptr<Stemmer>> stemmer_or =
49       ProduceStemmer();
50   if (!stemmer_or.ok()) {
51     return result;
52   }
53 
54   std::unique_ptr<Stemmer> stemmer = std::move(stemmer_or).ValueOrDie();
55   std::string stemmed_term = stemmer->Stem(term);
56   ReturnStemmer(std::move(stemmer));
57 
58   if (stemmed_term != term) {
59     result.emplace_back(std::move(stemmed_term), /*is_stemmed_term=*/true);
60   }
61   return result;
62 }
63 
64 libtextclassifier3::StatusOr<std::unique_ptr<Stemmer>>
ProduceStemmer() const65 StemmingExpander::ProduceStemmer() const {
66   std::unique_ptr<Stemmer> stemmer = nullptr;
67   {
68     absl_ports::unique_lock l(&mutex_);
69     if (cached_stemmer_ != nullptr) {
70       stemmer = std::move(cached_stemmer_);
71     }
72   }
73   if (stemmer == nullptr) {
74     ICING_ASSIGN_OR_RETURN(stemmer, stemmer_factory::Create(language_code_));
75   }
76 
77   return stemmer;
78 }
79 
ReturnStemmer(std::unique_ptr<Stemmer> stemmer) const80 void StemmingExpander::ReturnStemmer(std::unique_ptr<Stemmer> stemmer) const {
81   absl_ports::unique_lock l(&mutex_);
82   if (!cached_stemmer_) {
83     cached_stemmer_ = std::move(stemmer);
84   }
85 }
86 
87 }  // namespace lib
88 }  // namespace icing
89