1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "engine/engine.h"
31 
32 #include <utility>
33 
34 #include "base/logging.h"
35 #include "base/port.h"
36 #include "converter/connector.h"
37 #include "converter/converter.h"
38 #include "converter/converter_interface.h"
39 #include "converter/immutable_converter.h"
40 #include "converter/immutable_converter_interface.h"
41 #include "converter/segmenter.h"
42 #include "data_manager/data_manager_interface.h"
43 #include "dictionary/dictionary_impl.h"
44 #include "dictionary/dictionary_interface.h"
45 #include "dictionary/pos_group.h"
46 #include "dictionary/pos_matcher.h"
47 #include "dictionary/suffix_dictionary.h"
48 #include "dictionary/suppression_dictionary.h"
49 #include "dictionary/system/system_dictionary.h"
50 #include "dictionary/system/value_dictionary.h"
51 #include "dictionary/user_dictionary.h"
52 #include "dictionary/user_pos.h"
53 #include "engine/engine_interface.h"
54 #include "engine/user_data_manager_interface.h"
55 #include "prediction/dictionary_predictor.h"
56 #include "prediction/predictor.h"
57 #include "prediction/predictor_interface.h"
58 #include "prediction/suggestion_filter.h"
59 #include "prediction/user_history_predictor.h"
60 #include "rewriter/rewriter.h"
61 #include "rewriter/rewriter_interface.h"
62 
63 using mozc::dictionary::DictionaryImpl;
64 using mozc::dictionary::PosGroup;
65 using mozc::dictionary::SuffixDictionary;
66 using mozc::dictionary::SuppressionDictionary;
67 using mozc::dictionary::SystemDictionary;
68 using mozc::dictionary::UserDictionary;
69 using mozc::dictionary::UserPOS;
70 using mozc::dictionary::ValueDictionary;
71 
72 namespace mozc {
73 namespace {
74 
75 class UserDataManagerImpl final : public UserDataManagerInterface {
76  public:
UserDataManagerImpl(PredictorInterface * predictor,RewriterInterface * rewriter)77   explicit UserDataManagerImpl(PredictorInterface *predictor,
78                                RewriterInterface *rewriter)
79       : predictor_(predictor), rewriter_(rewriter) {}
80   ~UserDataManagerImpl() override;
81 
82   bool Sync() override;
83   bool Reload() override;
84   bool ClearUserHistory() override;
85   bool ClearUserPrediction() override;
86   bool ClearUnusedUserPrediction() override;
87   bool ClearUserPredictionEntry(
88       const string &key, const string &value) override;
89   bool Wait() override;
90 
91  private:
92   PredictorInterface *predictor_;
93   RewriterInterface *rewriter_;
94 
95   DISALLOW_COPY_AND_ASSIGN(UserDataManagerImpl);
96 };
97 
~UserDataManagerImpl()98 UserDataManagerImpl::~UserDataManagerImpl() {}
99 
Sync()100 bool UserDataManagerImpl::Sync() {
101   // TODO(noriyukit): In the current implementation, if rewriter_->Sync() fails,
102   // predictor_->Sync() is never called. Check if we should call
103   // predictor_->Sync() or not.
104   return rewriter_->Sync() && predictor_->Sync();
105 }
106 
Reload()107 bool UserDataManagerImpl::Reload() {
108   // TODO(noriyukit): The same TODO as Sync().
109   return rewriter_->Reload() && predictor_->Reload();
110 }
111 
ClearUserHistory()112 bool UserDataManagerImpl::ClearUserHistory() {
113   rewriter_->Clear();
114   return true;
115 }
116 
ClearUserPrediction()117 bool UserDataManagerImpl::ClearUserPrediction() {
118   predictor_->ClearAllHistory();
119   return true;
120 }
121 
ClearUnusedUserPrediction()122 bool UserDataManagerImpl::ClearUnusedUserPrediction() {
123   predictor_->ClearUnusedHistory();
124   return true;
125 }
126 
ClearUserPredictionEntry(const string & key,const string & value)127 bool UserDataManagerImpl::ClearUserPredictionEntry(const string &key,
128                                                    const string &value) {
129   return predictor_->ClearHistoryEntry(key, value);
130 }
131 
Wait()132 bool UserDataManagerImpl::Wait() {
133   return predictor_->Wait();
134 }
135 
136 }  // namespace
137 
CreateDesktopEngine(std::unique_ptr<const DataManagerInterface> data_manager)138 std::unique_ptr<Engine> Engine::CreateDesktopEngine(
139     std::unique_ptr<const DataManagerInterface> data_manager) {
140   std::unique_ptr<Engine> engine(new Engine());
141   engine->Init(data_manager.release(),
142                &DefaultPredictor::CreateDefaultPredictor,
143                false);
144   return engine;
145 }
146 
CreateMobileEngine(std::unique_ptr<const DataManagerInterface> data_manager)147 std::unique_ptr<Engine> Engine::CreateMobileEngine(
148     std::unique_ptr<const DataManagerInterface> data_manager) {
149   std::unique_ptr<Engine> engine(new Engine());
150   engine->Init(data_manager.release(),
151                &MobilePredictor::CreateMobilePredictor,
152                true);
153   return engine;
154 }
155 
156 Engine::Engine() = default;
157 Engine::~Engine() = default;
158 
159 // Since the composite predictor class differs on desktop and mobile, Init()
160 // takes a function pointer to create an instance of predictor class.
Init(const DataManagerInterface * data_manager,PredictorInterface * (* predictor_factory)(PredictorInterface *,PredictorInterface *),bool enable_content_word_learning)161 void Engine::Init(
162     const DataManagerInterface *data_manager,
163     PredictorInterface *(*predictor_factory)(PredictorInterface *,
164                                              PredictorInterface *),
165     bool enable_content_word_learning) {
166   CHECK(data_manager);
167   CHECK(predictor_factory);
168 
169   suppression_dictionary_.reset(new SuppressionDictionary);
170   CHECK(suppression_dictionary_.get());
171 
172   pos_matcher_.reset(
173       new dictionary::POSMatcher(data_manager->GetPOSMatcherData()));
174 
175   user_dictionary_.reset(
176       new UserDictionary(UserPOS::CreateFromDataManager(*data_manager),
177                          *pos_matcher_,
178                          suppression_dictionary_.get()));
179   CHECK(user_dictionary_.get());
180 
181   const char *dictionary_data = NULL;
182   int dictionary_size = 0;
183   data_manager->GetSystemDictionaryData(&dictionary_data, &dictionary_size);
184 
185   SystemDictionary *sysdic =
186       SystemDictionary::Builder(dictionary_data, dictionary_size).Build();
187   dictionary_.reset(new DictionaryImpl(
188       sysdic,  // DictionaryImpl takes the ownership
189       new ValueDictionary(*pos_matcher_, &sysdic->value_trie()),
190       user_dictionary_.get(),
191       suppression_dictionary_.get(),
192       pos_matcher_.get()));
193   CHECK(dictionary_.get());
194 
195   StringPiece suffix_key_array_data, suffix_value_array_data;
196   const uint32 *token_array;
197   data_manager->GetSuffixDictionaryData(&suffix_key_array_data,
198                                         &suffix_value_array_data,
199                                         &token_array);
200   suffix_dictionary_.reset(new SuffixDictionary(suffix_key_array_data,
201                                                 suffix_value_array_data,
202                                                 token_array));
203   CHECK(suffix_dictionary_.get());
204 
205   connector_.reset(Connector::CreateFromDataManager(*data_manager));
206   CHECK(connector_.get());
207 
208   segmenter_.reset(Segmenter::CreateFromDataManager(*data_manager));
209   CHECK(segmenter_.get());
210 
211   pos_group_.reset(new PosGroup(data_manager->GetPosGroupData()));
212   CHECK(pos_group_.get());
213 
214   {
215     const char *data = NULL;
216     size_t size = 0;
217     data_manager->GetSuggestionFilterData(&data, &size);
218     CHECK(data);
219     suggestion_filter_.reset(new SuggestionFilter(data, size));
220   }
221 
222   immutable_converter_.reset(new ImmutableConverterImpl(
223       dictionary_.get(),
224       suffix_dictionary_.get(),
225       suppression_dictionary_.get(),
226       connector_.get(),
227       segmenter_.get(),
228       pos_matcher_.get(),
229       pos_group_.get(),
230       suggestion_filter_.get()));
231   CHECK(immutable_converter_.get());
232 
233   // Since predictor and rewriter require a pointer to a converter instace,
234   // allocate it first without initialization. It is initialized at the end of
235   // this method.
236   // TODO(noriyukit): This circular dependency is a bad design as careful
237   // handling is necessary to avoid infinite loop. Find more beautiful design
238   // and fix it!
239   ConverterImpl *converter_impl = new ConverterImpl;
240   converter_.reset(converter_impl);  // Involves cast to ConverterInterface*.
241   CHECK(converter_.get());
242 
243   {
244     // Create a predictor with three sub-predictors, dictionary predictor, user
245     // history predictor, and extra predictor.
246     PredictorInterface *dictionary_predictor =
247         new DictionaryPredictor(*data_manager,
248                                 converter_.get(),
249                                 immutable_converter_.get(),
250                                 dictionary_.get(),
251                                 suffix_dictionary_.get(),
252                                 connector_.get(),
253                                 segmenter_.get(),
254                                 pos_matcher_.get(),
255                                 suggestion_filter_.get());
256     CHECK(dictionary_predictor);
257 
258     PredictorInterface *user_history_predictor =
259         new UserHistoryPredictor(dictionary_.get(),
260                                  pos_matcher_.get(),
261                                  suppression_dictionary_.get(),
262                                  enable_content_word_learning);
263     CHECK(user_history_predictor);
264 
265     predictor_ = (*predictor_factory)(dictionary_predictor,
266                                       user_history_predictor);
267     CHECK(predictor_);
268   }
269 
270   rewriter_ = new RewriterImpl(converter_impl,
271                                data_manager,
272                                pos_group_.get(),
273                                dictionary_.get());
274   CHECK(rewriter_);
275 
276   converter_impl->Init(pos_matcher_.get(),
277                        suppression_dictionary_.get(),
278                        predictor_,
279                        rewriter_,
280                        immutable_converter_.get());
281 
282   user_data_manager_.reset(new UserDataManagerImpl(predictor_, rewriter_));
283 
284   data_manager_.reset(data_manager);
285 }
286 
Reload()287 bool Engine::Reload() {
288   if (!user_dictionary_.get()) {
289     return true;
290   }
291   VLOG(1) << "Reloading user dictionary";
292   return user_dictionary_->Reload();
293 }
294 
295 }  // namespace mozc
296