| package com.ibm.icu.dev.test.util; |
| |
| import com.ibm.icu.dev.test.TestFmwk; |
| import com.ibm.icu.impl.ICUService; |
| import com.ibm.icu.impl.ICUService.Factory; |
| import com.ibm.icu.impl.ICUService.Key; |
| import com.ibm.icu.impl.ICUService.ServiceListener; |
| import com.ibm.icu.impl.LocaleUtility; |
| import com.ibm.icu.impl.ICULocaleData; |
| import com.ibm.icu.impl.ICULocaleService; |
| import com.ibm.icu.impl.ICULocaleService.LocaleKey; |
| import com.ibm.icu.impl.ICULocaleService.MultipleKeyFactory; |
| import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory; |
| import java.util.Arrays; |
| import java.util.EventListener; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.ResourceBundle; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| public class ICUServiceTest extends TestFmwk |
| { |
| public static void main(String[] args) throws Exception { |
| ICUServiceTest test = new ICUServiceTest(); |
| test.run(args); |
| } |
| |
| private String lrmsg(String message, Object lhs, Object rhs) { |
| return message + " lhs: " + lhs + " rhs: " + rhs; |
| } |
| |
| public void confirmBoolean(String message, boolean val) { |
| logln(message, val, !val); |
| } |
| |
| public void confirmEqual(String message, Object lhs, Object rhs) { |
| logln(lrmsg(message, lhs, rhs), lhs == null ? rhs == null : lhs.equals(rhs)); |
| } |
| |
| public void confirmIdentical(String message, Object lhs, Object rhs) { |
| logln(lrmsg(message, lhs, rhs), lhs == rhs); |
| } |
| |
| public void confirmIdentical(String message, int lhs, int rhs) { |
| logln(message + " lhs: " + lhs + " rhs: " + rhs, lhs == rhs); |
| } |
| |
| // use locale keys |
| static final class TestService extends ICUService { |
| protected Key createKey(String id) { |
| return LocaleKey.createWithCanonicalFallback(id, null); // no fallback locale |
| } |
| } |
| |
| public void testAPI() { |
| // create a service using locale keys, |
| ICUService service = new TestService(); |
| |
| // register an object with one locale, |
| // search for an object with a more specific locale |
| // should return the original object |
| Integer singleton0 = new Integer(0); |
| service.registerObject(singleton0, "en_US"); |
| Object result = service.get("en_US_FOO"); |
| confirmIdentical("1) en_US_FOO -> en_US", result, singleton0); |
| |
| // register a new object with the more specific locale |
| // search for an object with that locale |
| // should return the new object |
| Integer singleton1 = new Integer(1); |
| service.registerObject(singleton1, "en_US_FOO"); |
| result = service.get("en_US_FOO"); |
| confirmIdentical("2) en_US_FOO -> en_US_FOO", result, singleton1); |
| |
| // search for an object that falls back to the first registered locale |
| result = service.get("en_US_BAR"); |
| confirmIdentical("3) en_US_BAR -> en_US", result, singleton0); |
| |
| // get a list of the factories, should be two |
| List factories = service.factories(); |
| confirmIdentical("4) factory size", factories.size(), 2); |
| |
| // register a new object with yet another locale |
| // original factory list is unchanged |
| Integer singleton2 = new Integer(2); |
| service.registerObject(singleton2, "en"); |
| confirmIdentical("5) factory size", factories.size(), 2); |
| |
| // search for an object with the new locale |
| // stack of factories is now en, en_US_FOO, en_US |
| // search for en_US should still find en_US object |
| result = service.get("en_US_BAR"); |
| confirmIdentical("6) en_US_BAR -> en_US", result, singleton0); |
| |
| // register a new object with an old id, should hide earlier factory using this id, but leave it there |
| Integer singleton3 = new Integer(3); |
| service.registerObject(singleton3, "en_US"); |
| factories = service.factories(); |
| confirmIdentical("9) factory size", factories.size(), 4); |
| |
| // should get data from that new factory |
| result = service.get("en_US_BAR"); |
| confirmIdentical("10) en_US_BAR -> (3)", result, singleton3); |
| |
| // remove new factory |
| // should have fewer factories again |
| service.unregisterFactory((Factory)factories.get(0)); |
| factories = service.factories(); |
| confirmIdentical("11) factory size", factories.size(), 3); |
| |
| // should get original data again after remove factory |
| result = service.get("en_US_BAR"); |
| confirmIdentical("12) en_US_BAR -> 0", result, singleton0); |
| |
| // shouldn't find unregistered ids |
| result = service.get("foo"); |
| confirmIdentical("13) foo -> null", result, null); |
| |
| // should find non-canonical strings |
| String[] resultID = new String[1]; |
| result = service.get("EN_us_fOo", resultID); |
| confirmEqual("14) find non-canonical", resultID[0], "en_US_FOO"); |
| |
| // should be able to register non-canonical strings and get them canonicalized |
| service.registerObject(singleton3, "eN_ca_dUde"); |
| result = service.get("En_Ca_DuDe", resultID); |
| confirmEqual("15) register non-canonical", resultID[0], "en_CA_DUDE"); |
| |
| // should be able to register invisible factories, these will not |
| // be visible by default, but if you know the secret password you |
| // can still access these services... |
| Integer singleton4 = new Integer(4); |
| service.registerObject(singleton4, "en_US_BAR", false); |
| result = service.get("en_US_BAR"); |
| confirmIdentical("17) get invisible", result, singleton4); |
| |
| // should not be able to locate invisible services |
| Set ids = service.getVisibleIDs(); |
| confirmBoolean("18) find invisible", !ids.contains("en_US_BAR")); |
| |
| service.reset(); |
| // an anonymous factory than handles all ids |
| { |
| Factory factory = new Factory() { |
| public Object create(Key key) { |
| return LocaleUtility.getLocaleFromName(key.currentID()); |
| } |
| |
| public void updateVisibleIDs(Map result) { |
| } |
| |
| public String getDisplayName(String id, Locale l) { |
| return null; |
| } |
| }; |
| service.registerFactory(factory); |
| |
| // anonymous factory will still handle the id |
| result = service.get(Locale.US.toString()); |
| confirmEqual("21) locale", result, Locale.US); |
| |
| // still normalizes id |
| result = service.get("EN_US_BAR"); |
| confirmEqual("22) locale", result, LocaleUtility.getLocaleFromName("en_US_BAR")); |
| |
| // we can override for particular ids |
| service.registerObject(singleton3, "en_US_BAR"); |
| result = service.get("en_US_BAR"); |
| confirmIdentical("23) override super", result, singleton3); |
| } |
| |
| // empty service should not recognize anything |
| service.reset(); |
| result = service.get("en_US"); |
| confirmIdentical("24) empty", result, null); |
| |
| // create a custom multiple key factory |
| { |
| String[] xids = { "en_US_VALLEY_GIRL", |
| "en_US_VALLEY_BOY", |
| "en_US_SURFER_GAL", |
| "en_US_SURFER_DUDE" |
| }; |
| service.registerFactory(new TestMultipleFactory(xids)); |
| } |
| |
| // iterate over the visual ids returned by the multiple factory |
| { |
| Set vids = service.getVisibleIDs(); |
| Iterator iter = vids.iterator(); |
| int count = 0; |
| while (iter.hasNext()) { |
| ++count; |
| logln(" " + iter.next()); |
| } |
| // four visible ids |
| confirmIdentical("25) visible ids", count, 4); |
| } |
| |
| // iterate over the display names |
| { |
| Map dids = service.getDisplayNames(Locale.GERMANY); |
| Iterator iter = dids.entrySet().iterator(); |
| int count = 0; |
| while (iter.hasNext()) { |
| ++count; |
| Entry e = (Entry)iter.next(); |
| logln(" " + e.getKey() + " -- > " + e.getValue()); |
| } |
| // four display names, in german |
| confirmIdentical("26) display names", count, 4); |
| } |
| |
| // no valid display name |
| confirmIdentical("27) get display name", service.getDisplayName("en_US_VALLEY_GEEK"), null); |
| |
| { |
| String name = service.getDisplayName("en_US_SURFER_DUDE", Locale.US); |
| confirmEqual("28) get display name", name, "English (United States,SURFER,DUDE)"); |
| } |
| |
| // register another multiple factory |
| { |
| String[] xids = { |
| "en_US_SURFER_GAL", "en_US_SILICON", "en_US_SILICON_GEEK", "en_US" |
| }; |
| service.registerFactory(new TestMultipleFactory(xids, "Rad dude")); |
| } |
| |
| // this time, we have seven display names (we replaced surfer gal) |
| { |
| Map dids = service.getDisplayNames(LocaleUtility.getLocaleFromName("es")); |
| Iterator iter = dids.entrySet().iterator(); |
| int count = 0; |
| while (iter.hasNext()) { |
| ++count; |
| Entry e = (Entry)iter.next(); |
| logln(" " + e.getKey() + " -- > " + e.getValue()); |
| } |
| // seven display names, in spanish |
| confirmIdentical("29) display names", count, 7); |
| } |
| |
| // we should get the display name corresponding to the actual id |
| // returned by the id we used. |
| { |
| String[] actualID = new String[1]; |
| String id = "en_us_silicon_dude"; |
| String dude = (String)service.get(id, actualID); |
| if (dude != null) { |
| String displayName = service.getDisplayName(actualID[0], Locale.US); |
| logln("found actual: " + dude + " with display name: " + displayName); |
| confirmBoolean("30) found display name for actual", displayName != null); |
| |
| displayName = service.getDisplayName(id, Locale.US); |
| logln("found query: " + dude + " with display name: " + displayName); |
| confirmBoolean("31) found display name for query", displayName == null); |
| } else { |
| errln("30) service could not find entry for " + id); |
| } |
| |
| id = "en_US_BOZO"; |
| String bozo = (String)service.get(id, actualID); |
| if (bozo != null) { |
| String displayName = service.getDisplayName(actualID[0], Locale.US); |
| logln("found actual: " + bozo + " with display name: " + displayName); |
| confirmBoolean("32) found display name for actual", displayName != null); |
| |
| displayName = service.getDisplayName(id, Locale.US); |
| logln("found actual: " + bozo + " with display name: " + displayName); |
| confirmBoolean("33) found display name for query", displayName == null); |
| } else { |
| errln("32) service could not find entry for " + id); |
| } |
| } |
| |
| // hiding factory should obscure 'sublocales' |
| { |
| String[] xids = { |
| "en_US_VALLEY", "en_US_SILICON" |
| }; |
| service.registerFactory(new TestHidingFactory(xids)); |
| } |
| |
| { |
| Map dids = service.getDisplayNames(); |
| Iterator iter = dids.entrySet().iterator(); |
| int count = 0; |
| while (iter.hasNext()) { |
| ++count; |
| Entry e = (Entry)iter.next(); |
| logln(" " + e.getKey() + " -- > " + e.getValue()); |
| } |
| confirmIdentical("31 hiding factory", count, 5); |
| } |
| |
| { |
| Set xids = service.getVisibleIDs(); |
| Iterator iter = xids.iterator(); |
| while (iter.hasNext()) { |
| String xid = (String)iter.next(); |
| logln(xid + "? " + service.get(xid)); |
| } |
| |
| logln("valleygirl? " + service.get("en_US_VALLEY_GIRL")); |
| logln("valleyboy? " + service.get("en_US_VALLEY_BOY")); |
| logln("valleydude? " + service.get("en_US_VALLEY_DUDE")); |
| logln("surfergirl? " + service.get("en_US_SURFER_GIRL")); |
| } |
| |
| // resource bundle factory. |
| service.reset(); |
| service.registerFactory(new ICUResourceBundleFactory("Countries;Languages", true)); |
| |
| // list all of the resources that really define Countries;Languages |
| // this takes a long time to build the visible id list |
| { |
| Set xids = service.getVisibleIDs(); |
| StringBuffer buf = new StringBuffer("{"); |
| boolean notfirst = false; |
| Iterator iter = xids.iterator(); |
| while (iter.hasNext()) { |
| String xid = (String)iter.next(); |
| if (notfirst) { |
| buf.append(", "); |
| } else { |
| notfirst = true; |
| } |
| buf.append(xid); |
| } |
| buf.append("}"); |
| logln(buf.toString()); |
| } |
| |
| // get all the display names of these resources |
| // this should be fast since the display names were cached. |
| { |
| Map names = service.getDisplayNames(LocaleUtility.getLocaleFromName("de_DE")); |
| StringBuffer buf = new StringBuffer("{"); |
| Iterator iter = names.entrySet().iterator(); |
| while (iter.hasNext()) { |
| Entry e = (Entry)iter.next(); |
| String name = (String)e.getKey(); |
| String id = (String)e.getValue(); |
| buf.append("\n " + name + " --> " + id); |
| } |
| buf.append("\n}"); |
| logln(buf.toString()); |
| } |
| |
| service.registerFactory(new CalifornioLanguageFactory()); |
| // get all the display names of these resources |
| { |
| Map names = service.getDisplayNames(LocaleUtility.getLocaleFromName("en_US_CA_SURFER")); |
| StringBuffer buf = new StringBuffer("{"); |
| Iterator iter = names.entrySet().iterator(); |
| while (iter.hasNext()) { |
| Entry e = (Entry)iter.next(); |
| String name = (String)e.getKey(); |
| String id = (String)e.getValue(); |
| buf.append("\n " + name + " --> " + id); |
| } |
| buf.append("\n}"); |
| logln(buf.toString()); |
| } |
| |
| // test notification |
| // simple registration |
| { |
| ICULocaleService ls = new ICULocaleService(); |
| ServiceListener l1 = new ServiceListener() { |
| private int n; |
| public void serviceChanged(ICUService s) { |
| logln("listener 1 report " + n++ + " service changed: " + s); |
| } |
| }; |
| ls.addListener(l1); |
| ServiceListener l2 = new ServiceListener() { |
| private int n; |
| public void serviceChanged(ICUService s) { |
| logln("listener 2 report " + n++ + " service changed: " + s); |
| } |
| }; |
| ls.addListener(l2); |
| logln("registering foo... "); |
| ls.registerObject("Foo", "en_FOO"); |
| logln("registering bar... "); |
| ls.registerObject("Bar", "en_BAR"); |
| logln("getting foo..."); |
| logln((String)ls.get("en_FOO")); |
| logln("removing listener 2..."); |
| ls.removeListener(l2); |
| logln("registering baz..."); |
| ls.registerObject("Baz", "en_BAZ"); |
| logln("removing listener 1"); |
| ls.removeListener(l1); |
| logln("registering burp..."); |
| ls.registerObject("Burp", "en_BURP"); |
| |
| // should only get one notification even if register multiple times |
| logln("... trying multiple registration"); |
| ls.addListener(l1); |
| ls.addListener(l1); |
| ls.addListener(l1); |
| ls.addListener(l2); |
| ls.registerObject("Foo", "en_FOO"); |
| logln("... registered foo"); |
| |
| // since in a separate thread, we can callback and not deadlock |
| ServiceListener l3 = new ServiceListener() { |
| private int n; |
| public void serviceChanged(ICUService s) { |
| logln("listener 3 report " + n++ + " service changed..."); |
| if (s.get("en_BOINK") == null) { // don't recurse on ourselves!!! |
| logln("registering boink..."); |
| s.registerObject("boink", "en_BOINK"); |
| } |
| } |
| }; |
| ls.addListener(l3); |
| logln("registering boo..."); |
| ls.registerObject("Boo", "en_BOO"); |
| logln("...done"); |
| |
| try { |
| Thread.sleep(100); |
| } |
| catch (InterruptedException e) { |
| } |
| } |
| } |
| |
| |
| static class TestMultipleFactory extends MultipleKeyFactory { |
| protected final String[] ids; |
| protected final String factoryID; |
| |
| public TestMultipleFactory(String[] ids) { |
| this(ids, ""); |
| } |
| |
| public TestMultipleFactory(String[] ids, String factoryID) { |
| this.ids = (String[])ids.clone(); |
| |
| if (factoryID == null || factoryID.length() == 0) { |
| this.factoryID = ""; |
| } else { |
| this.factoryID = factoryID + ": "; |
| } |
| } |
| |
| protected Object handleCreate(Key key) { |
| for (int i = 0; i < ids.length; ++i) { |
| if (key.currentID().equalsIgnoreCase(ids[i])) { |
| return factoryID + key.canonicalID(); |
| } |
| } |
| return null; |
| } |
| |
| protected void handleUpdateVisibleIDs(Set result) { |
| for (int i = 0; i < ids.length; ++i) { |
| result.add(ids[i]); |
| } |
| } |
| protected String handleGetDisplayName(String id, Locale locale) { |
| return factoryID + LocaleUtility.getLocaleFromName(id).getDisplayName(locale); |
| } |
| } |
| |
| static class TestHidingFactory implements ICUService.Factory { |
| protected final String[] ids; |
| protected final String factoryID; |
| |
| public TestHidingFactory(String[] ids) { |
| this(ids, "Hiding"); |
| } |
| |
| public TestHidingFactory(String[] ids, String factoryID) { |
| this.ids = (String[])ids.clone(); |
| |
| if (factoryID == null || factoryID.length() == 0) { |
| this.factoryID = ""; |
| } else { |
| this.factoryID = factoryID + ": "; |
| } |
| } |
| |
| public Object create(Key key) { |
| for (int i = 0; i < ids.length; ++i) { |
| if (LocaleUtility.isFallbackOf(ids[i], key.currentID())) { |
| return factoryID + key.canonicalID(); |
| } |
| } |
| return null; |
| } |
| |
| public void updateVisibleIDs(Map result) { |
| for (int i = 0; i < ids.length; ++i) { |
| String id = ids[i]; |
| Iterator iter = result.keySet().iterator(); |
| while (iter.hasNext()) { |
| if (LocaleUtility.isFallbackOf(id, (String)iter.next())) { |
| iter.remove(); |
| } |
| } |
| result.put(id, this); |
| } |
| } |
| |
| public String getDisplayName(String id, Locale locale) { |
| return factoryID + LocaleUtility.getLocaleFromName(id).getDisplayName(locale); |
| } |
| } |
| |
| static class CalifornioLanguageFactory extends ICUResourceBundleFactory { |
| CalifornioLanguageFactory() { |
| super("Countries;Languages", true); |
| } |
| |
| private static String californio = "en_US_CA"; |
| private static String valley = californio + "_VALLEY"; |
| private static String surfer = californio + "_SURFER"; |
| private static String geek = californio + "_GEEK"; |
| |
| public void handleUpdateVisibleIDs(Set result) { |
| super.handleUpdateVisibleIDs(result); |
| |
| result.add(californio); |
| result.add(valley); |
| result.add(surfer); |
| result.add(geek); |
| } |
| |
| protected String handleGetDisplayName(String id, Locale locale) { |
| String prefix = ""; |
| String suffix = ""; |
| String ls = locale.toString(); |
| if (LocaleUtility.isFallbackOf(californio, ls)) { |
| if (ls.equalsIgnoreCase(valley)) { |
| prefix = "Like, you know, it's so totally "; |
| } else if (ls.equalsIgnoreCase(surfer)) { |
| prefix = "Dude, its "; |
| } else if (ls.equalsIgnoreCase(geek)) { |
| prefix = "I'd estimate it's approximately "; |
| } else { |
| prefix = "Huh? Maybe "; |
| } |
| } |
| if (LocaleUtility.isFallbackOf(californio, id)) { |
| if (id.equalsIgnoreCase(valley)) { |
| suffix = "like the Valley, you know? Let's go to the mall!"; |
| } else if (id.equalsIgnoreCase(surfer)) { |
| suffix = "time to hit those gnarly waves, Dude!!!"; |
| } else if (id.equalsIgnoreCase(geek)) { |
| suffix = "all systems go. T-Minus 9, 8, 7..."; |
| } else { |
| suffix = "No Habla Englais"; |
| } |
| } else { |
| suffix = super.handleGetDisplayName(id, locale); |
| } |
| |
| return prefix + suffix; |
| } |
| } |
| |
| public void TestLocale() { |
| ICULocaleService service = new ICULocaleService(); |
| service.registerObject("root", ""); |
| service.registerObject("german", "de"); |
| service.registerObject("german_Germany", "de_DE"); |
| service.registerObject("japanese", "ja"); |
| service.registerObject("japanese_Japan", "ja_JP"); |
| |
| Object target = service.get("de_US"); |
| confirmEqual("test de_US", "german", target); |
| |
| target = service.get("za_PPP"); |
| confirmEqual("test zappp", "root", target); |
| |
| Locale loc = Locale.getDefault(); |
| Locale.setDefault(Locale.JAPANESE); |
| target = service.get("za_PPP"); |
| confirmEqual("test with ja locale", "japanese", target); |
| |
| Set ids = service.getVisibleIDs(); |
| for (Iterator iter = ids.iterator(); iter.hasNext();) { |
| logln("id: " + iter.next()); |
| } |
| |
| Locale.setDefault(loc); |
| ids = service.getVisibleIDs(); |
| for (Iterator iter = ids.iterator(); iter.hasNext();) { |
| logln("id: " + iter.next()); |
| } |
| |
| target = service.get("za_PPP"); |
| confirmEqual("test with en locale", "root", target); |
| } |
| } |