/**
 *******************************************************************************
 * Copyright (C) 2001-2002, 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: 2002/12/12 18:02:09 $
 * $Revision: 1.10 $
 *
 *******************************************************************************
 */
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 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.ResourceBundle;
import java.util.Set;
import java.util.SortedMap;
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 {
        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 = 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", "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 = service.getDisplayNames();
	    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: " + service.getDisplayNames(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 = 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());
	}

        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 = {
                califactory.californio, califactory.valley, califactory.surfer, califactory.geek
            };
            for (int i = 0; i < idNames.length; ++i) {
                String idName = idNames[i];
                buf.append("\n  --- " + idName + " ---");
                Map names = service.getDisplayNames(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 + "\"");
    }

    public void errln(String msg) {
        // System.out.println(msg);
        super.errln(msg);
    }

    // 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;
	}
    }
}
