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