1 /*
2  *******************************************************************************
3  * Copyright (C) 2003-2014, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 
8 package com.ibm.icu.dev.test.collator;
9 
10 import java.util.Arrays;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.Locale;
16 import java.util.Map;
17 import java.util.MissingResourceException;
18 import java.util.Set;
19 
20 import com.ibm.icu.dev.test.TestFmwk;
21 import com.ibm.icu.text.Collator;
22 import com.ibm.icu.text.Collator.CollatorFactory;
23 import com.ibm.icu.util.ULocale;
24 
25 public class CollationServiceTest extends TestFmwk {
main(String[] args)26     public static void main(String[] args) {
27         new CollationServiceTest().run(args);
28     }
29 
TestRegister()30     public void TestRegister() {
31         // register a singleton
32         Collator frcol = Collator.getInstance(ULocale.FRANCE);
33         Collator uscol = Collator.getInstance(ULocale.US);
34 
35         { // try override en_US collator
36             Object key = Collator.registerInstance(frcol, ULocale.US);
37             Collator ncol = Collator.getInstance(ULocale.US);
38             if (!frcol.equals(ncol)) {
39                 errln("register of french collator for en_US failed");
40             }
41 
42             // coverage
43             Collator test = Collator.getInstance(ULocale.GERMANY); // CollatorFactory.handleCreate
44             if (!test.getLocale(ULocale.VALID_LOCALE).equals(ULocale.GERMAN)) {
45                 errln("Collation from Germany is really " + test.getLocale(ULocale.VALID_LOCALE));
46             }
47 
48             if (!Collator.unregister(key)) {
49                 errln("failed to unregister french collator");
50             }
51             ncol = Collator.getInstance(ULocale.US);
52             if (!uscol.equals(ncol)) {
53                 errln("collator after unregister does not match original");
54             }
55         }
56 
57         ULocale fu_FU = new ULocale("fu_FU_FOO");
58 
59         { // try create collator for new locale
60             Collator fucol = Collator.getInstance(fu_FU);
61             Object key = Collator.registerInstance(frcol, fu_FU);
62             Collator ncol = Collator.getInstance(fu_FU);
63             if (!frcol.equals(ncol)) {
64                 errln("register of fr collator for fu_FU failed");
65             }
66 
67             ULocale[] locales = Collator.getAvailableULocales();
68             boolean found = false;
69             for (int i = 0; i < locales.length; ++i) {
70                 if (locales[i].equals(fu_FU)) {
71                     found = true;
72                     break;
73                 }
74             }
75             if (!found) {
76                 errln("new locale fu_FU not reported as supported locale");
77             }
78             try{
79                 String name = Collator.getDisplayName(fu_FU);
80                 if (!"fu (FU, FOO)".equals(name)
81                         && !"fu_FU_FOO".equals(name) /* no LocaleDisplayNamesImpl */) {
82                     errln("found " + name + " for fu_FU");
83                 }
84             }catch(MissingResourceException ex){
85                 warnln("Could not load locale data.");
86             }
87             try{
88                 String name = Collator.getDisplayName(fu_FU, fu_FU);
89                 if (!"fu (FU, FOO)".equals(name)
90                         && !"fu_FU_FOO".equals(name) /* no LocaleDisplayNamesImpl */) {
91                     errln("found " + name + " for fu_FU");
92                 }
93             }catch(MissingResourceException ex){
94                 warnln("Could not load locale data.");
95             }
96 
97             if (!Collator.unregister(key)) {
98                 errln("failed to unregister french collator");
99             }
100             ncol = Collator.getInstance(fu_FU);
101             if (!fucol.equals(ncol)) {
102                 errln("collator after unregister does not match original fu_FU");
103             }
104         }
105 
106         {
107             // coverage after return to default
108             ULocale[] locales = Collator.getAvailableULocales();
109 
110             for (int i = 0; i < locales.length; ++i) {
111                 if (locales[i].equals(fu_FU)) {
112                     errln("new locale fu_FU not reported as supported locale");
113                     break;
114                 }
115             }
116 
117             Collator ncol = Collator.getInstance(ULocale.US);
118             if (!ncol.getLocale(ULocale.VALID_LOCALE).equals(ULocale.US)) {
119                 errln("Collation from US is really " + ncol.getLocale(ULocale.VALID_LOCALE));
120             }
121         }
122     }
123 
TestRegisterFactory()124     public void TestRegisterFactory() {
125 
126         class CollatorInfo {
127             ULocale locale;
128             Collator collator;
129             Map displayNames; // locale -> string
130 
131             CollatorInfo(ULocale locale, Collator collator, Map displayNames) {
132                 this.locale = locale;
133                 this.collator = collator;
134                 this.displayNames = displayNames;
135             }
136 
137             String getDisplayName(ULocale displayLocale) {
138                 String name = null;
139                 if (displayNames != null) {
140                     name = (String)displayNames.get(displayLocale);
141                 }
142                 if (name == null) {
143                     name = locale.getDisplayName(displayLocale);
144                 }
145                 return name;
146             }
147         }
148 
149         class TestFactory extends CollatorFactory {
150             private Map map;
151             private Set ids;
152 
153             TestFactory(CollatorInfo[] info) {
154                 map = new HashMap();
155                 for (int i = 0; i < info.length; ++i) {
156                     CollatorInfo ci = info[i];
157                     map.put(ci.locale, ci);
158                 }
159             }
160 
161             public Collator createCollator(ULocale loc) {
162                 CollatorInfo ci = (CollatorInfo)map.get(loc);
163                 if (ci != null) {
164                     return ci.collator;
165                 }
166                 return null;
167             }
168 
169             public String getDisplayName(ULocale objectLocale, ULocale displayLocale) {
170                 CollatorInfo ci = (CollatorInfo)map.get(objectLocale);
171                 if (ci != null) {
172                     return ci.getDisplayName(displayLocale);
173                 }
174                 return null;
175             }
176 
177             public Set getSupportedLocaleIDs() {
178                 if (ids == null) {
179                     HashSet set = new HashSet();
180                     Iterator iter = map.keySet().iterator();
181                     while (iter.hasNext()) {
182                         ULocale locale = (ULocale)iter.next();
183                         String id = locale.toString();
184                         set.add(id);
185                     }
186                     ids = Collections.unmodifiableSet(set);
187                 }
188                 return ids;
189             }
190         }
191 
192         class TestFactoryWrapper extends CollatorFactory {
193             CollatorFactory delegate;
194 
195             TestFactoryWrapper(CollatorFactory delegate) {
196                 this.delegate = delegate;
197             }
198 
199             public Collator createCollator(ULocale loc) {
200                 return delegate.createCollator(loc);
201             }
202 
203             // use CollatorFactory getDisplayName(ULocale, ULocale) for coverage
204 
205             public Set getSupportedLocaleIDs() {
206                 return delegate.getSupportedLocaleIDs();
207             }
208         }
209 
210         ULocale fu_FU = new ULocale("fu_FU");
211         ULocale fu_FU_FOO = new ULocale("fu_FU_FOO");
212 
213         Map fuFUNames = new HashMap();
214         fuFUNames.put(fu_FU, "ze leetle bunny Fu-Fu");
215         fuFUNames.put(fu_FU_FOO, "zee leetel bunny Foo-Foo");
216         fuFUNames.put(ULocale.US, "little bunny Foo Foo");
217 
218         Collator frcol = Collator.getInstance(ULocale.FRANCE);
219        /* Collator uscol = */Collator.getInstance(ULocale.US);
220         Collator gecol = Collator.getInstance(ULocale.GERMANY);
221         Collator jpcol = Collator.getInstance(ULocale.JAPAN);
222         Collator fucol = Collator.getInstance(fu_FU);
223 
224         CollatorInfo[] info = {
225             new CollatorInfo(ULocale.US, frcol, null),
226             new CollatorInfo(ULocale.FRANCE, gecol, null),
227             new CollatorInfo(fu_FU, jpcol, fuFUNames),
228         };
229         TestFactory factory = null;
230         try{
231             factory = new TestFactory(info);
232         }catch(MissingResourceException ex){
233             warnln("Could not load locale data.");
234         }
235         // coverage
236         {
237             TestFactoryWrapper wrapper = new TestFactoryWrapper(factory); // in java, gc lets us easily multiply reference!
238             Object key = Collator.registerFactory(wrapper);
239             String name = null;
240             try{
241                 name = Collator.getDisplayName(fu_FU, fu_FU_FOO);
242             }catch(MissingResourceException ex){
243                 warnln("Could not load locale data.");
244             }
245             logln("*** default name: " + name);
246             Collator.unregister(key);
247 
248             ULocale bar_BAR = new ULocale("bar_BAR");
249             Collator col = Collator.getInstance(bar_BAR);
250             ULocale valid = col.getLocale(ULocale.VALID_LOCALE);
251             String validName = valid.getName();
252             if(validName.length() != 0 && !validName.equals("root")) {
253                 errln("Collation from bar_BAR is really \"" + validName + "\" but should be root");
254             }
255         }
256 
257         int n1 = checkAvailable("before registerFactory");
258 
259         {
260             Object key = Collator.registerFactory(factory);
261 
262             int n2 = checkAvailable("after registerFactory");
263 
264             Collator ncol = Collator.getInstance(ULocale.US);
265             if (!frcol.equals(ncol)) {
266                 errln("frcoll for en_US failed");
267             }
268 
269             ncol = Collator.getInstance(fu_FU_FOO);
270             if (!jpcol.equals(ncol)) {
271                 errln("jpcol for fu_FU_FOO failed, got: " + ncol);
272             }
273 
274             ULocale[] locales = Collator.getAvailableULocales();
275             boolean found = false;
276             for (int i = 0; i < locales.length; ++i) {
277                 if (locales[i].equals(fu_FU)) {
278                     found = true;
279                     break;
280                 }
281             }
282             if (!found) {
283                 errln("new locale fu_FU not reported as supported locale");
284             }
285 
286             String name = Collator.getDisplayName(fu_FU);
287             if (!"little bunny Foo Foo".equals(name)) {
288                 errln("found " + name + " for fu_FU");
289             }
290 
291             name = Collator.getDisplayName(fu_FU, fu_FU_FOO);
292             if (!"zee leetel bunny Foo-Foo".equals(name)) {
293                 errln("found " + name + " for fu_FU in fu_FU_FOO");
294             }
295 
296             if (!Collator.unregister(key)) {
297                 errln("failed to unregister factory");
298             }
299 
300             int n3 = checkAvailable("after unregister");
301             assertTrue("register increases count", n2>n1);
302             assertTrue("unregister restores count", n3==n1);
303 
304             ncol = Collator.getInstance(fu_FU);
305             if (!fucol.equals(ncol)) {
306                 errln("collator after unregister does not match original fu_FU");
307             }
308         }
309     }
310 
311     /**
312      * Check the integrity of the results of Collator.getAvailableULocales().
313      * Return the number of items returned.
314      */
checkAvailable(String msg)315     int checkAvailable(String msg) {
316         Locale locs[] = Collator.getAvailableLocales();
317         if (!assertTrue("getAvailableLocales != null", locs!=null)) return -1;
318         checkArray(msg, locs, null);
319         ULocale ulocs[] = Collator.getAvailableULocales();
320         if (!assertTrue("getAvailableULocales != null", ulocs!=null)) return -1;
321         checkArray(msg, ulocs, null);
322         // This is not true because since ULocale objects with script code cannot be
323         // converted to Locale objects
324         //assertTrue("getAvailableLocales().length == getAvailableULocales().length", locs.length == ulocs.length);
325         return locs.length;
326     }
327 
328     private static final String KW[] = {
329         "collation"
330     };
331 
332     private static final String KWVAL[] = {
333         "phonebook",
334         "stroke"
335     };
336 
TestSeparateTrees()337     public void TestSeparateTrees() {
338         String kw[] = Collator.getKeywords();
339         if (!assertTrue("getKeywords != null", kw!=null)) return;
340         checkArray("getKeywords", kw, KW);
341 
342         String kwval[] = Collator.getKeywordValues(KW[0]);
343         if (!assertTrue("getKeywordValues != null", kwval!=null)) return;
344         checkArray("getKeywordValues", kwval, KWVAL);
345 
346         boolean isAvailable[] = new boolean[1];
347         ULocale equiv = Collator.getFunctionalEquivalent(KW[0],
348                                                          new ULocale("de"),
349                                                          isAvailable);
350         if (assertTrue("getFunctionalEquivalent(de)!=null", equiv!=null)) {
351             assertEquals("getFunctionalEquivalent(de)", "root", equiv.toString());
352         }
353         assertTrue("getFunctionalEquivalent(de).isAvailable==true",
354                    isAvailable[0] == true);
355 
356         equiv = Collator.getFunctionalEquivalent(KW[0],
357                                                  new ULocale("de_DE"),
358                                                  isAvailable);
359         if (assertTrue("getFunctionalEquivalent(de_DE)!=null", equiv!=null)) {
360             assertEquals("getFunctionalEquivalent(de_DE)", "root", equiv.toString());
361         }
362         assertTrue("getFunctionalEquivalent(de_DE).isAvailable==false",
363                    isAvailable[0] == false);
364 
365         equiv = Collator.getFunctionalEquivalent(KW[0], new ULocale("zh_Hans"));
366         if (assertTrue("getFunctionalEquivalent(zh_Hans)!=null", equiv!=null)) {
367             assertEquals("getFunctionalEquivalent(zh_Hans)", "zh", equiv.toString());
368         }
369     }
370 
TestGetFunctionalEquivalent()371     public void TestGetFunctionalEquivalent() {
372         String kw[] = Collator.getKeywords();
373         final String DATA[] = {
374                           "sv", "sv", "t",
375                           "sv@collation=direct", "sv", "t",
376                           "sv@collation=traditional", "sv", "t",
377                           "sv@collation=gb2312han", "sv", "t",
378                           "sv@collation=stroke", "sv", "t",
379                           "sv@collation=pinyin", "sv", "t",
380                           "sv@collation=standard", "sv@collation=standard", "t",
381                           "sv@collation=reformed", "sv", "t",
382                           "sv@collation=big5han", "sv", "t",
383                           "sv_FI", "sv", "f",
384                           "sv_FI@collation=direct", "sv", "f",
385                           "sv_FI@collation=traditional", "sv", "f",
386                           "sv_FI@collation=gb2312han", "sv", "f",
387                           "sv_FI@collation=stroke", "sv", "f",
388                           "sv_FI@collation=pinyin", "sv", "f",
389                           "sv_FI@collation=standard", "sv@collation=standard", "f",
390                           "sv_FI@collation=reformed", "sv", "f",
391                           "sv_FI@collation=big5han", "sv", "f",
392                           "nl", "root", "t",
393                           "nl@collation=direct", "root", "t",
394                           "nl_BE", "root", "f",
395                           "nl_BE@collation=direct", "root", "f",
396                           "nl_BE@collation=traditional", "root", "f",
397                           "nl_BE@collation=gb2312han", "root", "f",
398                           "nl_BE@collation=stroke", "root", "f",
399                           "nl_BE@collation=pinyin", "root", "f",
400                           "nl_BE@collation=big5han", "root", "f",
401                           "nl_BE@collation=phonebook", "root", "f",
402                           "en_US_VALLEYGIRL","root","f"
403                         };
404         final int DATA_COUNT=(DATA.length/3);
405 
406         for(int i=0;i<DATA_COUNT;i++) {
407             boolean isAvailable[] = new boolean[1];
408             ULocale input = new ULocale(DATA[(i*3)+0]);
409             ULocale expect = new ULocale(DATA[(i*3)+1]);
410             boolean expectAvailable = DATA[(i*3)+2].equals("t");
411             ULocale actual = Collator.getFunctionalEquivalent(kw[0],input,isAvailable);
412             if(!actual.equals(expect) || (expectAvailable!=isAvailable[0])) {
413                 errln("#" + i + ": Collator.getFunctionalEquivalent(" + input + ")=" + actual + ", avail " + new Boolean(isAvailable[0]) + ", " +
414                         "expected " + expect + " avail " + new Boolean(expectAvailable));
415             } else {
416                 logln("#" + i + ": Collator.getFunctionalEquivalent(" + input + ")=" + actual + ", avail " + new Boolean(isAvailable[0]));
417             }
418         }
419     }
420 
421 //    public void PrintFunctionalEquivalentList() {
422 //        ULocale[] locales = Collator.getAvailableULocales();
423 //        String[] keywords = Collator.getKeywords();
424 //        logln("Collation");
425 //        logln("Possible keyword=values pairs:");
426 //        for (int i = 0; i < Collator.getKeywords().length; ++i) {
427 //                String[] values = Collator.getKeywordValues(keywords[i]);
428 //                for (int j = 0; j < values.length; ++j) {
429 //                        System.out.println(keywords[i] + "=" + values[j]);
430 //                }
431 //        }
432 //        logln("Differing Collators:");
433 //        boolean[] isAvailable = {true};
434 //        for (int k = 0; k < locales.length; ++k) {
435 //                logln(locales[k].getDisplayName(ULocale.ENGLISH) + " [" +locales[k] + "]");
436 //                for (int i = 0; i < Collator.getKeywords().length; ++i) {
437 //                        ULocale base = Collator.getFunctionalEquivalent(keywords[i],locales[k]);
438 //                        String[] values = Collator.getKeywordValues(keywords[i]);
439 //                        for (int j = 0; j < Collator.getKeywordValues(keywords[i]).length;++j) {
440 //                                ULocale other = Collator.getFunctionalEquivalent(keywords[i],
441 //                                        new ULocale(locales[k] + "@" + keywords[i] + "=" + values[j]),
442 //                                        isAvailable);
443 //                                if (isAvailable[0] && !other.equals(base)) {
444 //                                        logln("\t" + keywords[i] + "=" + values[j] + ";\t" + base + ";\t" + other);
445 //                                }
446 //                        }
447 //                }
448 //        }
449 //    }
450 
arrayContains(String[] array, String s)451     private static boolean arrayContains(String[] array, String s) {
452         for (int i = 0; i < array.length; ++i) {
453             if (s.equals(array[i])) {
454                 return true;
455             }
456         }
457         return false;
458     }
459 
TestGetKeywordValues()460     public void TestGetKeywordValues(){
461         final String[][] PREFERRED = {
462             {"und",             "standard", "eor", "search"},
463             {"en_US",           "standard", "eor", "search"},
464             {"en_029",          "standard", "eor", "search"},
465             {"de_DE",           "standard", "phonebook", "search", "eor"},
466             {"de_Latn_DE",      "standard", "phonebook", "search", "eor"},
467             {"zh",              "pinyin", "stroke", "eor", "search", "standard"},
468             {"zh_Hans",         "pinyin", "stroke", "eor", "search", "standard"},
469             {"zh_CN",           "pinyin", "stroke", "eor", "search", "standard"},
470             {"zh_Hant",         "stroke", "pinyin", "eor", "search", "standard"},
471             {"zh_TW",           "stroke", "pinyin", "eor", "search", "standard"},
472             {"zh__PINYIN",      "pinyin", "stroke", "eor", "search", "standard"},
473             {"es_ES",           "standard", "search", "traditional", "eor"},
474             {"es__TRADITIONAL", "traditional", "search", "standard", "eor"},
475             {"und@collation=phonebook",     "standard", "eor", "search"},
476             {"de_DE@collation=big5han",     "standard", "phonebook", "search", "eor"},
477             {"zzz@collation=xxx",           "standard", "eor", "search"},
478         };
479 
480         for (int i = 0; i < PREFERRED.length; i++) {
481             String locale = PREFERRED[i][0];
482             ULocale loc = new ULocale(locale);
483             String[] expected = PREFERRED[i];
484             String[] pref = Collator.getKeywordValuesForLocale("collation", loc, true);
485             for (int j = 1; j < expected.length; ++j) {
486                 if (!arrayContains(pref, expected[j])) {
487                     errln("Keyword value " + expected[j] + " missing for locale: " + locale);
488                 }
489             }
490 
491             // Collator.getKeywordValues return the same contents for both commonlyUsed
492             // true and false.
493             String[] all = Collator.getKeywordValuesForLocale("collation", loc, false);
494             boolean matchAll = false;
495             if (pref.length == all.length) {
496                 matchAll = true;
497                 for (int j = 0; j < pref.length; j++) {
498                     boolean foundMatch = false;
499                     for (int k = 0; k < all.length; k++) {
500                         if (pref[j].equals(all[k])) {
501                             foundMatch = true;
502                             break;
503                         }
504                     }
505                     if (!foundMatch) {
506                         matchAll = false;
507                         break;
508                     }
509                 }
510             }
511             if (!matchAll) {
512                 errln("FAIL: All values for locale " + loc
513                         + " got:" + Arrays.toString(all) + " expected:" + Arrays.toString(pref));
514             }
515         }
516     }
517 }
518