1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dialer.smartdial.map;
18 
19 import android.support.v4.util.SimpleArrayMap;
20 import com.android.dialer.dialpadview.DialpadCharMappings;
21 import com.google.common.base.Optional;
22 
23 /** A {@link SmartDialMap} for the Latin alphabet, which is for T9 dialpad searching. */
24 @SuppressWarnings("Guava")
25 final class LatinSmartDialMap extends SmartDialMap {
26 
27   private static LatinSmartDialMap instance;
28 
getInstance()29   static LatinSmartDialMap getInstance() {
30     if (instance == null) {
31       instance = new LatinSmartDialMap();
32     }
33 
34     return instance;
35   }
36 
LatinSmartDialMap()37   private LatinSmartDialMap() {}
38 
39   /*
40    * The switch statement in this function was generated using the python code:
41    * from unidecode import unidecode
42    * for i in range(192, 564):
43    *     char = unichr(i)
44    *     decoded = unidecode(char)
45    *     # Unicode characters that decompose into multiple characters i.e.
46    *     #  into ss are not supported for now
47    *     if (len(decoded) == 1 and decoded.isalpha()):
48    *         print "case '" + char + "': return Optional.of('" + unidecode(char) +  "');"
49    *
50    * This gives us a way to map characters containing accents/diacritics to their
51    * alphabetic equivalents. The unidecode library can be found at:
52    * http://pypi.python.org/pypi/Unidecode/0.04.1
53    *
54    * Also remaps all upper case latin characters to their lower case equivalents.
55    */
56   @Override
normalizeCharacter(char ch)57   Optional<Character> normalizeCharacter(char ch) {
58     if (isValidDialpadAlphabeticChar(ch)) {
59       return Optional.of(ch);
60     }
61 
62     switch (ch) {
63       case 'À':
64         return Optional.of('a');
65       case 'Á':
66         return Optional.of('a');
67       case 'Â':
68         return Optional.of('a');
69       case 'Ã':
70         return Optional.of('a');
71       case 'Ä':
72         return Optional.of('a');
73       case 'Å':
74         return Optional.of('a');
75       case 'Ç':
76         return Optional.of('c');
77       case 'È':
78         return Optional.of('e');
79       case 'É':
80         return Optional.of('e');
81       case 'Ê':
82         return Optional.of('e');
83       case 'Ë':
84         return Optional.of('e');
85       case 'Ì':
86         return Optional.of('i');
87       case 'Í':
88         return Optional.of('i');
89       case 'Î':
90         return Optional.of('i');
91       case 'Ï':
92         return Optional.of('i');
93       case 'Ð':
94         return Optional.of('d');
95       case 'Ñ':
96         return Optional.of('n');
97       case 'Ò':
98         return Optional.of('o');
99       case 'Ó':
100         return Optional.of('o');
101       case 'Ô':
102         return Optional.of('o');
103       case 'Õ':
104         return Optional.of('o');
105       case 'Ö':
106         return Optional.of('o');
107       case '×':
108         return Optional.of('x');
109       case 'Ø':
110         return Optional.of('o');
111       case 'Ù':
112         return Optional.of('u');
113       case 'Ú':
114         return Optional.of('u');
115       case 'Û':
116         return Optional.of('u');
117       case 'Ü':
118         return Optional.of('u');
119       case 'Ý':
120         return Optional.of('u');
121       case 'à':
122         return Optional.of('a');
123       case 'á':
124         return Optional.of('a');
125       case 'â':
126         return Optional.of('a');
127       case 'ã':
128         return Optional.of('a');
129       case 'ä':
130         return Optional.of('a');
131       case 'å':
132         return Optional.of('a');
133       case 'ç':
134         return Optional.of('c');
135       case 'è':
136         return Optional.of('e');
137       case 'é':
138         return Optional.of('e');
139       case 'ê':
140         return Optional.of('e');
141       case 'ë':
142         return Optional.of('e');
143       case 'ì':
144         return Optional.of('i');
145       case 'í':
146         return Optional.of('i');
147       case 'î':
148         return Optional.of('i');
149       case 'ï':
150         return Optional.of('i');
151       case 'ð':
152         return Optional.of('d');
153       case 'ñ':
154         return Optional.of('n');
155       case 'ò':
156         return Optional.of('o');
157       case 'ó':
158         return Optional.of('o');
159       case 'ô':
160         return Optional.of('o');
161       case 'õ':
162         return Optional.of('o');
163       case 'ö':
164         return Optional.of('o');
165       case 'ø':
166         return Optional.of('o');
167       case 'ù':
168         return Optional.of('u');
169       case 'ú':
170         return Optional.of('u');
171       case 'û':
172         return Optional.of('u');
173       case 'ü':
174         return Optional.of('u');
175       case 'ý':
176         return Optional.of('y');
177       case 'ÿ':
178         return Optional.of('y');
179       case 'Ā':
180         return Optional.of('a');
181       case 'ā':
182         return Optional.of('a');
183       case 'Ă':
184         return Optional.of('a');
185       case 'ă':
186         return Optional.of('a');
187       case 'Ą':
188         return Optional.of('a');
189       case 'ą':
190         return Optional.of('a');
191       case 'Ć':
192         return Optional.of('c');
193       case 'ć':
194         return Optional.of('c');
195       case 'Ĉ':
196         return Optional.of('c');
197       case 'ĉ':
198         return Optional.of('c');
199       case 'Ċ':
200         return Optional.of('c');
201       case 'ċ':
202         return Optional.of('c');
203       case 'Č':
204         return Optional.of('c');
205       case 'č':
206         return Optional.of('c');
207       case 'Ď':
208         return Optional.of('d');
209       case 'ď':
210         return Optional.of('d');
211       case 'Đ':
212         return Optional.of('d');
213       case 'đ':
214         return Optional.of('d');
215       case 'Ē':
216         return Optional.of('e');
217       case 'ē':
218         return Optional.of('e');
219       case 'Ĕ':
220         return Optional.of('e');
221       case 'ĕ':
222         return Optional.of('e');
223       case 'Ė':
224         return Optional.of('e');
225       case 'ė':
226         return Optional.of('e');
227       case 'Ę':
228         return Optional.of('e');
229       case 'ę':
230         return Optional.of('e');
231       case 'Ě':
232         return Optional.of('e');
233       case 'ě':
234         return Optional.of('e');
235       case 'Ĝ':
236         return Optional.of('g');
237       case 'ĝ':
238         return Optional.of('g');
239       case 'Ğ':
240         return Optional.of('g');
241       case 'ğ':
242         return Optional.of('g');
243       case 'Ġ':
244         return Optional.of('g');
245       case 'ġ':
246         return Optional.of('g');
247       case 'Ģ':
248         return Optional.of('g');
249       case 'ģ':
250         return Optional.of('g');
251       case 'Ĥ':
252         return Optional.of('h');
253       case 'ĥ':
254         return Optional.of('h');
255       case 'Ħ':
256         return Optional.of('h');
257       case 'ħ':
258         return Optional.of('h');
259       case 'Ĩ':
260         return Optional.of('i');
261       case 'ĩ':
262         return Optional.of('i');
263       case 'Ī':
264         return Optional.of('i');
265       case 'ī':
266         return Optional.of('i');
267       case 'Ĭ':
268         return Optional.of('i');
269       case 'ĭ':
270         return Optional.of('i');
271       case 'Į':
272         return Optional.of('i');
273       case 'į':
274         return Optional.of('i');
275       case 'İ':
276         return Optional.of('i');
277       case 'ı':
278         return Optional.of('i');
279       case 'Ĵ':
280         return Optional.of('j');
281       case 'ĵ':
282         return Optional.of('j');
283       case 'Ķ':
284         return Optional.of('k');
285       case 'ķ':
286         return Optional.of('k');
287       case 'ĸ':
288         return Optional.of('k');
289       case 'Ĺ':
290         return Optional.of('l');
291       case 'ĺ':
292         return Optional.of('l');
293       case 'Ļ':
294         return Optional.of('l');
295       case 'ļ':
296         return Optional.of('l');
297       case 'Ľ':
298         return Optional.of('l');
299       case 'ľ':
300         return Optional.of('l');
301       case 'Ŀ':
302         return Optional.of('l');
303       case 'ŀ':
304         return Optional.of('l');
305       case 'Ł':
306         return Optional.of('l');
307       case 'ł':
308         return Optional.of('l');
309       case 'Ń':
310         return Optional.of('n');
311       case 'ń':
312         return Optional.of('n');
313       case 'Ņ':
314         return Optional.of('n');
315       case 'ņ':
316         return Optional.of('n');
317       case 'Ň':
318         return Optional.of('n');
319       case 'ň':
320         return Optional.of('n');
321       case 'Ō':
322         return Optional.of('o');
323       case 'ō':
324         return Optional.of('o');
325       case 'Ŏ':
326         return Optional.of('o');
327       case 'ŏ':
328         return Optional.of('o');
329       case 'Ő':
330         return Optional.of('o');
331       case 'ő':
332         return Optional.of('o');
333       case 'Ŕ':
334         return Optional.of('r');
335       case 'ŕ':
336         return Optional.of('r');
337       case 'Ŗ':
338         return Optional.of('r');
339       case 'ŗ':
340         return Optional.of('r');
341       case 'Ř':
342         return Optional.of('r');
343       case 'ř':
344         return Optional.of('r');
345       case 'Ś':
346         return Optional.of('s');
347       case 'ś':
348         return Optional.of('s');
349       case 'Ŝ':
350         return Optional.of('s');
351       case 'ŝ':
352         return Optional.of('s');
353       case 'Ş':
354         return Optional.of('s');
355       case 'ş':
356         return Optional.of('s');
357       case 'Š':
358         return Optional.of('s');
359       case 'š':
360         return Optional.of('s');
361       case 'Ţ':
362         return Optional.of('t');
363       case 'ţ':
364         return Optional.of('t');
365       case 'Ť':
366         return Optional.of('t');
367       case 'ť':
368         return Optional.of('t');
369       case 'Ŧ':
370         return Optional.of('t');
371       case 'ŧ':
372         return Optional.of('t');
373       case 'Ũ':
374         return Optional.of('u');
375       case 'ũ':
376         return Optional.of('u');
377       case 'Ū':
378         return Optional.of('u');
379       case 'ū':
380         return Optional.of('u');
381       case 'Ŭ':
382         return Optional.of('u');
383       case 'ŭ':
384         return Optional.of('u');
385       case 'Ů':
386         return Optional.of('u');
387       case 'ů':
388         return Optional.of('u');
389       case 'Ű':
390         return Optional.of('u');
391       case 'ű':
392         return Optional.of('u');
393       case 'Ų':
394         return Optional.of('u');
395       case 'ų':
396         return Optional.of('u');
397       case 'Ŵ':
398         return Optional.of('w');
399       case 'ŵ':
400         return Optional.of('w');
401       case 'Ŷ':
402         return Optional.of('y');
403       case 'ŷ':
404         return Optional.of('y');
405       case 'Ÿ':
406         return Optional.of('y');
407       case 'Ź':
408         return Optional.of('z');
409       case 'ź':
410         return Optional.of('z');
411       case 'Ż':
412         return Optional.of('z');
413       case 'ż':
414         return Optional.of('z');
415       case 'Ž':
416         return Optional.of('z');
417       case 'ž':
418         return Optional.of('z');
419       case 'ſ':
420         return Optional.of('s');
421       case 'ƀ':
422         return Optional.of('b');
423       case 'Ɓ':
424         return Optional.of('b');
425       case 'Ƃ':
426         return Optional.of('b');
427       case 'ƃ':
428         return Optional.of('b');
429       case 'Ɔ':
430         return Optional.of('o');
431       case 'Ƈ':
432         return Optional.of('c');
433       case 'ƈ':
434         return Optional.of('c');
435       case 'Ɖ':
436         return Optional.of('d');
437       case 'Ɗ':
438         return Optional.of('d');
439       case 'Ƌ':
440         return Optional.of('d');
441       case 'ƌ':
442         return Optional.of('d');
443       case 'ƍ':
444         return Optional.of('d');
445       case 'Ɛ':
446         return Optional.of('e');
447       case 'Ƒ':
448         return Optional.of('f');
449       case 'ƒ':
450         return Optional.of('f');
451       case 'Ɠ':
452         return Optional.of('g');
453       case 'Ɣ':
454         return Optional.of('g');
455       case 'Ɩ':
456         return Optional.of('i');
457       case 'Ɨ':
458         return Optional.of('i');
459       case 'Ƙ':
460         return Optional.of('k');
461       case 'ƙ':
462         return Optional.of('k');
463       case 'ƚ':
464         return Optional.of('l');
465       case 'ƛ':
466         return Optional.of('l');
467       case 'Ɯ':
468         return Optional.of('w');
469       case 'Ɲ':
470         return Optional.of('n');
471       case 'ƞ':
472         return Optional.of('n');
473       case 'Ɵ':
474         return Optional.of('o');
475       case 'Ơ':
476         return Optional.of('o');
477       case 'ơ':
478         return Optional.of('o');
479       case 'Ƥ':
480         return Optional.of('p');
481       case 'ƥ':
482         return Optional.of('p');
483       case 'ƫ':
484         return Optional.of('t');
485       case 'Ƭ':
486         return Optional.of('t');
487       case 'ƭ':
488         return Optional.of('t');
489       case 'Ʈ':
490         return Optional.of('t');
491       case 'Ư':
492         return Optional.of('u');
493       case 'ư':
494         return Optional.of('u');
495       case 'Ʊ':
496         return Optional.of('y');
497       case 'Ʋ':
498         return Optional.of('v');
499       case 'Ƴ':
500         return Optional.of('y');
501       case 'ƴ':
502         return Optional.of('y');
503       case 'Ƶ':
504         return Optional.of('z');
505       case 'ƶ':
506         return Optional.of('z');
507       case 'ƿ':
508         return Optional.of('w');
509       case 'Ǎ':
510         return Optional.of('a');
511       case 'ǎ':
512         return Optional.of('a');
513       case 'Ǐ':
514         return Optional.of('i');
515       case 'ǐ':
516         return Optional.of('i');
517       case 'Ǒ':
518         return Optional.of('o');
519       case 'ǒ':
520         return Optional.of('o');
521       case 'Ǔ':
522         return Optional.of('u');
523       case 'ǔ':
524         return Optional.of('u');
525       case 'Ǖ':
526         return Optional.of('u');
527       case 'ǖ':
528         return Optional.of('u');
529       case 'Ǘ':
530         return Optional.of('u');
531       case 'ǘ':
532         return Optional.of('u');
533       case 'Ǚ':
534         return Optional.of('u');
535       case 'ǚ':
536         return Optional.of('u');
537       case 'Ǜ':
538         return Optional.of('u');
539       case 'ǜ':
540         return Optional.of('u');
541       case 'Ǟ':
542         return Optional.of('a');
543       case 'ǟ':
544         return Optional.of('a');
545       case 'Ǡ':
546         return Optional.of('a');
547       case 'ǡ':
548         return Optional.of('a');
549       case 'Ǥ':
550         return Optional.of('g');
551       case 'ǥ':
552         return Optional.of('g');
553       case 'Ǧ':
554         return Optional.of('g');
555       case 'ǧ':
556         return Optional.of('g');
557       case 'Ǩ':
558         return Optional.of('k');
559       case 'ǩ':
560         return Optional.of('k');
561       case 'Ǫ':
562         return Optional.of('o');
563       case 'ǫ':
564         return Optional.of('o');
565       case 'Ǭ':
566         return Optional.of('o');
567       case 'ǭ':
568         return Optional.of('o');
569       case 'ǰ':
570         return Optional.of('j');
571       case 'Dz':
572         return Optional.of('d');
573       case 'Ǵ':
574         return Optional.of('g');
575       case 'ǵ':
576         return Optional.of('g');
577       case 'Ƿ':
578         return Optional.of('w');
579       case 'Ǹ':
580         return Optional.of('n');
581       case 'ǹ':
582         return Optional.of('n');
583       case 'Ǻ':
584         return Optional.of('a');
585       case 'ǻ':
586         return Optional.of('a');
587       case 'Ǿ':
588         return Optional.of('o');
589       case 'ǿ':
590         return Optional.of('o');
591       case 'Ȁ':
592         return Optional.of('a');
593       case 'ȁ':
594         return Optional.of('a');
595       case 'Ȃ':
596         return Optional.of('a');
597       case 'ȃ':
598         return Optional.of('a');
599       case 'Ȅ':
600         return Optional.of('e');
601       case 'ȅ':
602         return Optional.of('e');
603       case 'Ȇ':
604         return Optional.of('e');
605       case 'ȇ':
606         return Optional.of('e');
607       case 'Ȉ':
608         return Optional.of('i');
609       case 'ȉ':
610         return Optional.of('i');
611       case 'Ȋ':
612         return Optional.of('i');
613       case 'ȋ':
614         return Optional.of('i');
615       case 'Ȍ':
616         return Optional.of('o');
617       case 'ȍ':
618         return Optional.of('o');
619       case 'Ȏ':
620         return Optional.of('o');
621       case 'ȏ':
622         return Optional.of('o');
623       case 'Ȑ':
624         return Optional.of('r');
625       case 'ȑ':
626         return Optional.of('r');
627       case 'Ȓ':
628         return Optional.of('r');
629       case 'ȓ':
630         return Optional.of('r');
631       case 'Ȕ':
632         return Optional.of('u');
633       case 'ȕ':
634         return Optional.of('u');
635       case 'Ȗ':
636         return Optional.of('u');
637       case 'ȗ':
638         return Optional.of('u');
639       case 'Ș':
640         return Optional.of('s');
641       case 'ș':
642         return Optional.of('s');
643       case 'Ț':
644         return Optional.of('t');
645       case 'ț':
646         return Optional.of('t');
647       case 'Ȝ':
648         return Optional.of('y');
649       case 'ȝ':
650         return Optional.of('y');
651       case 'Ȟ':
652         return Optional.of('h');
653       case 'ȟ':
654         return Optional.of('h');
655       case 'Ȥ':
656         return Optional.of('z');
657       case 'ȥ':
658         return Optional.of('z');
659       case 'Ȧ':
660         return Optional.of('a');
661       case 'ȧ':
662         return Optional.of('a');
663       case 'Ȩ':
664         return Optional.of('e');
665       case 'ȩ':
666         return Optional.of('e');
667       case 'Ȫ':
668         return Optional.of('o');
669       case 'ȫ':
670         return Optional.of('o');
671       case 'Ȭ':
672         return Optional.of('o');
673       case 'ȭ':
674         return Optional.of('o');
675       case 'Ȯ':
676         return Optional.of('o');
677       case 'ȯ':
678         return Optional.of('o');
679       case 'Ȱ':
680         return Optional.of('o');
681       case 'ȱ':
682         return Optional.of('o');
683       case 'Ȳ':
684         return Optional.of('y');
685       case 'ȳ':
686         return Optional.of('y');
687       case 'A':
688         return Optional.of('a');
689       case 'B':
690         return Optional.of('b');
691       case 'C':
692         return Optional.of('c');
693       case 'D':
694         return Optional.of('d');
695       case 'E':
696         return Optional.of('e');
697       case 'F':
698         return Optional.of('f');
699       case 'G':
700         return Optional.of('g');
701       case 'H':
702         return Optional.of('h');
703       case 'I':
704         return Optional.of('i');
705       case 'J':
706         return Optional.of('j');
707       case 'K':
708         return Optional.of('k');
709       case 'L':
710         return Optional.of('l');
711       case 'M':
712         return Optional.of('m');
713       case 'N':
714         return Optional.of('n');
715       case 'O':
716         return Optional.of('o');
717       case 'P':
718         return Optional.of('p');
719       case 'Q':
720         return Optional.of('q');
721       case 'R':
722         return Optional.of('r');
723       case 'S':
724         return Optional.of('s');
725       case 'T':
726         return Optional.of('t');
727       case 'U':
728         return Optional.of('u');
729       case 'V':
730         return Optional.of('v');
731       case 'W':
732         return Optional.of('w');
733       case 'X':
734         return Optional.of('x');
735       case 'Y':
736         return Optional.of('y');
737       case 'Z':
738         return Optional.of('z');
739       default:
740         return Optional.absent();
741     }
742   }
743 
744   @Override
getCharToKeyMap()745   SimpleArrayMap<Character, Character> getCharToKeyMap() {
746     return DialpadCharMappings.getDefaultCharToKeyMap();
747   }
748 }
749