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 "dictionary/dictionary_impl.h"
31
32 #include <string>
33
34 #include "base/logging.h"
35 #include "base/string_piece.h"
36 #include "base/util.h"
37 #include "dictionary/dictionary_interface.h"
38 #include "dictionary/dictionary_token.h"
39 #include "dictionary/pos_matcher.h"
40 #include "dictionary/suppression_dictionary.h"
41 #include "protocol/commands.pb.h"
42
43 namespace mozc {
44 namespace dictionary {
45
DictionaryImpl(const DictionaryInterface * system_dictionary,const DictionaryInterface * value_dictionary,DictionaryInterface * user_dictionary,const SuppressionDictionary * suppression_dictionary,const POSMatcher * pos_matcher)46 DictionaryImpl::DictionaryImpl(
47 const DictionaryInterface *system_dictionary,
48 const DictionaryInterface *value_dictionary,
49 DictionaryInterface *user_dictionary,
50 const SuppressionDictionary *suppression_dictionary,
51 const POSMatcher *pos_matcher)
52 : pos_matcher_(pos_matcher),
53 system_dictionary_(system_dictionary),
54 value_dictionary_(value_dictionary),
55 user_dictionary_(user_dictionary),
56 suppression_dictionary_(suppression_dictionary) {
57 CHECK(pos_matcher_);
58 CHECK(system_dictionary_.get());
59 CHECK(value_dictionary_.get());
60 CHECK(user_dictionary_);
61 CHECK(suppression_dictionary_);
62 dics_.push_back(system_dictionary_.get());
63 dics_.push_back(value_dictionary_.get());
64 dics_.push_back(user_dictionary_);
65 }
66
~DictionaryImpl()67 DictionaryImpl::~DictionaryImpl() {
68 dics_.clear();
69 }
70
HasKey(StringPiece key) const71 bool DictionaryImpl::HasKey(StringPiece key) const {
72 for (size_t i = 0; i < dics_.size(); ++i) {
73 if (dics_[i]->HasKey(key)) {
74 return true;
75 }
76 }
77 return false;
78 }
79
HasValue(StringPiece value) const80 bool DictionaryImpl::HasValue(StringPiece value) const {
81 for (size_t i = 0; i < dics_.size(); ++i) {
82 if (dics_[i]->HasValue(value)) {
83 return true;
84 }
85 }
86 return false;
87 }
88
89 namespace {
90
91 class CallbackWithFilter : public DictionaryInterface::Callback {
92 public:
CallbackWithFilter(const bool use_spelling_correction,const bool use_zip_code_conversion,const bool use_t13n_conversion,const POSMatcher * pos_matcher,const SuppressionDictionary * suppression_dictionary,DictionaryInterface::Callback * callback)93 CallbackWithFilter(const bool use_spelling_correction,
94 const bool use_zip_code_conversion,
95 const bool use_t13n_conversion,
96 const POSMatcher *pos_matcher,
97 const SuppressionDictionary *suppression_dictionary,
98 DictionaryInterface::Callback *callback)
99 : use_spelling_correction_(use_spelling_correction),
100 use_zip_code_conversion_(use_zip_code_conversion),
101 use_t13n_conversion_(use_t13n_conversion),
102 pos_matcher_(pos_matcher),
103 suppression_dictionary_(suppression_dictionary),
104 callback_(callback) {}
105
OnKey(StringPiece key)106 virtual ResultType OnKey(StringPiece key) {
107 return callback_->OnKey(key);
108 }
109
OnActualKey(StringPiece key,StringPiece actual_key,bool is_expanded)110 virtual ResultType OnActualKey(StringPiece key, StringPiece actual_key,
111 bool is_expanded) {
112 return callback_->OnActualKey(key, actual_key, is_expanded);
113 }
114
OnToken(StringPiece key,StringPiece actual_key,const Token & token)115 virtual ResultType OnToken(StringPiece key, StringPiece actual_key,
116 const Token &token) {
117 if (!(token.attributes & Token::USER_DICTIONARY)) {
118 if (!use_spelling_correction_ &&
119 (token.attributes & Token::SPELLING_CORRECTION)) {
120 return TRAVERSE_CONTINUE;
121 }
122 if (!use_zip_code_conversion_ && pos_matcher_->IsZipcode(token.lid)) {
123 return TRAVERSE_CONTINUE;
124 }
125 if (!use_t13n_conversion_ &&
126 Util::IsEnglishTransliteration(token.value)) {
127 return TRAVERSE_CONTINUE;
128 }
129 }
130 if (suppression_dictionary_->SuppressEntry(token.key, token.value)) {
131 return TRAVERSE_CONTINUE;
132 }
133 return callback_->OnToken(key, actual_key, token);
134 }
135
136 private:
137 const bool use_spelling_correction_;
138 const bool use_zip_code_conversion_;
139 const bool use_t13n_conversion_;
140 const POSMatcher *pos_matcher_;
141 const SuppressionDictionary *suppression_dictionary_;
142 DictionaryInterface::Callback *callback_;
143 };
144
145 } // namespace
146
LookupPredictive(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const147 void DictionaryImpl::LookupPredictive(
148 StringPiece key,
149 const ConversionRequest &conversion_request,
150 Callback *callback) const {
151 CallbackWithFilter callback_with_filter(
152 conversion_request.config().use_spelling_correction(),
153 conversion_request.config().use_zip_code_conversion(),
154 conversion_request.config().use_t13n_conversion(),
155 pos_matcher_,
156 suppression_dictionary_,
157 callback);
158 for (size_t i = 0; i < dics_.size(); ++i) {
159 dics_[i]->LookupPredictive(
160 key,
161 conversion_request,
162 &callback_with_filter);
163 }
164 }
165
LookupPrefix(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const166 void DictionaryImpl::LookupPrefix(
167 StringPiece key,
168 const ConversionRequest &conversion_request,
169 Callback *callback) const {
170 CallbackWithFilter callback_with_filter(
171 conversion_request.config().use_spelling_correction(),
172 conversion_request.config().use_zip_code_conversion(),
173 conversion_request.config().use_t13n_conversion(),
174 pos_matcher_,
175 suppression_dictionary_,
176 callback);
177 for (size_t i = 0; i < dics_.size(); ++i) {
178 dics_[i]->LookupPrefix(
179 key,
180 conversion_request,
181 &callback_with_filter);
182 }
183 }
184
LookupExact(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const185 void DictionaryImpl::LookupExact(
186 StringPiece key,
187 const ConversionRequest &conversion_request,
188 Callback *callback) const {
189 CallbackWithFilter callback_with_filter(
190 conversion_request.config().use_spelling_correction(),
191 conversion_request.config().use_zip_code_conversion(),
192 conversion_request.config().use_t13n_conversion(),
193 pos_matcher_,
194 suppression_dictionary_,
195 callback);
196 for (size_t i = 0; i < dics_.size(); ++i) {
197 dics_[i]->LookupExact(key, conversion_request, &callback_with_filter);
198 }
199 }
200
LookupReverse(StringPiece str,const ConversionRequest & conversion_request,Callback * callback) const201 void DictionaryImpl::LookupReverse(
202 StringPiece str,
203 const ConversionRequest &conversion_request,
204 Callback *callback) const {
205 CallbackWithFilter callback_with_filter(
206 conversion_request.config().use_spelling_correction(),
207 conversion_request.config().use_zip_code_conversion(),
208 conversion_request.config().use_t13n_conversion(),
209 pos_matcher_,
210 suppression_dictionary_,
211 callback);
212 for (size_t i = 0; i < dics_.size(); ++i) {
213 dics_[i]->LookupReverse(str, conversion_request, &callback_with_filter);
214 }
215 }
216
LookupComment(StringPiece key,StringPiece value,const ConversionRequest & conversion_request,string * comment) const217 bool DictionaryImpl::LookupComment(StringPiece key, StringPiece value,
218 const ConversionRequest &conversion_request,
219 string *comment) const {
220 // TODO(komatsu): UserDictionary should be treated as the highest priority.
221 // In the current implementation, UserDictionary is the last node of dics_,
222 // but the only dictionary which may return true.
223 for (size_t i = 0; i < dics_.size(); ++i) {
224 if (dics_[i]->LookupComment(key, value, conversion_request, comment)) {
225 return true;
226 }
227 }
228 return false;
229 }
230
Reload()231 bool DictionaryImpl::Reload() {
232 return user_dictionary_->Reload();
233 }
234
PopulateReverseLookupCache(StringPiece str) const235 void DictionaryImpl::PopulateReverseLookupCache(StringPiece str) const {
236 for (size_t i = 0; i < dics_.size(); ++i) {
237 dics_[i]->PopulateReverseLookupCache(str);
238 }
239 }
240
ClearReverseLookupCache() const241 void DictionaryImpl::ClearReverseLookupCache() const {
242 for (size_t i = 0; i < dics_.size(); ++i) {
243 dics_[i]->ClearReverseLookupCache();
244 }
245 }
246
247 } // namespace dictionary
248 } // namespace mozc
249