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_mock.h"
31 
32 #include <climits>
33 #include <map>
34 #include <memory>
35 #include <string>
36 
37 #include "base/logging.h"
38 #include "base/stl_util.h"
39 #include "base/string_piece.h"
40 #include "base/util.h"
41 #include "dictionary/dictionary_token.h"
42 
43 namespace mozc {
44 namespace dictionary {
45 namespace {
46 
47 const int kDummyPosId = 1;
48 
HasKeyInternal(const std::map<string,std::vector<Token * >> & dic,StringPiece key)49 bool HasKeyInternal(const std::map<string, std::vector<Token *>> &dic,
50                     StringPiece key) {
51   typedef std::vector<Token *> TokenPtrVector;
52   for (std::map<string, std::vector<Token *>>::const_iterator map_it =
53            dic.begin();
54        map_it != dic.end(); ++map_it) {
55     const TokenPtrVector &v = map_it->second;
56     for (TokenPtrVector::const_iterator it = v.begin(); it != v.end(); ++it) {
57       if ((*it)->key == key) {
58         return true;
59       }
60     }
61   }
62   return false;
63 }
64 
HasValueInternal(const std::map<string,std::vector<Token * >> & dic,StringPiece value)65 bool HasValueInternal(const std::map<string, std::vector<Token *>> &dic,
66                       StringPiece value) {
67   typedef std::vector<Token *> TokenPtrVector;
68   for (std::map<string, std::vector<Token *>>::const_iterator map_it =
69            dic.begin();
70        map_it != dic.end(); ++map_it) {
71     const TokenPtrVector &v = map_it->second;
72     for (TokenPtrVector::const_iterator it = v.begin(); it != v.end(); ++it) {
73       if ((*it)->value == value) {
74         return true;
75       }
76     }
77   }
78   return false;
79 }
80 
CreateToken(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)81 Token *CreateToken(const string &str, const string &key, const string &value,
82                    Token::AttributesBitfield attributes) {
83   std::unique_ptr<Token> token(new Token());
84   token->key = key;
85   token->value = value;
86   // TODO(noriyukit): Currently, we cannot set cost and POS IDs.
87   token->cost = 0;
88   token->lid = token->rid = kDummyPosId;
89   token->attributes = attributes;
90   return token.release();
91 }
92 
DeletePtrs(std::map<string,std::vector<Token * >> * m)93 void DeletePtrs(std::map<string, std::vector<Token *>> *m) {
94   for (std::map<string, std::vector<Token *>>::iterator iter = m->begin();
95        iter != m->end(); ++iter) {
96     STLDeleteElements(&iter->second);
97   }
98 }
99 
100 }  // namespace
101 
DictionaryMock()102 DictionaryMock::DictionaryMock() {
103   LOG(INFO) << "DictionaryMock is created";
104 }
105 
~DictionaryMock()106 DictionaryMock::~DictionaryMock() {
107   DeletePtrs(&prefix_dictionary_);
108   DeletePtrs(&exact_dictionary_);
109   DeletePtrs(&reverse_dictionary_);
110   DeletePtrs(&predictive_dictionary_);
111 }
112 
HasKey(StringPiece key) const113 bool DictionaryMock::HasKey(StringPiece key) const {
114   return HasKeyInternal(predictive_dictionary_, key) ||
115          HasKeyInternal(prefix_dictionary_, key) ||
116          HasKeyInternal(reverse_dictionary_, key) ||
117          HasKeyInternal(exact_dictionary_, key);
118 }
119 
HasValue(StringPiece value) const120 bool DictionaryMock::HasValue(StringPiece value) const {
121   return HasValueInternal(predictive_dictionary_, value) ||
122          HasValueInternal(prefix_dictionary_, value) ||
123          HasValueInternal(reverse_dictionary_, value) ||
124          HasValueInternal(exact_dictionary_, value);
125 }
126 
LookupPredictive(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const127 void DictionaryMock::LookupPredictive(
128     StringPiece key,
129     const ConversionRequest &conversion_request,
130     Callback *callback) const {
131   std::map<string, std::vector<Token *>>::const_iterator vector_iter =
132       predictive_dictionary_.find(key.as_string());
133   if (vector_iter == predictive_dictionary_.end()) {
134     return;
135   }
136   if (callback->OnKey(key) != Callback::TRAVERSE_CONTINUE ||
137       callback->OnActualKey(key, key, false) != Callback::TRAVERSE_CONTINUE) {
138     return;
139   }
140   for (std::vector<Token *>::const_iterator iter = vector_iter->second.begin();
141        iter != vector_iter->second.end(); ++iter) {
142     if (callback->OnToken(key, key, **iter) != Callback::TRAVERSE_CONTINUE) {
143       return;
144     }
145   }
146 }
147 
LookupPrefix(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const148 void DictionaryMock::LookupPrefix(
149     StringPiece key,
150     const ConversionRequest &conversion_request,
151     Callback *callback) const {
152   CHECK(!key.empty());
153 
154   string prefix;
155   for (size_t len = 1; len <= key.size(); ++len) {
156     prefix.assign(key.data(), len);
157     std::map<string, std::vector<Token *>>::const_iterator iter =
158         prefix_dictionary_.find(prefix);
159     if (iter == prefix_dictionary_.end()) {
160       continue;
161     }
162     switch (callback->OnKey(prefix)) {
163       case Callback::TRAVERSE_DONE:
164       case Callback::TRAVERSE_CULL:
165         return;
166       case Callback::TRAVERSE_NEXT_KEY:
167         continue;
168       default:
169         break;
170     }
171     switch (callback->OnActualKey(prefix, prefix, false)) {
172       case Callback::TRAVERSE_DONE:
173       case Callback::TRAVERSE_CULL:
174         return;
175       case Callback::TRAVERSE_NEXT_KEY:
176         continue;
177       default:
178         break;
179     }
180     for (std::vector<Token *>::const_iterator token_iter = iter->second.begin();
181          token_iter != iter->second.end(); ++token_iter) {
182       Callback::ResultType ret =
183           callback->OnToken(prefix, prefix, **token_iter);
184       if (ret == Callback::TRAVERSE_DONE || ret == Callback::TRAVERSE_CULL) {
185         return;
186       }
187       if (ret == Callback::TRAVERSE_NEXT_KEY) {
188         break;
189       }
190     }
191   }
192 }
193 
LookupExact(StringPiece key,const ConversionRequest & conversion_request,Callback * callback) const194 void DictionaryMock::LookupExact(
195     StringPiece key,
196     const ConversionRequest &conversion_request,
197     Callback *callback) const {
198   std::map<string, std::vector<Token *>>::const_iterator iter =
199       exact_dictionary_.find(key.as_string());
200   if (iter == exact_dictionary_.end()) {
201     return;
202   }
203   if (callback->OnKey(key) != Callback::TRAVERSE_CONTINUE) {
204     return;
205   }
206   for (std::vector<Token *>::const_iterator token_iter = iter->second.begin();
207        token_iter != iter->second.end(); ++token_iter) {
208     if (callback->OnToken(key, key, **token_iter) !=
209         Callback::TRAVERSE_CONTINUE) {
210       return;
211     }
212   }
213 }
214 
LookupReverse(StringPiece str,const ConversionRequest & conversion_request,Callback * callback) const215 void DictionaryMock::LookupReverse(
216     StringPiece str,
217     const ConversionRequest &conversion_request,
218     Callback *callback) const {
219   CHECK(!str.empty());
220 
221   for (int i = 1; i <= str.size(); ++i) {
222     StringPiece prefix = str.substr(0, i);
223 
224     std::map<string, std::vector<Token *>>::const_iterator iter =
225         reverse_dictionary_.find(prefix.as_string());
226     if (iter == reverse_dictionary_.end()) {
227       continue;
228     }
229 
230     if (callback->OnKey(prefix) != Callback::TRAVERSE_CONTINUE) {
231       return;
232     }
233     for (std::vector<Token *>::const_iterator token_iter = iter->second.begin();
234          token_iter != iter->second.end(); ++token_iter) {
235       if (callback->OnToken(prefix, prefix, **token_iter) !=
236           Callback::TRAVERSE_CONTINUE) {
237         return;
238       }
239     }
240   }
241 }
242 
AddLookupPredictive(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)243 void DictionaryMock::AddLookupPredictive(const string &str,
244                                          const string &key, const string &value,
245                                          Token::AttributesBitfield attributes) {
246   predictive_dictionary_[str].push_back(
247       CreateToken(str, key, value, attributes));
248 }
249 
AddLookupPrefix(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)250 void DictionaryMock::AddLookupPrefix(const string &str,
251                                      const string &key, const string &value,
252                                      Token::AttributesBitfield attributes) {
253   prefix_dictionary_[str].push_back(
254       CreateToken(str, key, value, attributes));
255 }
256 
AddLookupReverse(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)257 void DictionaryMock::AddLookupReverse(const string &str,
258                                       const string &key, const string &value,
259                                       Token::AttributesBitfield attributes) {
260   reverse_dictionary_[str].push_back(
261       CreateToken(str, key, value, attributes));
262 }
263 
AddLookupExact(const string & str,const string & key,const string & value,Token::AttributesBitfield attributes)264 void DictionaryMock::AddLookupExact(const string &str,
265                                     const string &key, const string &value,
266                                     Token::AttributesBitfield attributes) {
267   exact_dictionary_[str].push_back(
268       CreateToken(str, key, value, attributes));
269 }
270 
271 }  // namespace dictionary
272 }  // namespace mozc
273