/**
 *******************************************************************************
 * Copyright (C) 2001-2003, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/util/ICUServiceTest.java,v $
 * $Date: 2003/06/03 18:49:31 $
 * $Revision: 1.14 $
 *
 *******************************************************************************
 */
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.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);
		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);
		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(ICULocaleData.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;
	}
    }
}
