17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2001-2013, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.util;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.Collator;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collections;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Comparator;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.EventListener;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashSet;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Iterator;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.List;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map.Entry;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.SortedMap;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.dev.test.TestFmwk;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICULocaleService;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICULocaleService.LocaleKey;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUNotifier;
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICURWLock;
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUResourceBundle;
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService.Factory;
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService.Key;
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService.ServiceListener;
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService.SimpleFactory;
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.LocaleUtility;
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale;
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class ICUServiceTest extends TestFmwk
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static void main(String[] args) throws Exception {
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICUServiceTest test = new ICUServiceTest();
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    test.run(args);
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String lrmsg(String message, Object lhs, Object rhs) {
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    return message + " lhs: " + lhs + " rhs: " + rhs;
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void confirmBoolean(String message, boolean val) {
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    msg(message, val ? LOG : ERR, !val, true);
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void confirmEqual(String message, Object lhs, Object rhs) {
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        msg(lrmsg(message, lhs, rhs), (lhs == null ? rhs == null : lhs.equals(rhs)) ? LOG : ERR, true, true);
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void confirmIdentical(String message, Object lhs, Object rhs) {
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    msg(lrmsg(message, lhs, rhs), lhs == rhs ? LOG : ERR, true, true);
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void confirmIdentical(String message, int lhs, int rhs) {
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    msg(message + " lhs: " + lhs + " rhs: " + rhs, lhs == rhs ? LOG : ERR, true, true);
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Convenience override of getDisplayNames(ULocale, Comparator, String) that
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * uses the current default ULocale as the locale, the default collator for
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the locale as the comparator to sort the display names, and null for
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the matchID.
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public SortedMap getDisplayNames(ICUService service) {
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale locale = ULocale.getDefault();
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Collator col = Collator.getInstance(locale.toLocale());
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return service.getDisplayNames(locale, col, null);
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Convenience override of getDisplayNames(ULocale, Comparator, String) that
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * uses the default collator for the locale as the comparator to
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * sort the display names, and null for the matchID.
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public SortedMap getDisplayNames(ICUService service, ULocale locale) {
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Collator col = Collator.getInstance(locale.toLocale());
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return service.getDisplayNames(locale, col, null);
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Convenience override of getDisplayNames(ULocale, Comparator, String) that
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * uses the default collator for the locale as the comparator to
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * sort the display names.
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public SortedMap getDisplayNames(ICUService service, ULocale locale, String matchID) {
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Collator col = Collator.getInstance(locale.toLocale());
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return service.getDisplayNames(locale, col, matchID);
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // use locale keys
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final class TestService extends ICUService {
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public TestService() {
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super("Test Service");
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Key createKey(String id) {
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return LocaleKey.createWithCanonicalFallback(id, null); // no fallback locale
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestAPI() {
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // create a service using locale keys,
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICUService service = new TestService();
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("service name:" + service.getName());
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // register an object with one locale,
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // search for an object with a more specific locale
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should return the original object
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Integer singleton0 = new Integer(0);
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject(singleton0, "en_US");
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Object result = service.get("en_US_FOO");
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("1) en_US_FOO -> en_US", result, singleton0);
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // register a new object with the more specific locale
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // search for an object with that locale
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should return the new object
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Integer singleton1 = new Integer(1);
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject(singleton1, "en_US_FOO");
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US_FOO");
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("2) en_US_FOO -> en_US_FOO", result, singleton1);
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // search for an object that falls back to the first registered locale
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US_BAR");
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("3) en_US_BAR -> en_US", result, singleton0);
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // get a list of the factories, should be two
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    List factories = service.factories();
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("4) factory size", factories.size(), 2);
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // register a new object with yet another locale
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // original factory list is unchanged
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Integer singleton2 = new Integer(2);
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject(singleton2, "en");
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("5) factory size", factories.size(), 2);
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // search for an object with the new locale
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // stack of factories is now en, en_US_FOO, en_US
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // search for en_US should still find en_US object
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US_BAR");
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("6) en_US_BAR -> en_US", result, singleton0);
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // register a new object with an old id, should hide earlier factory using this id, but leave it there
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Integer singleton3 = new Integer(3);
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject(singleton3, "en_US");
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    factories = service.factories();
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("9) factory size", factories.size(), 4);
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should get data from that new factory
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US_BAR");
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("10) en_US_BAR -> (3)", result, singleton3);
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // remove new factory
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should have fewer factories again
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.unregisterFactory((Factory)factories.get(0));
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    factories = service.factories();
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("11) factory size", factories.size(), 3);
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should get original data again after remove factory
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US_BAR");
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("12) en_US_BAR -> 0", result, singleton0);
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // shouldn't find unregistered ids
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("foo");
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("13) foo -> null", result, null);
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should find non-canonical strings
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    String[] resultID = new String[1];
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("EN_us_fOo", resultID);
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("14) find non-canonical", resultID[0], "en_US_FOO");
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should be able to register non-canonical strings and get them canonicalized
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject(singleton3, "eN_ca_dUde");
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("En_Ca_DuDe", resultID);
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("15) register non-canonical", resultID[0], "en_CA_DUDE");
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should be able to register invisible factories, these will not
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // be visible by default, but if you know the secret password you
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // can still access these services...
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Integer singleton4 = new Integer(4);
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject(singleton4, "en_US_BAR", false);
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US_BAR");
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("17) get invisible", result, singleton4);
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should not be able to locate invisible services
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Set ids = service.getVisibleIDs();
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmBoolean("18) find invisible", !ids.contains("en_US_BAR"));
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.reset();
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // an anonymous factory than handles all ids
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Factory factory = new Factory() {
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public Object create(Key key, ICUService unusedService) {
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return new ULocale(key.currentID());
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public void updateVisibleIDs(Map unusedResult) {
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public String getDisplayName(String id, ULocale l) {
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(factory);
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // anonymous factory will still handle the id
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result = service.get(ULocale.US.toString());
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("21) locale", result, ULocale.US);
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // still normalizes id
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result = service.get("EN_US_BAR");
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("22) locale", result, new ULocale("en_US_BAR"));
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // we can override for particular ids
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerObject(singleton3, "en_US_BAR");
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result = service.get("en_US_BAR");
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmIdentical("23) override super", result, singleton3);
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // empty service should not recognize anything
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.reset();
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    result = service.get("en_US");
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("24) empty", result, null);
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // create a custom multiple key factory
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String[] xids = { "en_US_VALLEY_GIRL",
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                  "en_US_VALLEY_BOY",
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                  "en_US_SURFER_GAL",
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                  "en_US_SURFER_DUDE"
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(new TestLocaleKeyFactory(xids, "Later"));
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // iterate over the visual ids returned by the multiple factory
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Set vids = service.getVisibleIDs();
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator iter = vids.iterator();
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int count = 0;
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (iter.hasNext()) {
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ++count;
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String id = (String)iter.next();
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("  " + id + " --> " + service.get(id));
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // four visible ids
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmIdentical("25) visible ids", count, 4);
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // iterate over the display names
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Map dids = getDisplayNames(service, ULocale.GERMANY);
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator iter = dids.entrySet().iterator();
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int count = 0;
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (iter.hasNext()) {
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ++count;
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Entry e = (Entry)iter.next();
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("  " + e.getKey() + " -- > " + e.getValue());
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // four display names, in german
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmIdentical("26) display names", count, 4);
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // no valid display name
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmIdentical("27) get display name", service.getDisplayName("en_US_VALLEY_GEEK"), null);
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String name = service.getDisplayName("en_US_SURFER_DUDE", ULocale.US);
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("28) get display name", name, "English (United States, SURFER_DUDE)");
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // register another multiple factory
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String[] xids = {
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "en_US_SURFER", "en_US_SURFER_GAL", "en_US_SILICON", "en_US_SILICON_GEEK"
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(new TestLocaleKeyFactory(xids, "Rad dude"));
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // this time, we have seven display names
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Rad dude's surfer gal 'replaces' later's surfer gal
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Map dids = getDisplayNames(service);
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator iter = dids.entrySet().iterator();
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int count = 0;
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (iter.hasNext()) {
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ++count;
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Entry e = (Entry)iter.next();
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("  " + e.getKey() + " --> " + e.getValue());
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // seven display names, in spanish
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmIdentical("29) display names", count, 7);
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // we should get the display name corresponding to the actual id
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // returned by the id we used.
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String[] actualID = new String[1];
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String id = "en_us_surfer_gal";
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String gal = (String)service.get(id, actualID);
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (gal != null) {
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("actual id: " + actualID[0]);
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String displayName = service.getDisplayName(actualID[0], ULocale.US);
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("found actual: " + gal + " with display name: " + displayName);
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmBoolean("30) found display name for actual", displayName != null);
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        displayName = service.getDisplayName(id, ULocale.US);
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("found query: " + gal + " with display name: " + displayName);
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // this is no longer a bug, we want to return display names for anything
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // that a factory handles.  since we handle it, we should return a display
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // name.  see jb3549
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // confirmBoolean("31) found display name for query", displayName == null);
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("30) service could not find entry for " + id);
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        id = "en_US_SURFER_BOZO";
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String bozo = (String)service.get(id, actualID);
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (bozo != null) {
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String displayName = service.getDisplayName(actualID[0], ULocale.US);
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("found actual: " + bozo + " with display name: " + displayName);
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmBoolean("32) found display name for actual", displayName != null);
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        displayName = service.getDisplayName(id, ULocale.US);
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("found actual: " + bozo + " with display name: " + displayName);
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // see above and jb3549
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // confirmBoolean("33) found display name for query", displayName == null);
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("32) service could not find entry for " + id);
3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            confirmBoolean("34) is default ", !service.isDefault());
3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      // disallow hiding for now
3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      // hiding factory should obscure 'sublocales'
3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      {
3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      String[] xids = {
3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      "en_US_VALLEY", "en_US_SILICON"
3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      };
3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      service.registerFactory(new TestHidingFactory(xids, "hiding"));
3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      {
3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      Map dids = service.getDisplayNames();
3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      Iterator iter = dids.entrySet().iterator();
3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      int count = 0;
3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      while (iter.hasNext()) {
3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      ++count;
3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      Entry e = (Entry)iter.next();
3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      logln("  " + e.getKey() + " -- > " + e.getValue());
3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      confirmIdentical("35) hiding factory", count, 5);
3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        */
3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Set xids = service.getVisibleIDs();
3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator iter = xids.iterator();
3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (iter.hasNext()) {
3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String xid = (String)iter.next();
3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(xid + "?  " + service.get(xid));
3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("valleygirl?  " + service.get("en_US_VALLEY_GIRL"));
3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("valleyboy?   " + service.get("en_US_VALLEY_BOY"));
3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("valleydude?  " + service.get("en_US_VALLEY_DUDE"));
3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("surfergirl?  " + service.get("en_US_SURFER_GIRL"));
3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // resource bundle factory.
3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.reset();
3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerFactory(new ICUResourceBundleFactory());
3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // list all of the resources
3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("all visible ids: " + service.getVisibleIDs());
3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*
3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          Set xids = service.getVisibleIDs();
3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          StringBuffer buf = new StringBuffer("{");
3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          boolean notfirst = false;
3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          Iterator iter = xids.iterator();
3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          while (iter.hasNext()) {
3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          String xid = (String)iter.next();
3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          if (notfirst) {
3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          buf.append(", ");
3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          } else {
3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          notfirst = true;
3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          }
4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          buf.append(xid);
4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          }
4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          buf.append("}");
4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          logln(buf.toString());
4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            */
4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // list only the resources for es, default locale
4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // since we're using the default Key, only "es" is matched
4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("visible ids for es locale: " + service.getVisibleIDs("es"));
4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // list only the spanish display names for es, spanish collation order
4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // since we're using the default Key, only "es" is matched
4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("display names: " + getDisplayNames(service, new ULocale("es"), "es"));
4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // list the display names in reverse order
4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("display names in reverse order: " +
4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                  service.getDisplayNames(ULocale.US, new Comparator() {
4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          public int compare(Object lhs, Object rhs) {
4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                              return -String.CASE_INSENSITIVE_ORDER.compare((String)lhs, (String)rhs);
4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          }
4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                      }));
4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // get all the display names of these resources
4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // this should be fast since the display names were cached.
4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("service display names for de_DE");
4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Map names = getDisplayNames(service, new ULocale("de_DE"));
4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer buf = new StringBuffer("{");
4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator iter = names.entrySet().iterator();
4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (iter.hasNext()) {
4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Entry e = (Entry)iter.next();
4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String name = (String)e.getKey();
4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String id = (String)e.getValue();
4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        buf.append("\n   " + name + " --> " + id);
4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        buf.append("\n}");
4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(buf.toString());
4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CalifornioLanguageFactory califactory = new CalifornioLanguageFactory();
4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(califactory);
4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // get all the display names of these resources
4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("californio language factory");
4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer buf = new StringBuffer("{");
4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String[] idNames = {
4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                CalifornioLanguageFactory.californio,
4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CalifornioLanguageFactory.valley,
4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CalifornioLanguageFactory.surfer,
4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CalifornioLanguageFactory.geek
4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            };
4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < idNames.length; ++i) {
4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String idName = idNames[i];
4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buf.append("\n  --- " + idName + " ---");
4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                Map names = getDisplayNames(service, new ULocale(idName));
4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                Iterator iter = names.entrySet().iterator();
4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                while (iter.hasNext()) {
4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    Entry e = (Entry)iter.next();
4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    String name = (String)e.getKey();
4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    String id = (String)e.getValue();
4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buf.append("\n    " + name + " --> " + id);
4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        buf.append("\n}");
4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(buf.toString());
4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // test notification
4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // simple registration
4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("simple registration notification");
4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ICULocaleService ls = new ICULocaleService();
4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ServiceListener l1 = new ServiceListener() {
4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            private int n;
4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public void serviceChanged(ICUService s) {
4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("listener 1 report " + n++ + " service changed: " + s);
4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l1);
4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ServiceListener l2 = new ServiceListener() {
4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            private int n;
4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public void serviceChanged(ICUService s) {
4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("listener 2 report " + n++ + " service changed: " + s);
4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l2);
4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("registering foo... ");
4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.registerObject("Foo", "en_FOO");
4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("registering bar... ");
4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.registerObject("Bar", "en_BAR");
4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("getting foo...");
4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln((String)ls.get("en_FOO"));
4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("removing listener 2...");
5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.removeListener(l2);
5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("registering baz...");
5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.registerObject("Baz", "en_BAZ");
5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("removing listener 1");
5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.removeListener(l1);
5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("registering burp...");
5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.registerObject("Burp", "en_BURP");
5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // should only get one notification even if register multiple times
5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("... trying multiple registration");
5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l1);
5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l1);
5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l1);
5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l2);
5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.registerObject("Foo", "en_FOO");
5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("... registered foo");
5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // since in a separate thread, we can callback and not deadlock
5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ServiceListener l3 = new ServiceListener() {
5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            private int n;
5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public void serviceChanged(ICUService s) {
5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("listener 3 report " + n++ + " service changed...");
5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (s.get("en_BOINK") == null) { // don't recurse on ourselves!!!
5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("registering boink...");
5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                s.registerObject("boink", "en_BOINK");
5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.addListener(l3);
5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("registering boo...");
5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ls.registerObject("Boo", "en_BOO");
5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("...done");
5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Thread.sleep(100);
5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        catch (InterruptedException e) {
5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class TestLocaleKeyFactory extends LocaleKeyFactory {
5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected final Set ids;
5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected final String factoryID;
5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public TestLocaleKeyFactory(String[] ids, String factoryID) {
5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(VISIBLE, factoryID);
5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.ids = Collections.unmodifiableSet(new HashSet(Arrays.asList(ids)));
5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.factoryID = factoryID + ": ";
5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected Object handleCreate(ULocale loc, int kind, ICUService service) {
5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return factoryID + loc.toString();
5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected Set getSupportedIDs() {
5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ids;
5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      // Disallow hiding for now since it causes gnarly problems, like
5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      // how do you localize the hidden (but still exported) names.
5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      static class TestHidingFactory implements ICUService.Factory {
5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      protected final String[] ids;
5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      protected final String factoryID;
5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      public TestHidingFactory(String[] ids) {
5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      this(ids, "Hiding");
5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      public TestHidingFactory(String[] ids, String factoryID) {
5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      this.ids = (String[])ids.clone();
5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      if (factoryID == null || factoryID.length() == 0) {
5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      this.factoryID = "";
5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      } else {
5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      this.factoryID = factoryID + ": ";
5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      public Object create(Key key, ICUService service) {
5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      for (int i = 0; i < ids.length; ++i) {
5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      if (LocaleUtility.isFallbackOf(ids[i], key.currentID())) {
5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      return factoryID + key.canonicalID();
5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      return null;
5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      public void updateVisibleIDs(Map result) {
5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      for (int i = 0; i < ids.length; ++i) {
5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      String id = ids[i];
5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      Iterator iter = result.keySet().iterator();
5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      while (iter.hasNext()) {
5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      if (LocaleUtility.isFallbackOf(id, (String)iter.next())) {
5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      iter.remove();
5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      result.put(id, this);
6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      public String getDisplayName(String id, ULocale locale) {
6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      return factoryID + new ULocale(id).getDisplayName(locale);
6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class CalifornioLanguageFactory extends ICUResourceBundleFactory {
6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static String californio = "en_US_CA";
6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static String valley = californio + "_VALLEY";
6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static String surfer = californio + "_SURFER";
6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static String geek = californio + "_GEEK";
6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public static Set supportedIDs;
6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        static {
6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            HashSet result = new HashSet();
6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.addAll(ICUResourceBundle.getAvailableLocaleNameSet());
6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.add(californio);
6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.add(valley);
6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.add(surfer);
6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.add(geek);
6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            supportedIDs = Collections.unmodifiableSet(result);
6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Set getSupportedIDs() {
6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return supportedIDs;
6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getDisplayName(String id, ULocale locale) {
6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String prefix = "";
6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String suffix = "";
6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String ls = locale.toString();
6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (LocaleUtility.isFallbackOf(californio, ls)) {
6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (ls.equalsIgnoreCase(valley)) {
6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prefix = "Like, you know, it's so totally ";
6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (ls.equalsIgnoreCase(surfer)) {
6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prefix = "Dude, its ";
6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (ls.equalsIgnoreCase(geek)) {
6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prefix = "I'd estimate it's approximately ";
6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prefix = "Huh?  Maybe ";
6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (LocaleUtility.isFallbackOf(californio, id)) {
6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (id.equalsIgnoreCase(valley)) {
6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            suffix = "like the Valley, you know?  Let's go to the mall!";
6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (id.equalsIgnoreCase(surfer)) {
6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            suffix = "time to hit those gnarly waves, Dude!!!";
6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (id.equalsIgnoreCase(geek)) {
6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            suffix = "all systems go.  T-Minus 9, 8, 7...";
6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            suffix = "No Habla Englais";
6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        suffix = super.getDisplayName(id, locale);
6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return prefix + suffix;
6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestLocale() {
6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICULocaleService service = new ICULocaleService("test locale");
6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject("root", ULocale.ROOT);
6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject("german", "de");
6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject("german_Germany", ULocale.GERMANY);
6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject("japanese", "ja");
6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerObject("japanese_Japan", ULocale.JAPAN);
6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Object target = service.get("de_US");
6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test de_US", "german", target);
6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale de = new ULocale("de");
6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale de_US = new ULocale("de_US");
6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US);
6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test de_US 2", "german", target);
6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, LocaleKey.KIND_ANY);
6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test de_US 3", "german", target);
6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, 1234);
6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test de_US 4", "german", target);
6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale[] actualReturn = new ULocale[1];
6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, actualReturn);
6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US 5", "german", target);
6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US 6", actualReturn[0], de);
6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        actualReturn[0] = null;
6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, LocaleKey.KIND_ANY, actualReturn);
6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US 7", actualReturn[0], de);
6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        actualReturn[0] = null;
6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, 1234, actualReturn);
6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test de_US 8", "german", target);
6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US 9", actualReturn[0], de);
7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerObject("one/de_US", de_US, 1);
7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerObject("two/de_US", de_US, 2);
7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, 1);
7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US kind 1", "one/de_US", target);
7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US, 2);
7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US kind 2", "two/de_US", target);
7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(de_US);
7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("test de_US kind 3", "german", target);
7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en", null, 1234);
7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey prefix: " + lkey.prefix());
7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey descriptor: " + lkey.currentDescriptor());
7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey current locale: " + lkey.currentLocale());
7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        lkey.fallback();
7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey descriptor 2: " + lkey.currentDescriptor());
7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        lkey.fallback();
7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey descriptor 3: " + lkey.currentDescriptor());
7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    target = service.get("za_PPP");
7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test zappp", "root", target);
7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ULocale loc = ULocale.getDefault();
7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ULocale.setDefault(ULocale.JAPANESE);
7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    target = service.get("za_PPP");
7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test with ja locale", "japanese", target);
7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Set ids = service.getVisibleIDs();
7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    for (Iterator iter = ids.iterator(); iter.hasNext();) {
7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("id: " + iter.next());
7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ULocale.setDefault(loc);
7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ids = service.getVisibleIDs();
7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    for (Iterator iter = ids.iterator(); iter.hasNext();) {
7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("id: " + iter.next());
7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    target = service.get("za_PPP");
7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    confirmEqual("test with en locale", "root", target);
7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale[] locales = service.getAvailableULocales();
7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmIdentical("test available locales", locales.length, 6);
7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("locales: ");
7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < locales.length; ++i) {
7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("\n  [" + i + "] " + locales[i]);
7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(" ");
7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(new ICUResourceBundleFactory());
7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        target = service.get(ULocale.JAPAN);
7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int n = 0;
7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            List factories = service.factories();
7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Iterator iter = factories.iterator();
7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (iter.hasNext()) {
7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("[" + n++ + "] " + iter.next());
7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // list only the english display names for es, in reverse order
7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // since we're using locale keys, we should get all and only the es locales
7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // hmmm, the default toString function doesn't print in sorted order for TreeMap
7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            SortedMap map = service.getDisplayNames(ULocale.US,
7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            new Comparator() {
7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                public int compare(Object lhs, Object rhs) {
7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                return -String.CASE_INSENSITIVE_ORDER.compare((String)lhs, (String)rhs);
7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            },
7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            "es");
7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("es display names in reverse order " + map);
7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestWrapFactory() {
7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        final String greeting = "Hello There";
7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        final String greetingID = "greeting";
7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ICUService service = new ICUService("wrap");
7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerObject(greeting, greetingID);
7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("test one: " + service.get(greetingID));
7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        class WrapFactory implements Factory {
7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public Object create(Key key, ICUService serviceArg) {
7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (key.currentID().equals(greetingID)) {
7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    Object previous = serviceArg.getKey(key, null, this);
7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return "A different greeting: \"" + previous + "\"";
7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public void updateVisibleIDs(Map result) {
8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.put("greeting", this);
8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public String getDisplayName(String id, ULocale locale) {
8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return "wrap '" + id + "'";
8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(new WrapFactory());
8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        confirmEqual("wrap test: ", service.get(greetingID), "A different greeting: \"" + greeting + "\"");
8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // misc coverage tests
8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestCoverage() {
8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Key
8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Key key = new Key("foobar");
8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("ID: " + key.id());
8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("canonicalID: " + key.canonicalID());
8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("currentID: " + key.currentID());
8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("has fallback: " + key.fallback());
8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // SimpleFactory
8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    Object obj = new Object();
8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    SimpleFactory sf = new SimpleFactory(obj, "object");
8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sf = new SimpleFactory(null, null);
8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("didn't throw exception");
8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (IllegalArgumentException e) {
8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("OK: " + e.getMessage());
8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("threw wrong exception" + e);
8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln(sf.getDisplayName("object", null));
8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ICUService
8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICUService service = new ICUService();
8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    service.registerFactory(sf);
8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.get(null, null);
8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("didn't throw exception");
8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (NullPointerException e) {
8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("OK: " + e.getMessage());
8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      catch (Exception e) {
8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      errln("threw wrong exception" + e);
8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      }
8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        */
8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.registerFactory(null);
8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("didn't throw exception");
8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (NullPointerException e) {
8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("OK: " + e.getMessage());
8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("threw wrong exception" + e);
8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        service.unregisterFactory(null);
8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("didn't throw exception");
8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (NullPointerException e) {
8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("OK: " + e.getMessage());
8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("threw wrong exception" + e);
8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("object is: " + service.get("object"));
8767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("stats: " + service.stats());
8787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ICURWLock
8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICURWLock rwlock = new ICURWLock();
8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.resetStats();
8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.acquireRead();
8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.releaseRead();
8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.acquireWrite();
8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.releaseWrite();
8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("stats: " + rwlock.getStats());
8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("stats: " + rwlock.clearStats());
8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.acquireRead();
8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.releaseRead();
8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.acquireWrite();
8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    rwlock.releaseWrite();
8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("stats: " + rwlock.getStats());
8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        rwlock.releaseRead();
8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("no error thrown");
9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("OK: " + e.getMessage());
9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        rwlock.releaseWrite();
9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("no error thrown");
9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("OK: " + e.getMessage());
9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // ICULocaleService
9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // LocaleKey
9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // LocaleKey lkey = LocaleKey.create("en_US", "ja_JP");
9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // lkey = LocaleKey.create(null, null);
9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en_US", "ja_JP");
9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey: " + lkey);
9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        lkey = LocaleKey.createWithCanonicalFallback(null, null);
9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkey from null,null: " + lkey);
9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // LocaleKeyFactory
9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    LocaleKeyFactory lkf = new LKFSubclass(false);
9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("lkf: " + lkf);
9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("obj: " + lkf.create(lkey, null));
9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln(lkf.getDisplayName("foo", null));
9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln(lkf.getDisplayName("bar", null));
9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    lkf.updateVisibleIDs(new HashMap());
9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    LocaleKeyFactory invisibleLKF = new LKFSubclass(false);
9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("obj: " + invisibleLKF.create(lkey, null));
9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln(invisibleLKF.getDisplayName("foo", null));
9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln(invisibleLKF.getDisplayName("bar", null));
9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    invisibleLKF.updateVisibleIDs(new HashMap());
9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ResourceBundleFactory
9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICUResourceBundleFactory rbf = new ICUResourceBundleFactory();
9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    logln("RB: " + rbf.create(lkey, null));
9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ICUNotifier
9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ICUNotifier nf = new ICUNSubclass();
9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        nf.addListener(null);
9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("added null listener");
9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (NullPointerException e) {
9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(e.getMessage());
9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("got wrong exception");
9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        nf.addListener(new WrongListener());
9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("added wrong listener");
9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (IllegalStateException e) {
9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(e.getMessage());
9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("got wrong exception");
9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    try {
9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        nf.removeListener(null);
9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("removed null listener");
9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (NullPointerException e) {
9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln(e.getMessage());
9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    catch (Exception e) {
9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        errln("got wrong exception");
9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    nf.removeListener(new MyListener());
9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    nf.notifyChanged();
9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    nf.addListener(new MyListener());
9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    nf.removeListener(new MyListener());
9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class MyListener implements EventListener {
9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class WrongListener implements EventListener {
9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class ICUNSubclass extends ICUNotifier {
9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public boolean acceptsListener(EventListener l) {
9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return l instanceof MyListener;
9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // not used, just needed to implement abstract base
9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public void notifyListener(EventListener l) {
9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class LKFSubclass extends LocaleKeyFactory {
10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    LKFSubclass(boolean visible) {
10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super(visible ? VISIBLE : INVISIBLE);
10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected Set getSupportedIDs() {
10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return Collections.EMPTY_SET;
10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
1010