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