/**
 *******************************************************************************
 * Copyright (C) 2001-2004, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.util;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.ICUNotifier;
import com.ibm.icu.impl.ICURWLock;
import com.ibm.icu.impl.ICUResourceBundle;
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.ICUService.SimpleFactory;
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.LocaleKeyFactory;
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
import com.ibm.icu.text.Collator;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;

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) {
	msg(message, val ? LOG : ERR, !val, true);
    }

    public void confirmEqual(String message, Object lhs, Object rhs) {
        msg(lrmsg(message, lhs, rhs), (lhs == null ? rhs == null : lhs.equals(rhs)) ? LOG : ERR, true, true);
    }

    public void confirmIdentical(String message, Object lhs, Object rhs) {
	msg(lrmsg(message, lhs, rhs), lhs == rhs ? LOG : ERR, true, true);
    }

    public void confirmIdentical(String message, int lhs, int rhs) {
	msg(message + " lhs: " + lhs + " rhs: " + rhs, lhs == rhs ? LOG : ERR, true, true);
    }

    /**
     * Convenience override of getDisplayNames(Locale, Comparator, String) that
     * uses the current default Locale as the locale, the default collator for
     * the locale as the comparator to sort the display names, and null for
     * the matchID.
     */
    public SortedMap getDisplayNames(ICUService service) {
        Locale locale = Locale.getDefault();
        Collator col = Collator.getInstance(locale);
        return service.getDisplayNames(locale, col, null);
    }

    /**
     * Convenience override of getDisplayNames(Locale, Comparator, String) that
     * uses the default collator for the locale as the comparator to
     * sort the display names, and null for the matchID.
     */
    public SortedMap getDisplayNames(ICUService service, Locale locale) {
        Collator col = Collator.getInstance(locale);
        return service.getDisplayNames(locale, col, null);
    }
    /**
     * Convenience override of getDisplayNames(Locale, Comparator, String) that
     * uses the default collator for the locale as the comparator to
     * sort the display names.
     */
    public SortedMap getDisplayNames(ICUService service, Locale locale, String matchID) {
        Collator col = Collator.getInstance(locale);
        return service.getDisplayNames(locale, col, matchID);
    }

    // use locale keys
    static final class TestService extends ICUService {
        public TestService() {
            super("Test Service");
        }

	public 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();

        logln("service name:" + service.getName());

	// 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, ICUService service) {
			return LocaleUtility.getLocaleFromName(key.currentID());
		    }

                    ///CLOVER:OFF
		    public void updateVisibleIDs(Map result) {
		    }
                    ///CLOVER:ON

                    ///CLOVER:OFF
		    public String getDisplayName(String id, Locale l) {
			return null;
		    }
                    ///CLOVER:ON
		};
	    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 TestLocaleKeyFactory(xids, "Later"));
	}

	// 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;
                String id = (String)iter.next();
		logln("  " + id + " --> " + service.get(id));
	    }
	    // four visible ids
	    confirmIdentical("25) visible ids", count, 4);
	}

	// iterate over the display names
	{
	    Map dids = getDisplayNames(service,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", "en_US_SURFER_GAL", "en_US_SILICON", "en_US_SILICON_GEEK"
	    };
	    service.registerFactory(new TestLocaleKeyFactory(xids, "Rad dude"));
	}

	// this time, we have seven display names
        // Rad dude's surfer gal 'replaces' later's surfer gal
	{
	    Map dids = getDisplayNames(service);
	    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_surfer_gal";
	    String gal = (String)service.get(id, actualID);
	    if (gal != null) {
                logln("actual id: " + actualID[0]);
		String displayName = service.getDisplayName(actualID[0], Locale.US);
		logln("found actual: " + gal + " with display name: " + displayName);
		confirmBoolean("30) found display name for actual", displayName != null);

		displayName = service.getDisplayName(id, Locale.US);
		logln("found query: " + gal + " with display name: " + displayName);
		// this is no longer a bug, we want to return display names for anything
		// that a factory handles.  since we handle it, we should return a display
		// name.  see jb3549
		// confirmBoolean("31) found display name for query", displayName == null);
	    } else {
		errln("30) service could not find entry for " + id);
	    }

            // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
	    id = "en_US_SURFER_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);
		// see above and jb3549
		// confirmBoolean("33) found display name for query", displayName == null);
	    } else {
		errln("32) service could not find entry for " + id);
	    }

            confirmBoolean("34) is default ", !service.isDefault());
	}

        /*
        // disallow hiding for now

	// hiding factory should obscure 'sublocales'
	{
	    String[] xids = {
		"en_US_VALLEY", "en_US_SILICON"
	    };
	    service.registerFactory(new TestHidingFactory(xids, "hiding"));
	}

	{
	    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("35) 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());

	// list all of the resources 
	{
            logln("all visible ids: " + service.getVisibleIDs());
            /*
	    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());
            */
	}

        // list only the resources for es, default locale
        // since we're using the default Key, only "es" is matched
        {
            logln("visible ids for es locale: " + service.getVisibleIDs("es"));
        }

        // list only the spanish display names for es, spanish collation order
        // since we're using the default Key, only "es" is matched
        {
            logln("display names: " + getDisplayNames(service,LocaleUtility.getLocaleFromName("es"), "es"));
        }

        // list the display names in reverse order
        { 
            logln("display names in reverse order: " +
                  service.getDisplayNames(Locale.US, new Comparator() {
                          public int compare(Object lhs, Object rhs) {
                              return -String.CASE_INSENSITIVE_ORDER.compare(lhs, rhs);
                          }
                      }));
        }

	// get all the display names of these resources
	// this should be fast since the display names were cached.
	{
            logln("service display names for de_DE");
	    Map names = getDisplayNames(service,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());
	}

        CalifornioLanguageFactory califactory = new CalifornioLanguageFactory();
        service.registerFactory(califactory);
	// get all the display names of these resources
	{
            logln("californio language factory");
	    StringBuffer buf = new StringBuffer("{");
            String[] idNames = {
                CalifornioLanguageFactory.californio, CalifornioLanguageFactory.valley, CalifornioLanguageFactory.surfer, CalifornioLanguageFactory.geek
            };
            for (int i = 0; i < idNames.length; ++i) {
                String idName = idNames[i];
                buf.append("\n  --- " + idName + " ---");
                Map names = getDisplayNames(service,LocaleUtility.getLocaleFromName(idName));
                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
	{
            logln("simple registration notification");
	    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 TestLocaleKeyFactory extends LocaleKeyFactory {
	protected final Set ids;
	protected final String factoryID;

	public TestLocaleKeyFactory(String[] ids, String factoryID) {
            super(VISIBLE, factoryID);

	    this.ids = Collections.unmodifiableSet(new HashSet(Arrays.asList(ids)));
            this.factoryID = factoryID + ": ";
	}
    
	protected Object handleCreate(Locale loc, int kind, ICUService service) {
            return factoryID + loc.toString();
	}

	protected Set getSupportedIDs() {
            return ids;
	}
    }

    /*
     // Disallow hiding for now since it causes gnarly problems, like
     // how do you localize the hidden (but still exported) names.

    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, ICUService service) {
	    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 {
	public static String californio = "en_US_CA";
	public static String valley = californio + "_VALLEY";
	public static String surfer = californio + "_SURFER";
	public static String geek = californio + "_GEEK";
        public static Set supportedIDs;
        static {
            HashSet result = new HashSet();
            result.addAll(ICUResourceBundle.getAvailableLocaleNameSet());
	    result.add(californio);
	    result.add(valley);
	    result.add(surfer);
	    result.add(geek);
            supportedIDs = Collections.unmodifiableSet(result);
        }

	public Set getSupportedIDs() {
            return supportedIDs;
	}

	public String getDisplayName(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.getDisplayName(id, locale);
	    }
		
	    return prefix + suffix;
	}
    }

    public void TestLocale() {
	ICULocaleService service = new ICULocaleService("test locale");
	service.registerObject("root", "");
	service.registerObject("german", "de");
	service.registerObject("german_Germany", Locale.GERMANY);
	service.registerObject("japanese", "ja");
	service.registerObject("japanese_Japan", Locale.JAPAN);

	Object target = service.get("de_US");
	confirmEqual("test de_US", "german", target);

        Locale de = LocaleUtility.getLocaleFromName("de");
        Locale de_US = LocaleUtility.getLocaleFromName("de_US");

        target = service.get(de_US);
	confirmEqual("test de_US 2", "german", target);

        target = service.get(de_US, LocaleKey.KIND_ANY);
	confirmEqual("test de_US 3", "german", target);

        target = service.get(de_US, 1234);
	confirmEqual("test de_US 4", "german", target);

        Locale[] actualReturn = new Locale[1];
        target = service.get(de_US, actualReturn);
        confirmEqual("test de_US 5", "german", target);
        confirmEqual("test de_US 6", actualReturn[0], de);

        actualReturn[0] = null;
        target = service.get(de_US, LocaleKey.KIND_ANY, actualReturn);
        confirmEqual("test de_US 7", actualReturn[0], de);

        actualReturn[0] = null;
        target = service.get(de_US, 1234, actualReturn);
	confirmEqual("test de_US 8", "german", target);
        confirmEqual("test de_US 9", actualReturn[0], de);

        service.registerObject("one/de_US", de_US, 1);
        service.registerObject("two/de_US", de_US, 2);

        target = service.get(de_US, 1);
        confirmEqual("test de_US kind 1", "one/de_US", target);
        
        target = service.get(de_US, 2);
        confirmEqual("test de_US kind 2", "two/de_US", target);
        
        target = service.get(de_US);
        confirmEqual("test de_US kind 3", "german", target);

        LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en", null, 1234);
        logln("lkey prefix: " + lkey.prefix());
        logln("lkey descriptor: " + lkey.currentDescriptor());
        logln("lkey current locale: " + lkey.currentLocale());

        lkey.fallback();
        logln("lkey descriptor 2: " + lkey.currentDescriptor());

        lkey.fallback();
        logln("lkey descriptor 3: " + lkey.currentDescriptor());

	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);

        Locale[] locales = service.getAvailableLocales();
        confirmIdentical("test available locales", locales.length, 6);
        logln("locales: ");
        for (int i = 0; i < locales.length; ++i) {
            log("\n  [" + i + "] " + locales[i]);
        }
        logln(" ");

        service.registerFactory(new ICUResourceBundleFactory());
        target = service.get(Locale.JAPAN);

        {
            int n = 0;
            List factories = service.factories();
            Iterator iter = factories.iterator();
            while (iter.hasNext()) {
                logln("[" + n++ + "] " + iter.next());
            }
        }

        // list only the english display names for es, in reverse order
        // since we're using locale keys, we should get all and only the es locales
        // hmmm, the default toString function doesn't print in sorted order for TreeMap
        {
            SortedMap map = service.getDisplayNames(Locale.US, 
                                              new Comparator() {
                                                  public int compare(Object lhs, Object rhs) {
                                                    return -String.CASE_INSENSITIVE_ORDER.compare(lhs, rhs);
                                                  }
                                                },
                                              "es");

            logln("es display names in reverse order " + map);
        }
    }

    public void TestWrapFactory() {
        final String greeting = "Hello There";
        final String greetingID = "greeting";

        ICUService service = new ICUService("wrap");
        service.registerObject(greeting, greetingID);

        logln("test one: " + service.get(greetingID));

        class WrapFactory implements Factory {
            public Object create(Key key, ICUService service) {
                if (key.currentID().equals(greetingID)) {
                    Object previous = service.getKey(key, null, this);
                    return "A different greeting: \"" + previous + "\"";
                }
                return null;
            }

            public void updateVisibleIDs(Map result) {
                result.put("greeting", this);
            }

            public String getDisplayName(String id, Locale locale) {
                return "wrap '" + id + "'";
            }
        }
        service.registerFactory(new WrapFactory());

        confirmEqual("wrap test: ", service.get(greetingID), "A different greeting: \"" + greeting + "\"");
    }

    // misc coverage tests
    public void TestCoverage() {
	// Key
	Key key = new Key("foobar");
	logln("ID: " + key.id());
	logln("canonicalID: " + key.canonicalID());
	logln("currentID: " + key.currentID());
	logln("has fallback: " + key.fallback());

	// SimpleFactory
	Object obj = new Object();
	SimpleFactory sf = new SimpleFactory(obj, "object");
	try {
	    sf = new SimpleFactory(null, null);
	    errln("didn't throw exception");
	}
	catch (IllegalArgumentException e) {
	    logln("OK: " + e.getMessage());
	}
	catch (Exception e) {
	    errln("threw wrong exception" + e);
	}
	logln(sf.getDisplayName("object", null));

	// ICUService
	ICUService service = new ICUService();
	service.registerFactory(sf);

	try {
	    service.get(null, null);
	    errln("didn't throw exception");
	}
	catch (NullPointerException e) {
	    logln("OK: " + e.getMessage());
	}
        /*
	catch (Exception e) {
	    errln("threw wrong exception" + e);
	}
        */
	try {
	    service.registerFactory(null);
	    errln("didn't throw exception");
	}
	catch (NullPointerException e) {
	    logln("OK: " + e.getMessage());
	}
	catch (Exception e) {
	    errln("threw wrong exception" + e);
	}

	try {
	    service.unregisterFactory(null);
	    errln("didn't throw exception");
	}
	catch (NullPointerException e) {
	    logln("OK: " + e.getMessage());
	}
	catch (Exception e) {
	    errln("threw wrong exception" + e);
	}

	logln("object is: " + service.get("object"));

	logln("stats: " + service.stats());

	// ICURWLock

	ICURWLock rwlock = new ICURWLock();
	rwlock.acquireRead();
	rwlock.releaseRead();

	rwlock.acquireWrite();
	rwlock.releaseWrite();
	logln("stats: " + rwlock.getStats());
	logln("stats: " + rwlock.clearStats());
	rwlock.acquireRead();
	rwlock.releaseRead();
	rwlock.acquireWrite();
	rwlock.releaseWrite();
	logln("stats: " + rwlock.getStats());

	try {
	    rwlock.releaseRead();
	    errln("no error thrown");
	}
	catch (InternalError e) {
	    logln("OK: " + e.getMessage());
	}

	try {
	    rwlock.releaseWrite();
	    errln("no error thrown");
	}
	catch (InternalError e) {
	    logln("OK: " + e.getMessage());
	}

        // ICULocaleService

	// LocaleKey
        
	// LocaleKey lkey = LocaleKey.create("en_US", "ja_JP");
	// lkey = LocaleKey.create(null, null);
	LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en_US", "ja_JP");
        logln("lkey: " + lkey);

        lkey = LocaleKey.createWithCanonicalFallback(null, null);
        logln("lkey from null,null: " + lkey);

	// LocaleKeyFactory 
	LocaleKeyFactory lkf = new LKFSubclass(false);
        logln("lkf: " + lkf);
	logln("obj: " + lkf.create(lkey, null));
	logln(lkf.getDisplayName("foo", null));
	logln(lkf.getDisplayName("bar", null));
	lkf.updateVisibleIDs(new HashMap());

	LocaleKeyFactory invisibleLKF = new LKFSubclass(false);
	logln("obj: " + invisibleLKF.create(lkey, null));
	logln(invisibleLKF.getDisplayName("foo", null));
	logln(invisibleLKF.getDisplayName("bar", null));
	invisibleLKF.updateVisibleIDs(new HashMap());

	// ResourceBundleFactory
	ICUResourceBundleFactory rbf = new ICUResourceBundleFactory();
	logln("RB: " + rbf.create(lkey, null));

	// ICUNotifier
	ICUNotifier nf = new ICUNSubclass();
	try {
	    nf.addListener(null);
	    errln("added null listener");
	}
	catch (NullPointerException e) {
	    logln(e.getMessage());
	}
	catch (Exception e) {
	    errln("got wrong exception");
	}

	try {
	    nf.addListener(new WrongListener());
	    errln("added wrong listener");
	}
	catch (InternalError e) {
	    logln(e.getMessage());
	}
	catch (Exception e) {
	    errln("got wrong exception");
	}

	try {
	    nf.removeListener(null);
	    errln("removed null listener");
	}
	catch (NullPointerException e) {
	    logln(e.getMessage());
	}
	catch (Exception e) {
	    errln("got wrong exception");
	}

	nf.removeListener(new MyListener());
	nf.notifyChanged();
	nf.addListener(new MyListener());
	nf.removeListener(new MyListener());
    }

    static class MyListener implements EventListener {
    }

    static class WrongListener implements EventListener {
    }

    static class ICUNSubclass extends ICUNotifier {
	public boolean acceptsListener(EventListener l) {
	    return l instanceof MyListener;
	}

        // not used, just needed to implement abstract base
        ///CLOVER:OFF
	public void notifyListener(EventListener l) {
	}
        ///CLOVER:ON
    }

    static class LKFSubclass extends LocaleKeyFactory {
	LKFSubclass(boolean visible) {
	    super(visible ? VISIBLE : INVISIBLE);
	}

	protected Set getSupportedIDs() {
            return Collections.EMPTY_SET;
	}
    }
}
