]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceTest.java
Upgrade ICU4J.
[Dictionary.git] / jars / icu4j-52_1 / main / tests / core / src / com / ibm / icu / dev / test / util / ICUServiceTest.java
1 /**
2  *******************************************************************************
3  * Copyright (C) 2001-2013, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.dev.test.util;
8
9 import java.text.Collator;
10 import java.util.Arrays;
11 import java.util.Collections;
12 import java.util.Comparator;
13 import java.util.EventListener;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.Set;
21 import java.util.SortedMap;
22
23 import com.ibm.icu.dev.test.TestFmwk;
24 import com.ibm.icu.impl.ICULocaleService;
25 import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
26 import com.ibm.icu.impl.ICULocaleService.LocaleKey;
27 import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
28 import com.ibm.icu.impl.ICUNotifier;
29 import com.ibm.icu.impl.ICURWLock;
30 import com.ibm.icu.impl.ICUResourceBundle;
31 import com.ibm.icu.impl.ICUService;
32 import com.ibm.icu.impl.ICUService.Factory;
33 import com.ibm.icu.impl.ICUService.Key;
34 import com.ibm.icu.impl.ICUService.ServiceListener;
35 import com.ibm.icu.impl.ICUService.SimpleFactory;
36 import com.ibm.icu.impl.LocaleUtility;
37 import com.ibm.icu.util.ULocale;
38
39 public class ICUServiceTest extends TestFmwk
40 {
41     public static void main(String[] args) throws Exception {
42     ICUServiceTest test = new ICUServiceTest();
43     test.run(args);
44     }
45
46     private String lrmsg(String message, Object lhs, Object rhs) {
47     return message + " lhs: " + lhs + " rhs: " + rhs;
48     }
49
50     public void confirmBoolean(String message, boolean val) {
51     msg(message, val ? LOG : ERR, !val, true);
52     }
53
54     public void confirmEqual(String message, Object lhs, Object rhs) {
55         msg(lrmsg(message, lhs, rhs), (lhs == null ? rhs == null : lhs.equals(rhs)) ? LOG : ERR, true, true);
56     }
57
58     public void confirmIdentical(String message, Object lhs, Object rhs) {
59     msg(lrmsg(message, lhs, rhs), lhs == rhs ? LOG : ERR, true, true);
60     }
61
62     public void confirmIdentical(String message, int lhs, int rhs) {
63     msg(message + " lhs: " + lhs + " rhs: " + rhs, lhs == rhs ? LOG : ERR, true, true);
64     }
65
66     /**
67      * Convenience override of getDisplayNames(ULocale, Comparator, String) that
68      * uses the current default ULocale as the locale, the default collator for
69      * the locale as the comparator to sort the display names, and null for
70      * the matchID.
71      */
72     public SortedMap getDisplayNames(ICUService service) {
73         ULocale locale = ULocale.getDefault();
74         Collator col = Collator.getInstance(locale.toLocale());
75         return service.getDisplayNames(locale, col, null);
76     }
77
78     /**
79      * Convenience override of getDisplayNames(ULocale, Comparator, String) that
80      * uses the default collator for the locale as the comparator to
81      * sort the display names, and null for the matchID.
82      */
83     public SortedMap getDisplayNames(ICUService service, ULocale locale) {
84         Collator col = Collator.getInstance(locale.toLocale());
85         return service.getDisplayNames(locale, col, null);
86     }
87     /**
88      * Convenience override of getDisplayNames(ULocale, Comparator, String) that
89      * uses the default collator for the locale as the comparator to
90      * sort the display names.
91      */
92     public SortedMap getDisplayNames(ICUService service, ULocale locale, String matchID) {
93         Collator col = Collator.getInstance(locale.toLocale());
94         return service.getDisplayNames(locale, col, matchID);
95     }
96
97     // use locale keys
98     static final class TestService extends ICUService {
99         public TestService() {
100             super("Test Service");
101         }
102
103     public Key createKey(String id) {
104         return LocaleKey.createWithCanonicalFallback(id, null); // no fallback locale
105     }
106     }
107
108     public void TestAPI() {
109     // create a service using locale keys,
110     ICUService service = new TestService();
111
112         logln("service name:" + service.getName());
113
114     // register an object with one locale,
115     // search for an object with a more specific locale
116     // should return the original object
117     Integer singleton0 = new Integer(0);
118     service.registerObject(singleton0, "en_US");
119     Object result = service.get("en_US_FOO");
120     confirmIdentical("1) en_US_FOO -> en_US", result, singleton0);
121
122     // register a new object with the more specific locale
123     // search for an object with that locale
124     // should return the new object
125     Integer singleton1 = new Integer(1);
126     service.registerObject(singleton1, "en_US_FOO");
127     result = service.get("en_US_FOO");
128     confirmIdentical("2) en_US_FOO -> en_US_FOO", result, singleton1);
129
130     // search for an object that falls back to the first registered locale
131     result = service.get("en_US_BAR");
132     confirmIdentical("3) en_US_BAR -> en_US", result, singleton0);
133
134     // get a list of the factories, should be two
135     List factories = service.factories();
136     confirmIdentical("4) factory size", factories.size(), 2);
137
138     // register a new object with yet another locale
139     // original factory list is unchanged
140     Integer singleton2 = new Integer(2);
141     service.registerObject(singleton2, "en");
142     confirmIdentical("5) factory size", factories.size(), 2);
143
144     // search for an object with the new locale
145     // stack of factories is now en, en_US_FOO, en_US
146     // search for en_US should still find en_US object
147     result = service.get("en_US_BAR");
148     confirmIdentical("6) en_US_BAR -> en_US", result, singleton0);
149
150     // register a new object with an old id, should hide earlier factory using this id, but leave it there
151     Integer singleton3 = new Integer(3);
152     service.registerObject(singleton3, "en_US");
153     factories = service.factories();
154     confirmIdentical("9) factory size", factories.size(), 4);
155
156     // should get data from that new factory
157     result = service.get("en_US_BAR");
158     confirmIdentical("10) en_US_BAR -> (3)", result, singleton3);
159
160     // remove new factory
161     // should have fewer factories again
162     service.unregisterFactory((Factory)factories.get(0));
163     factories = service.factories();
164     confirmIdentical("11) factory size", factories.size(), 3);
165
166     // should get original data again after remove factory
167     result = service.get("en_US_BAR");
168     confirmIdentical("12) en_US_BAR -> 0", result, singleton0);
169
170     // shouldn't find unregistered ids
171     result = service.get("foo");
172     confirmIdentical("13) foo -> null", result, null);
173
174     // should find non-canonical strings
175     String[] resultID = new String[1];
176     result = service.get("EN_us_fOo", resultID);
177     confirmEqual("14) find non-canonical", resultID[0], "en_US_FOO");
178
179     // should be able to register non-canonical strings and get them canonicalized
180     service.registerObject(singleton3, "eN_ca_dUde");
181     result = service.get("En_Ca_DuDe", resultID);
182     confirmEqual("15) register non-canonical", resultID[0], "en_CA_DUDE");
183
184     // should be able to register invisible factories, these will not
185     // be visible by default, but if you know the secret password you
186     // can still access these services...
187     Integer singleton4 = new Integer(4);
188     service.registerObject(singleton4, "en_US_BAR", false);
189     result = service.get("en_US_BAR");
190     confirmIdentical("17) get invisible", result, singleton4);
191
192     // should not be able to locate invisible services
193     Set ids = service.getVisibleIDs();
194     confirmBoolean("18) find invisible", !ids.contains("en_US_BAR"));
195
196     service.reset();
197     // an anonymous factory than handles all ids
198     {
199         Factory factory = new Factory() {
200             public Object create(Key key, ICUService unusedService) {
201                 return new ULocale(key.currentID());
202             }
203
204             public void updateVisibleIDs(Map unusedResult) {
205             }
206
207             public String getDisplayName(String id, ULocale l) {
208                 return null;
209             }
210         };
211         service.registerFactory(factory);
212
213         // anonymous factory will still handle the id
214         result = service.get(ULocale.US.toString());
215         confirmEqual("21) locale", result, ULocale.US);
216
217         // still normalizes id
218         result = service.get("EN_US_BAR");
219         confirmEqual("22) locale", result, new ULocale("en_US_BAR"));
220
221         // we can override for particular ids
222         service.registerObject(singleton3, "en_US_BAR");
223         result = service.get("en_US_BAR");
224         confirmIdentical("23) override super", result, singleton3);
225
226     }
227
228     // empty service should not recognize anything
229     service.reset();
230     result = service.get("en_US");
231     confirmIdentical("24) empty", result, null);
232
233     // create a custom multiple key factory
234     {
235         String[] xids = { "en_US_VALLEY_GIRL",
236                   "en_US_VALLEY_BOY",
237                   "en_US_SURFER_GAL",
238                   "en_US_SURFER_DUDE"
239         };
240         service.registerFactory(new TestLocaleKeyFactory(xids, "Later"));
241     }
242
243     // iterate over the visual ids returned by the multiple factory
244     {
245         Set vids = service.getVisibleIDs();
246         Iterator iter = vids.iterator();
247         int count = 0;
248         while (iter.hasNext()) {
249         ++count;
250                 String id = (String)iter.next();
251         logln("  " + id + " --> " + service.get(id));
252         }
253         // four visible ids
254         confirmIdentical("25) visible ids", count, 4);
255     }
256
257     // iterate over the display names
258     {
259         Map dids = getDisplayNames(service, ULocale.GERMANY);
260         Iterator iter = dids.entrySet().iterator();
261         int count = 0;
262         while (iter.hasNext()) {
263         ++count;
264         Entry e = (Entry)iter.next();
265         logln("  " + e.getKey() + " -- > " + e.getValue());
266         }
267         // four display names, in german
268         confirmIdentical("26) display names", count, 4);
269     }
270
271     // no valid display name
272     confirmIdentical("27) get display name", service.getDisplayName("en_US_VALLEY_GEEK"), null);
273
274     {
275         String name = service.getDisplayName("en_US_SURFER_DUDE", ULocale.US);
276         confirmEqual("28) get display name", name, "English (United States, SURFER_DUDE)");
277     }
278
279     // register another multiple factory
280     {
281         String[] xids = {
282         "en_US_SURFER", "en_US_SURFER_GAL", "en_US_SILICON", "en_US_SILICON_GEEK"
283         };
284         service.registerFactory(new TestLocaleKeyFactory(xids, "Rad dude"));
285     }
286
287     // this time, we have seven display names
288         // Rad dude's surfer gal 'replaces' later's surfer gal
289     {
290         Map dids = getDisplayNames(service);
291         Iterator iter = dids.entrySet().iterator();
292         int count = 0;
293         while (iter.hasNext()) {
294         ++count;
295         Entry e = (Entry)iter.next();
296         logln("  " + e.getKey() + " --> " + e.getValue());
297         }
298         // seven display names, in spanish
299         confirmIdentical("29) display names", count, 7);
300     }
301
302     // we should get the display name corresponding to the actual id
303     // returned by the id we used.
304     {
305         String[] actualID = new String[1];
306         String id = "en_us_surfer_gal";
307         String gal = (String)service.get(id, actualID);
308         if (gal != null) {
309                 logln("actual id: " + actualID[0]);
310         String displayName = service.getDisplayName(actualID[0], ULocale.US);
311         logln("found actual: " + gal + " with display name: " + displayName);
312         confirmBoolean("30) found display name for actual", displayName != null);
313
314         displayName = service.getDisplayName(id, ULocale.US);
315         logln("found query: " + gal + " with display name: " + displayName);
316         // this is no longer a bug, we want to return display names for anything
317         // that a factory handles.  since we handle it, we should return a display
318         // name.  see jb3549
319         // confirmBoolean("31) found display name for query", displayName == null);
320         } else {
321         errln("30) service could not find entry for " + id);
322         }
323
324             // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
325         id = "en_US_SURFER_BOZO";
326         String bozo = (String)service.get(id, actualID);
327         if (bozo != null) {
328         String displayName = service.getDisplayName(actualID[0], ULocale.US);
329         logln("found actual: " + bozo + " with display name: " + displayName);
330         confirmBoolean("32) found display name for actual", displayName != null);
331
332         displayName = service.getDisplayName(id, ULocale.US);
333         logln("found actual: " + bozo + " with display name: " + displayName);
334         // see above and jb3549
335         // confirmBoolean("33) found display name for query", displayName == null);
336         } else {
337         errln("32) service could not find entry for " + id);
338         }
339
340             confirmBoolean("34) is default ", !service.isDefault());
341     }
342
343         /*
344       // disallow hiding for now
345
346       // hiding factory should obscure 'sublocales'
347       {
348       String[] xids = {
349       "en_US_VALLEY", "en_US_SILICON"
350       };
351       service.registerFactory(new TestHidingFactory(xids, "hiding"));
352       }
353
354       {
355       Map dids = service.getDisplayNames();
356       Iterator iter = dids.entrySet().iterator();
357       int count = 0;
358       while (iter.hasNext()) {
359       ++count;
360       Entry e = (Entry)iter.next();
361       logln("  " + e.getKey() + " -- > " + e.getValue());
362       }
363       confirmIdentical("35) hiding factory", count, 5);
364       }
365         */
366
367     {
368         Set xids = service.getVisibleIDs();
369         Iterator iter = xids.iterator();
370         while (iter.hasNext()) {
371         String xid = (String)iter.next();
372         logln(xid + "?  " + service.get(xid));
373         }
374
375         logln("valleygirl?  " + service.get("en_US_VALLEY_GIRL"));
376         logln("valleyboy?   " + service.get("en_US_VALLEY_BOY"));
377         logln("valleydude?  " + service.get("en_US_VALLEY_DUDE"));
378         logln("surfergirl?  " + service.get("en_US_SURFER_GIRL"));
379     }
380
381     // resource bundle factory.
382     service.reset();
383     service.registerFactory(new ICUResourceBundleFactory());
384
385     // list all of the resources
386     {
387             logln("all visible ids: " + service.getVisibleIDs());
388             /*
389           Set xids = service.getVisibleIDs();
390           StringBuffer buf = new StringBuffer("{");
391           boolean notfirst = false;
392           Iterator iter = xids.iterator();
393           while (iter.hasNext()) {
394           String xid = (String)iter.next();
395           if (notfirst) {
396           buf.append(", ");
397           } else {
398           notfirst = true;
399           }
400           buf.append(xid);
401           }
402           buf.append("}");
403           logln(buf.toString());
404             */
405     }
406
407         // list only the resources for es, default locale
408         // since we're using the default Key, only "es" is matched
409         {
410             logln("visible ids for es locale: " + service.getVisibleIDs("es"));
411         }
412
413         // list only the spanish display names for es, spanish collation order
414         // since we're using the default Key, only "es" is matched
415         {
416             logln("display names: " + getDisplayNames(service, new ULocale("es"), "es"));
417         }
418
419         // list the display names in reverse order
420         {
421             logln("display names in reverse order: " +
422                   service.getDisplayNames(ULocale.US, new Comparator() {
423                           public int compare(Object lhs, Object rhs) {
424                               return -String.CASE_INSENSITIVE_ORDER.compare((String)lhs, (String)rhs);
425                           }
426                       }));
427         }
428
429     // get all the display names of these resources
430     // this should be fast since the display names were cached.
431     {
432             logln("service display names for de_DE");
433         Map names = getDisplayNames(service, new ULocale("de_DE"));
434         StringBuffer buf = new StringBuffer("{");
435         Iterator iter = names.entrySet().iterator();
436         while (iter.hasNext()) {
437         Entry e = (Entry)iter.next();
438         String name = (String)e.getKey();
439         String id = (String)e.getValue();
440         buf.append("\n   " + name + " --> " + id);
441         }
442         buf.append("\n}");
443         logln(buf.toString());
444     }
445
446         CalifornioLanguageFactory califactory = new CalifornioLanguageFactory();
447         service.registerFactory(califactory);
448     // get all the display names of these resources
449     {
450             logln("californio language factory");
451         StringBuffer buf = new StringBuffer("{");
452             String[] idNames = {
453                 CalifornioLanguageFactory.californio,
454         CalifornioLanguageFactory.valley,
455         CalifornioLanguageFactory.surfer,
456         CalifornioLanguageFactory.geek
457             };
458             for (int i = 0; i < idNames.length; ++i) {
459                 String idName = idNames[i];
460                 buf.append("\n  --- " + idName + " ---");
461                 Map names = getDisplayNames(service, new ULocale(idName));
462                 Iterator iter = names.entrySet().iterator();
463                 while (iter.hasNext()) {
464                     Entry e = (Entry)iter.next();
465                     String name = (String)e.getKey();
466                     String id = (String)e.getValue();
467                     buf.append("\n    " + name + " --> " + id);
468                 }
469         }
470         buf.append("\n}");
471         logln(buf.toString());
472     }
473
474     // test notification
475     // simple registration
476     {
477             logln("simple registration notification");
478         ICULocaleService ls = new ICULocaleService();
479         ServiceListener l1 = new ServiceListener() {
480             private int n;
481             public void serviceChanged(ICUService s) {
482             logln("listener 1 report " + n++ + " service changed: " + s);
483             }
484         };
485         ls.addListener(l1);
486         ServiceListener l2 = new ServiceListener() {
487             private int n;
488             public void serviceChanged(ICUService s) {
489             logln("listener 2 report " + n++ + " service changed: " + s);
490             }
491         };
492         ls.addListener(l2);
493         logln("registering foo... ");
494         ls.registerObject("Foo", "en_FOO");
495         logln("registering bar... ");
496         ls.registerObject("Bar", "en_BAR");
497         logln("getting foo...");
498         logln((String)ls.get("en_FOO"));
499         logln("removing listener 2...");
500         ls.removeListener(l2);
501         logln("registering baz...");
502         ls.registerObject("Baz", "en_BAZ");
503         logln("removing listener 1");
504         ls.removeListener(l1);
505         logln("registering burp...");
506         ls.registerObject("Burp", "en_BURP");
507
508         // should only get one notification even if register multiple times
509         logln("... trying multiple registration");
510         ls.addListener(l1);
511         ls.addListener(l1);
512         ls.addListener(l1);
513         ls.addListener(l2);
514         ls.registerObject("Foo", "en_FOO");
515         logln("... registered foo");
516
517         // since in a separate thread, we can callback and not deadlock
518         ServiceListener l3 = new ServiceListener() {
519             private int n;
520             public void serviceChanged(ICUService s) {
521             logln("listener 3 report " + n++ + " service changed...");
522             if (s.get("en_BOINK") == null) { // don't recurse on ourselves!!!
523                 logln("registering boink...");
524                 s.registerObject("boink", "en_BOINK");
525             }
526             }
527         };
528         ls.addListener(l3);
529         logln("registering boo...");
530         ls.registerObject("Boo", "en_BOO");
531         logln("...done");
532
533         try {
534         Thread.sleep(100);
535         }
536         catch (InterruptedException e) {
537         }
538     }
539     }
540
541     static class TestLocaleKeyFactory extends LocaleKeyFactory {
542     protected final Set ids;
543     protected final String factoryID;
544
545     public TestLocaleKeyFactory(String[] ids, String factoryID) {
546             super(VISIBLE, factoryID);
547
548         this.ids = Collections.unmodifiableSet(new HashSet(Arrays.asList(ids)));
549             this.factoryID = factoryID + ": ";
550     }
551
552     protected Object handleCreate(ULocale loc, int kind, ICUService service) {
553             return factoryID + loc.toString();
554     }
555
556     protected Set getSupportedIDs() {
557             return ids;
558     }
559     }
560
561     /*
562       // Disallow hiding for now since it causes gnarly problems, like
563       // how do you localize the hidden (but still exported) names.
564
565       static class TestHidingFactory implements ICUService.Factory {
566       protected final String[] ids;
567       protected final String factoryID;
568
569       public TestHidingFactory(String[] ids) {
570       this(ids, "Hiding");
571       }
572
573       public TestHidingFactory(String[] ids, String factoryID) {
574       this.ids = (String[])ids.clone();
575
576       if (factoryID == null || factoryID.length() == 0) {
577       this.factoryID = "";
578       } else {
579       this.factoryID = factoryID + ": ";
580       }
581       }
582
583       public Object create(Key key, ICUService service) {
584       for (int i = 0; i < ids.length; ++i) {
585       if (LocaleUtility.isFallbackOf(ids[i], key.currentID())) {
586       return factoryID + key.canonicalID();
587       }
588       }
589       return null;
590       }
591
592       public void updateVisibleIDs(Map result) {
593       for (int i = 0; i < ids.length; ++i) {
594       String id = ids[i];
595       Iterator iter = result.keySet().iterator();
596       while (iter.hasNext()) {
597       if (LocaleUtility.isFallbackOf(id, (String)iter.next())) {
598       iter.remove();
599       }
600       }
601       result.put(id, this);
602       }
603       }
604
605       public String getDisplayName(String id, ULocale locale) {
606       return factoryID + new ULocale(id).getDisplayName(locale);
607       }
608       }
609     */
610
611     static class CalifornioLanguageFactory extends ICUResourceBundleFactory {
612     public static String californio = "en_US_CA";
613     public static String valley = californio + "_VALLEY";
614     public static String surfer = californio + "_SURFER";
615     public static String geek = californio + "_GEEK";
616         public static Set supportedIDs;
617         static {
618             HashSet result = new HashSet();
619             result.addAll(ICUResourceBundle.getAvailableLocaleNameSet());
620         result.add(californio);
621         result.add(valley);
622         result.add(surfer);
623         result.add(geek);
624             supportedIDs = Collections.unmodifiableSet(result);
625         }
626
627     public Set getSupportedIDs() {
628             return supportedIDs;
629     }
630
631     public String getDisplayName(String id, ULocale locale) {
632         String prefix = "";
633         String suffix = "";
634         String ls = locale.toString();
635         if (LocaleUtility.isFallbackOf(californio, ls)) {
636         if (ls.equalsIgnoreCase(valley)) {
637             prefix = "Like, you know, it's so totally ";
638         } else if (ls.equalsIgnoreCase(surfer)) {
639             prefix = "Dude, its ";
640         } else if (ls.equalsIgnoreCase(geek)) {
641             prefix = "I'd estimate it's approximately ";
642         } else {
643             prefix = "Huh?  Maybe ";
644         }
645         }
646         if (LocaleUtility.isFallbackOf(californio, id)) {
647         if (id.equalsIgnoreCase(valley)) {
648             suffix = "like the Valley, you know?  Let's go to the mall!";
649         } else if (id.equalsIgnoreCase(surfer)) {
650             suffix = "time to hit those gnarly waves, Dude!!!";
651         } else if (id.equalsIgnoreCase(geek)) {
652             suffix = "all systems go.  T-Minus 9, 8, 7...";
653         } else {
654             suffix = "No Habla Englais";
655         }
656         } else {
657         suffix = super.getDisplayName(id, locale);
658         }
659
660         return prefix + suffix;
661     }
662     }
663
664     public void TestLocale() {
665     ICULocaleService service = new ICULocaleService("test locale");
666     service.registerObject("root", ULocale.ROOT);
667     service.registerObject("german", "de");
668     service.registerObject("german_Germany", ULocale.GERMANY);
669     service.registerObject("japanese", "ja");
670     service.registerObject("japanese_Japan", ULocale.JAPAN);
671
672     Object target = service.get("de_US");
673     confirmEqual("test de_US", "german", target);
674
675         ULocale de = new ULocale("de");
676         ULocale de_US = new ULocale("de_US");
677
678         target = service.get(de_US);
679     confirmEqual("test de_US 2", "german", target);
680
681         target = service.get(de_US, LocaleKey.KIND_ANY);
682     confirmEqual("test de_US 3", "german", target);
683
684         target = service.get(de_US, 1234);
685     confirmEqual("test de_US 4", "german", target);
686
687         ULocale[] actualReturn = new ULocale[1];
688         target = service.get(de_US, actualReturn);
689         confirmEqual("test de_US 5", "german", target);
690         confirmEqual("test de_US 6", actualReturn[0], de);
691
692         actualReturn[0] = null;
693         target = service.get(de_US, LocaleKey.KIND_ANY, actualReturn);
694         confirmEqual("test de_US 7", actualReturn[0], de);
695
696         actualReturn[0] = null;
697         target = service.get(de_US, 1234, actualReturn);
698     confirmEqual("test de_US 8", "german", target);
699         confirmEqual("test de_US 9", actualReturn[0], de);
700
701         service.registerObject("one/de_US", de_US, 1);
702         service.registerObject("two/de_US", de_US, 2);
703
704         target = service.get(de_US, 1);
705         confirmEqual("test de_US kind 1", "one/de_US", target);
706
707         target = service.get(de_US, 2);
708         confirmEqual("test de_US kind 2", "two/de_US", target);
709
710         target = service.get(de_US);
711         confirmEqual("test de_US kind 3", "german", target);
712
713         LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en", null, 1234);
714         logln("lkey prefix: " + lkey.prefix());
715         logln("lkey descriptor: " + lkey.currentDescriptor());
716         logln("lkey current locale: " + lkey.currentLocale());
717
718         lkey.fallback();
719         logln("lkey descriptor 2: " + lkey.currentDescriptor());
720
721         lkey.fallback();
722         logln("lkey descriptor 3: " + lkey.currentDescriptor());
723
724     target = service.get("za_PPP");
725     confirmEqual("test zappp", "root", target);
726
727     ULocale loc = ULocale.getDefault();
728     ULocale.setDefault(ULocale.JAPANESE);
729     target = service.get("za_PPP");
730     confirmEqual("test with ja locale", "japanese", target);
731
732     Set ids = service.getVisibleIDs();
733     for (Iterator iter = ids.iterator(); iter.hasNext();) {
734         logln("id: " + iter.next());
735     }
736
737     ULocale.setDefault(loc);
738     ids = service.getVisibleIDs();
739     for (Iterator iter = ids.iterator(); iter.hasNext();) {
740         logln("id: " + iter.next());
741     }
742
743     target = service.get("za_PPP");
744     confirmEqual("test with en locale", "root", target);
745
746         ULocale[] locales = service.getAvailableULocales();
747         confirmIdentical("test available locales", locales.length, 6);
748         logln("locales: ");
749         for (int i = 0; i < locales.length; ++i) {
750             log("\n  [" + i + "] " + locales[i]);
751         }
752         logln(" ");
753
754         service.registerFactory(new ICUResourceBundleFactory());
755         target = service.get(ULocale.JAPAN);
756
757         {
758             int n = 0;
759             List factories = service.factories();
760             Iterator iter = factories.iterator();
761             while (iter.hasNext()) {
762                 logln("[" + n++ + "] " + iter.next());
763             }
764         }
765
766         // list only the english display names for es, in reverse order
767         // since we're using locale keys, we should get all and only the es locales
768         // hmmm, the default toString function doesn't print in sorted order for TreeMap
769         {
770             SortedMap map = service.getDisplayNames(ULocale.US,
771                             new Comparator() {
772                                 public int compare(Object lhs, Object rhs) {
773                                 return -String.CASE_INSENSITIVE_ORDER.compare((String)lhs, (String)rhs);
774                                 }
775                             },
776                             "es");
777
778             logln("es display names in reverse order " + map);
779         }
780     }
781
782     public void TestWrapFactory() {
783         final String greeting = "Hello There";
784         final String greetingID = "greeting";
785
786         ICUService service = new ICUService("wrap");
787         service.registerObject(greeting, greetingID);
788
789         logln("test one: " + service.get(greetingID));
790
791         class WrapFactory implements Factory {
792             public Object create(Key key, ICUService serviceArg) {
793                 if (key.currentID().equals(greetingID)) {
794                     Object previous = serviceArg.getKey(key, null, this);
795                     return "A different greeting: \"" + previous + "\"";
796                 }
797                 return null;
798             }
799
800             public void updateVisibleIDs(Map result) {
801                 result.put("greeting", this);
802             }
803
804             public String getDisplayName(String id, ULocale locale) {
805                 return "wrap '" + id + "'";
806             }
807         }
808         service.registerFactory(new WrapFactory());
809
810         confirmEqual("wrap test: ", service.get(greetingID), "A different greeting: \"" + greeting + "\"");
811     }
812
813     // misc coverage tests
814     public void TestCoverage() {
815     // Key
816     Key key = new Key("foobar");
817     logln("ID: " + key.id());
818     logln("canonicalID: " + key.canonicalID());
819     logln("currentID: " + key.currentID());
820     logln("has fallback: " + key.fallback());
821
822     // SimpleFactory
823     Object obj = new Object();
824     SimpleFactory sf = new SimpleFactory(obj, "object");
825     try {
826         sf = new SimpleFactory(null, null);
827         errln("didn't throw exception");
828     }
829     catch (IllegalArgumentException e) {
830         logln("OK: " + e.getMessage());
831     }
832     catch (Exception e) {
833         errln("threw wrong exception" + e);
834     }
835     logln(sf.getDisplayName("object", null));
836
837     // ICUService
838     ICUService service = new ICUService();
839     service.registerFactory(sf);
840
841     try {
842         service.get(null, null);
843         errln("didn't throw exception");
844     }
845     catch (NullPointerException e) {
846         logln("OK: " + e.getMessage());
847     }
848         /*
849       catch (Exception e) {
850       errln("threw wrong exception" + e);
851       }
852         */
853     try {
854         service.registerFactory(null);
855         errln("didn't throw exception");
856     }
857     catch (NullPointerException e) {
858         logln("OK: " + e.getMessage());
859     }
860     catch (Exception e) {
861         errln("threw wrong exception" + e);
862     }
863
864     try {
865         service.unregisterFactory(null);
866         errln("didn't throw exception");
867     }
868     catch (NullPointerException e) {
869         logln("OK: " + e.getMessage());
870     }
871     catch (Exception e) {
872         errln("threw wrong exception" + e);
873     }
874
875     logln("object is: " + service.get("object"));
876
877     logln("stats: " + service.stats());
878
879     // ICURWLock
880
881     ICURWLock rwlock = new ICURWLock();
882     rwlock.resetStats();
883
884     rwlock.acquireRead();
885     rwlock.releaseRead();
886
887     rwlock.acquireWrite();
888     rwlock.releaseWrite();
889     logln("stats: " + rwlock.getStats());
890     logln("stats: " + rwlock.clearStats());
891     rwlock.acquireRead();
892     rwlock.releaseRead();
893     rwlock.acquireWrite();
894     rwlock.releaseWrite();
895     logln("stats: " + rwlock.getStats());
896
897     try {
898         rwlock.releaseRead();
899         errln("no error thrown");
900     }
901     catch (Exception e) {
902         logln("OK: " + e.getMessage());
903     }
904
905     try {
906         rwlock.releaseWrite();
907         errln("no error thrown");
908     }
909     catch (Exception e) {
910         logln("OK: " + e.getMessage());
911     }
912
913         // ICULocaleService
914
915     // LocaleKey
916
917     // LocaleKey lkey = LocaleKey.create("en_US", "ja_JP");
918     // lkey = LocaleKey.create(null, null);
919     LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en_US", "ja_JP");
920         logln("lkey: " + lkey);
921
922         lkey = LocaleKey.createWithCanonicalFallback(null, null);
923         logln("lkey from null,null: " + lkey);
924
925     // LocaleKeyFactory
926     LocaleKeyFactory lkf = new LKFSubclass(false);
927         logln("lkf: " + lkf);
928     logln("obj: " + lkf.create(lkey, null));
929     logln(lkf.getDisplayName("foo", null));
930     logln(lkf.getDisplayName("bar", null));
931     lkf.updateVisibleIDs(new HashMap());
932
933     LocaleKeyFactory invisibleLKF = new LKFSubclass(false);
934     logln("obj: " + invisibleLKF.create(lkey, null));
935     logln(invisibleLKF.getDisplayName("foo", null));
936     logln(invisibleLKF.getDisplayName("bar", null));
937     invisibleLKF.updateVisibleIDs(new HashMap());
938
939     // ResourceBundleFactory
940     ICUResourceBundleFactory rbf = new ICUResourceBundleFactory();
941     logln("RB: " + rbf.create(lkey, null));
942
943     // ICUNotifier
944     ICUNotifier nf = new ICUNSubclass();
945     try {
946         nf.addListener(null);
947         errln("added null listener");
948     }
949     catch (NullPointerException e) {
950         logln(e.getMessage());
951     }
952     catch (Exception e) {
953         errln("got wrong exception");
954     }
955
956     try {
957         nf.addListener(new WrongListener());
958         errln("added wrong listener");
959     }
960     catch (IllegalStateException e) {
961         logln(e.getMessage());
962     }
963     catch (Exception e) {
964         errln("got wrong exception");
965     }
966
967     try {
968         nf.removeListener(null);
969         errln("removed null listener");
970     }
971     catch (NullPointerException e) {
972         logln(e.getMessage());
973     }
974     catch (Exception e) {
975         errln("got wrong exception");
976     }
977
978     nf.removeListener(new MyListener());
979     nf.notifyChanged();
980     nf.addListener(new MyListener());
981     nf.removeListener(new MyListener());
982     }
983
984     static class MyListener implements EventListener {
985     }
986
987     static class WrongListener implements EventListener {
988     }
989
990     static class ICUNSubclass extends ICUNotifier {
991         public boolean acceptsListener(EventListener l) {
992             return l instanceof MyListener;
993         }
994     
995         // not used, just needed to implement abstract base
996         public void notifyListener(EventListener l) {
997         }
998     }
999
1000     static class LKFSubclass extends LocaleKeyFactory {
1001     LKFSubclass(boolean visible) {
1002         super(visible ? VISIBLE : INVISIBLE);
1003     }
1004
1005     protected Set getSupportedIDs() {
1006             return Collections.EMPTY_SET;
1007     }
1008     }
1009 }