// Copyright (C) 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/**
 *******************************************************************************
 * Copyright (C) 2001-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */

#include "utypeinfo.h"  // for 'typeid' to work

#include "unicode/utypes.h"

#if !UCONFIG_NO_SERVICE

#include "cmemory.h"
#include "icusvtst.h"
#include "servloc.h"
#include <stdio.h>


class MyListener : public EventListener {
};

class WrongListener : public EventListener {
};

class ICUNSubclass : public ICUNotifier {
    public:
    UBool acceptsListener(const EventListener& /*l*/) const {
        return TRUE;
        // return l instanceof MyListener;
    }

    virtual void notifyListener(EventListener& /*l*/) const {
    }
};

// This factory does nothing
class LKFSubclass0 : public LocaleKeyFactory {
public:
        LKFSubclass0()
                : LocaleKeyFactory(VISIBLE, "LKFSubclass0")
        {
        }
};

class LKFSubclass : public LocaleKeyFactory {
    Hashtable table;

    public:
    LKFSubclass(UBool visible) 
        : LocaleKeyFactory(visible ? VISIBLE : INVISIBLE, "LKFSubclass")
    {
        UErrorCode status = U_ZERO_ERROR;
        table.put("en_US", this, status);
    }

    protected:
    virtual const Hashtable* getSupportedIDs(UErrorCode &/*status*/) const {
        return &table;
    }
};

class Integer : public UObject {
    public:
    const int32_t _val;

    Integer(int32_t val) : _val(val) {
    }

    Integer(const Integer& rhs) : UObject(rhs), _val(rhs._val) {
    }
    virtual ~Integer() {
    }

    public:
    /**
     * UObject boilerplate.
     */
    static UClassID getStaticClassID() { 
        return (UClassID)&fgClassID;
    }

    virtual UClassID getDynamicClassID() const {
        return getStaticClassID();
    }

    virtual UBool operator==(const UObject& other) const 
    {
        return typeid(*this) == typeid(other) &&
            _val == ((Integer&)other)._val;
    }

    public:
    virtual UnicodeString& debug(UnicodeString& result) const {
        debugClass(result);
        result.append(" val: ");
        result.append(_val);
        return result;
    }

    virtual UnicodeString& debugClass(UnicodeString& result) const {
        return result.append("Integer");
    }

    private:
    static const char fgClassID;
};

const char Integer::fgClassID = '\0';

// use locale keys
class TestIntegerService : public ICUService {
    public:
    ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const {
        return LocaleKey::createWithCanonicalFallback(id, NULL, status); // no fallback locale
    }

    virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& status) 
    {
        Integer* i;
        if (U_SUCCESS(status) && obj && (i = dynamic_cast<Integer*>(obj)) != NULL) {
            return new SimpleFactory(i, id, visible);
        }
        return NULL;
    }

    virtual UObject* cloneInstance(UObject* instance) const {
        return instance ? new Integer(*(Integer*)instance) : NULL;
    }
};


ICUServiceTest::ICUServiceTest() {
}

ICUServiceTest::~ICUServiceTest() {
}

void 
ICUServiceTest::runIndexedTest(int32_t index, UBool exec, const char* &name,
char* /*par*/)
{
    switch (index) {
        TESTCASE(0,testAPI_One);
        TESTCASE(1,testAPI_Two);
        TESTCASE(2,testRBF);
        TESTCASE(3,testNotification);
        TESTCASE(4,testLocale);
        TESTCASE(5,testWrapFactory);
        TESTCASE(6,testCoverage);
    default: name = ""; break;
    }
}

UnicodeString append(UnicodeString& result, const UObject* obj) 
{
    char buffer[128];
    if (obj == NULL) {
        result.append("NULL");
    } else {
        const UnicodeString* s;
        const Locale* loc;
        const Integer* i;
        if ((s = dynamic_cast<const UnicodeString*>(obj)) != NULL) {
            result.append(*s);
        } else if ((loc = dynamic_cast<const Locale*>(obj)) != NULL) {
            result.append(loc->getName());
        } else if ((i = dynamic_cast<const Integer*>(obj)) != NULL) {
            sprintf(buffer, "%d", (int)i->_val);
            result.append(buffer);
        } else {
            sprintf(buffer, "%p", (const void*)obj);
            result.append(buffer);
        }
    }
    return result;
}

UnicodeString& 
ICUServiceTest::lrmsg(UnicodeString& result, const UnicodeString& message, const UObject* lhs, const UObject* rhs) const 
{
    result.append(message);
    result.append(" lhs: ");
    append(result, lhs);
    result.append(", rhs: ");
    append(result, rhs);
    return result;
}

void 
ICUServiceTest::confirmBoolean(const UnicodeString& message, UBool val)
{
    if (val) {
        logln(message);
    } else {
        errln(message);
    }
}

#if 0
void
ICUServiceTest::confirmEqual(const UnicodeString& message, const UObject* lhs, const UObject* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}
#else
void
ICUServiceTest::confirmEqual(const UnicodeString& message, const Integer* lhs, const Integer* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}

void
ICUServiceTest::confirmEqual(const UnicodeString& message, const UnicodeString* lhs, const UnicodeString* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}

void
ICUServiceTest::confirmEqual(const UnicodeString& message, const Locale* lhs, const Locale* rhs) 
{
    UBool equ = (lhs == NULL)
        ? (rhs == NULL)
        : (rhs != NULL && lhs->operator==(*rhs));

    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);

    if (equ) {
        logln(temp);
    } else {
        errln(temp);
    }
}
#endif

// use these for now
void
ICUServiceTest::confirmStringsEqual(const UnicodeString& message, const UnicodeString& lhs, const UnicodeString& rhs) 
{
    UBool equ = lhs == rhs;

    UnicodeString temp = message;
    temp.append(" lhs: ");
    temp.append(lhs);
    temp.append(" rhs: ");
    temp.append(rhs);

    if (equ) {
        logln(temp);
    } else {
        dataerrln(temp);
    }
}


void 
ICUServiceTest::confirmIdentical(const UnicodeString& message, const UObject* lhs, const UObject *rhs) 
{
    UnicodeString temp;
    lrmsg(temp, message, lhs, rhs);
    if (lhs == rhs) {
        logln(temp);
    } else {
        errln(temp);
    }
}

void
ICUServiceTest::confirmIdentical(const UnicodeString& message, int32_t lhs, int32_t rhs)  
{
    if (lhs == rhs) {
        logln(message + " lhs: " + lhs + " rhs: " + rhs);
    } else {
        errln(message + " lhs: " + lhs + " rhs: " + rhs);
    }
}

void
ICUServiceTest::msgstr(const UnicodeString& message, UObject* obj, UBool err)
{
    if (obj) {
    UnicodeString* str = (UnicodeString*)obj;
        logln(message + *str);
        delete str;
    } else if (err) {
        errln("Error " + message + "string is NULL");
    }
}

void 
ICUServiceTest::testAPI_One() 
{
    // create a service using locale keys,
    TestIntegerService service;

    // register an object with one locale, 
    // search for an object with a more specific locale
    // should return the original object
    UErrorCode status = U_ZERO_ERROR;
    Integer* singleton0 = new Integer(0);
    service.registerInstance(singleton0, "en_US", status);
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_FOO", status);
        confirmEqual("1) en_US_FOO -> en_US", result, singleton0);
        delete result;
    }

    // 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.registerInstance(singleton1, "en_US_FOO", status);
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_FOO", status);
        confirmEqual("2) en_US_FOO -> en_US_FOO", result, singleton1);
        delete result;
    }

    // search for an object that falls back to the first registered locale
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("3) en_US_BAR -> en_US", result, singleton0);
        delete result;
    }

    // get a list of the factories, should be two
    {
        confirmIdentical("4) factory size", service.countFactories(), 2);
    }

    // register a new object with yet another locale
    Integer* singleton2 = new Integer(2);
    service.registerInstance(singleton2, "en", status);
    {
        confirmIdentical("5) factory size", service.countFactories(), 3);
    }

    // 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
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("6) en_US_BAR -> en_US", result, singleton0);
        delete result;
    }

    // register a new object with an old id, should hide earlier factory using this id, but leave it there
    Integer* singleton3 = new Integer(3);
    URegistryKey s3key = service.registerInstance(singleton3, "en_US", status);
    {
        confirmIdentical("9) factory size", service.countFactories(), 4);
    }

    // should get data from that new factory
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("10) en_US_BAR -> (3)", result, singleton3);
        delete result;
    }

    // remove new factory
    // should have fewer factories again
    // singleton3 dead!
    {
        UErrorCode status = U_ZERO_ERROR;
        service.unregister(s3key, status);
        confirmIdentical("11) factory size", service.countFactories(), 3);
    }

    // should get original data again after remove factory
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("12) en_US_BAR -> (3)", result, singleton0);
        delete result;
    }

    // shouldn't find unregistered ids
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("foo", status);
        confirmIdentical("13) foo -> null", result, NULL);
        delete result;
    }

    // should find non-canonical strings
    {
        UnicodeString resultID;
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("EN_us_fOo", &resultID, status);
        confirmEqual("14a) find-non-canonical", result, singleton1);
        confirmStringsEqual("14b) find non-canonical", resultID, "en_US_FOO");
        delete result;
    }

    // should be able to register non-canonical strings and get them canonicalized
    Integer* singleton4 = new Integer(4);
    service.registerInstance(singleton4, "eN_ca_dUde", status);
    {
        UnicodeString resultID;
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("En_Ca_DuDe", &resultID, status);
        confirmEqual("15a) find-non-canonical", result, singleton4);
        confirmStringsEqual("15b) register non-canonical", resultID, "en_CA_DUDE");
        delete result;
    }

    // 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* singleton5 = new Integer(5);
    service.registerInstance(singleton5, "en_US_BAR", FALSE, status);
    {
        UErrorCode status = U_ZERO_ERROR;
        Integer* result = (Integer*)service.get("en_US_BAR", status);
        confirmEqual("17) get invisible", result, singleton5);
        delete result;
    }
    
    // should not be able to locate invisible services
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, status);
        service.getVisibleIDs(ids, status);
        UnicodeString target = "en_US_BAR";
        confirmBoolean("18) find invisible", !ids.contains(&target));
    }

    // clear factory and caches
    service.reset();
    confirmBoolean("19) is default", service.isDefault());
}

/*
 ******************************************************************
 */
class TestStringSimpleKeyService : public ICUService {
public:
 
        virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& status) 
    {
                // We could put this type check into ICUService itself, but we'd still
                // have to implement cloneInstance.  Otherwise we could just tell the service
                // what the object type is when we create it, and the default implementation
                // could handle everything for us.  Phooey.
        if (obj && dynamic_cast<UnicodeString*>(obj) != NULL) {
                        return ICUService::createSimpleFactory(obj, id, visible, status);
        }
        return NULL;
    }

    virtual UObject* cloneInstance(UObject* instance) const {
        return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL;
    }
};

class TestStringService : public ICUService {
    public:
    ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const {
        return LocaleKey::createWithCanonicalFallback(id, NULL, status); // no fallback locale
    }

  virtual ICUServiceFactory* createSimpleFactory(UObject* obj, const UnicodeString& id, UBool visible, UErrorCode& /* status */) 
    {
        UnicodeString* s;
        if (obj && (s = dynamic_cast<UnicodeString*>(obj)) != NULL) {
            return new SimpleFactory(s, id, visible);
        }
        return NULL;
    }

    virtual UObject* cloneInstance(UObject* instance) const {
        return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL;
    }
};

// this creates a string for any id, but doesn't report anything
class AnonymousStringFactory : public ICUServiceFactory
{
    public:
    virtual UObject* create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& /* status */) const {
        return new UnicodeString(key.getID());
    }

    virtual void updateVisibleIDs(Hashtable& /*result*/, UErrorCode& /*status*/) const {
        // do nothing
    }

    virtual UnicodeString& getDisplayName(const UnicodeString& /*id*/, const Locale& /*locale*/, UnicodeString& result) const {
        // do nothing
        return result;
    }

    static UClassID getStaticClassID() {
        return (UClassID)&fgClassID;
    }

    virtual UClassID getDynamicClassID() const {
        return getStaticClassID();
    }

    private:
    static const char fgClassID;
};

const char AnonymousStringFactory::fgClassID = '\0';

class TestMultipleKeyStringFactory : public ICUServiceFactory {
    UErrorCode _status;
    UVector _ids;
    UnicodeString _factoryID;

    public:
    TestMultipleKeyStringFactory(const UnicodeString ids[], int32_t count, const UnicodeString& factoryID)
        : _status(U_ZERO_ERROR)
        , _ids(uprv_deleteUObject, uhash_compareUnicodeString, count, _status)
        , _factoryID(factoryID + ": ") 
    {
        for (int i = 0; i < count; ++i) {
            _ids.addElement(new UnicodeString(ids[i]), _status);
        }
    }
  
    ~TestMultipleKeyStringFactory() {
    }

    UObject* create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const {
        if (U_FAILURE(status)) {
        return NULL;
        }
        UnicodeString temp;
        key.currentID(temp);
        if (U_SUCCESS(_status)) {
        if (_ids.contains(&temp)) {
                return new UnicodeString(_factoryID + temp);
        }
        } else {
        status = _status;
    }
        return NULL;
    }

    void updateVisibleIDs(Hashtable& result, UErrorCode& status) const {
        if (U_SUCCESS(_status)) {
            for (int32_t i = 0; i < _ids.size(); ++i) {
                result.put(*(UnicodeString*)_ids[i], (void*)this, status);
            }
        }
    }

    UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const {
        if (U_SUCCESS(_status) && _ids.contains((void*)&id)) {
            char buffer[128];
            UErrorCode status = U_ZERO_ERROR;
            int32_t len = id.extract(buffer, sizeof(buffer), NULL, status);
            if (U_SUCCESS(status)) {
                if (len == sizeof(buffer)) {
                    --len;
                }
                buffer[len] = 0;
                Locale loc = Locale::createFromName(buffer);
                loc.getDisplayName(locale, result);
                return result;
            }
        }
        result.setToBogus(); // shouldn't happen
        return result;
    }

    static UClassID getStaticClassID() {
        return (UClassID)&fgClassID;
    }

    virtual UClassID getDynamicClassID() const {
        return getStaticClassID();
    }

    private:
    static const char fgClassID;
};

const char TestMultipleKeyStringFactory::fgClassID = '\0';

void 
ICUServiceTest::testAPI_Two()
{
    UErrorCode status = U_ZERO_ERROR;
    TestStringService service;
    service.registerFactory(new AnonymousStringFactory(), status);

    // anonymous factory will still handle the id
    {
        UErrorCode status = U_ZERO_ERROR;
        const UnicodeString en_US = "en_US";
        UnicodeString* result = (UnicodeString*)service.get(en_US, status);
        confirmEqual("21) locale", result, &en_US);
        delete result;
    }

    // still normalizes id
    {
        UErrorCode status = U_ZERO_ERROR;
        const UnicodeString en_US_BAR = "en_US_BAR";
        UnicodeString resultID;
        UnicodeString* result = (UnicodeString*)service.get("EN_us_bar", &resultID, status);
        confirmEqual("22) locale", &resultID, &en_US_BAR);
        delete result;
    }

    // we can override for particular ids
    UnicodeString* singleton0 = new UnicodeString("Zero");
    service.registerInstance(singleton0, "en_US_BAR", status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get("en_US_BAR", status);
        confirmEqual("23) override super", result, singleton0);
        delete result;
    }

    // empty service should not recognize anything 
    service.reset();
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get("en_US", status);
        confirmIdentical("24) empty", result, NULL);
    }

    // create a custom multiple key factory
    {
        UnicodeString xids[] = {
            "en_US_VALLEY_GIRL", 
            "en_US_VALLEY_BOY",
            "en_US_SURFER_GAL",
            "en_US_SURFER_DUDE"
        };
        int32_t count = UPRV_LENGTHOF(xids);

        ICUServiceFactory* f = new TestMultipleKeyStringFactory(xids, count, "Later");
        service.registerFactory(f, status);
    }

    // iterate over the visual ids returned by the multiple factory
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            UnicodeString* result = (UnicodeString*)service.get(*id, status);
            if (result) {
                logln("  " + *id + " --> " + *result);
                delete result;
            } else {
                errln("could not find " + *id);
            }
        }
        // four visible ids
        confirmIdentical("25) visible ids", ids.size(), 4);
    }

    // iterate over the display names
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector names(status);
        service.getDisplayNames(names, status);
        for (int i = 0; i < names.size(); ++i) {
            const StringPair* pair = (const StringPair*)names[i];
            logln("  " + pair->displayName + " --> " + pair->id);
        }
        confirmIdentical("26) display names", names.size(), 4);
    }

    // no valid display name
    {
        UnicodeString name;
        service.getDisplayName("en_US_VALLEY_GEEK", name);
        confirmBoolean("27) get display name", name.isBogus());
    }

    {
        UnicodeString name;
        service.getDisplayName("en_US_SURFER_DUDE", name, Locale::getEnglish());
        confirmStringsEqual("28) get display name", name, "English (United States, SURFER_DUDE)");
    }

    // register another multiple factory
    {
        UnicodeString xids[] = {
            "en_US_SURFER", 
            "en_US_SURFER_GAL", 
            "en_US_SILICON", 
            "en_US_SILICON_GEEK",
        };
        int32_t count = UPRV_LENGTHOF(xids);

        ICUServiceFactory* f = new TestMultipleKeyStringFactory(xids, count, "Rad dude");
        service.registerFactory(f, status);
    }

    // this time, we have seven display names
    // Rad dude's surfer gal 'replaces' Later's surfer gal
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector names(status);
        service.getDisplayNames(names, Locale("es"), status);
        for (int i = 0; i < names.size(); ++i) {
            const StringPair* pair = (const StringPair*)names[i];
            logln("  " + pair->displayName + " --> " + pair->id);
        }
        confirmIdentical("29) display names", names.size(), 7);
    }

    // we should get the display name corresponding to the actual id
    // returned by the id we used.
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString actualID;
        UnicodeString id = "en_us_surfer_gal";
        UnicodeString* gal = (UnicodeString*)service.get(id, &actualID, status);
        if (gal != NULL) {
            UnicodeString displayName;
            logln("actual id: " + actualID);
            service.getDisplayName(actualID, displayName, Locale::getEnglish());
            logln("found actual: " + *gal + " with display name: " + displayName);
            confirmBoolean("30) found display name for actual", !displayName.isBogus());

            service.getDisplayName(id, displayName, Locale::getEnglish());
            logln("found actual: " + *gal + " with display name: " + displayName);
            confirmBoolean("31) found display name for query", displayName.isBogus());

            delete gal;
        } else {
            errln("30) service could not find entry for " + id);
        }
    }

    // this should be handled by the 'dude' factory, since it overrides en_US_SURFER.
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString actualID;
        UnicodeString id = "en_US_SURFER_BOZO";
        UnicodeString* bozo = (UnicodeString*)service.get(id, &actualID, status);
        if (bozo != NULL) {
            UnicodeString displayName;
            service.getDisplayName(actualID, displayName, Locale::getEnglish());
            logln("found actual: " + *bozo + " with display name: " + displayName);
            confirmBoolean("32) found display name for actual", !displayName.isBogus());

            service.getDisplayName(id, displayName, Locale::getEnglish());
            logln("found actual: " + *bozo + " with display name: " + displayName);
            confirmBoolean("33) found display name for query", displayName.isBogus());

            delete bozo;
        } else {
            errln("32) service could not find entry for " + id);
        }
    }

    // certainly not default...
    {
        confirmBoolean("34) is default ", !service.isDefault());
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            msgstr(*id + "? ", service.get(*id, status));
        }

        logstr("valleygirl?  ", service.get("en_US_VALLEY_GIRL", status));
        logstr("valleyboy?   ", service.get("en_US_VALLEY_BOY", status));
        logstr("valleydude?  ", service.get("en_US_VALLEY_DUDE", status));
        logstr("surfergirl?  ", service.get("en_US_SURFER_GIRL", status));
    }
}


class CalifornioLanguageFactory : public ICUResourceBundleFactory 
{
    public:
    static const char* californio; // = "en_US_CA";
    static const char* valley; // = californio ## "_VALLEY";
    static const char* surfer; // = californio ## "_SURFER";
    static const char* geek; // = californio ## "_GEEK";
    static Hashtable* supportedIDs; // = NULL;

    static void cleanup(void) {
      delete supportedIDs;
      supportedIDs = NULL;
    }

    const Hashtable* getSupportedIDs(UErrorCode& status) const 
    {
        if (supportedIDs == NULL) {
            Hashtable* table = new Hashtable();
            table->put(UnicodeString(californio), (void*)table, status);
            table->put(UnicodeString(valley), (void*)table, status);
            table->put(UnicodeString(surfer), (void*)table, status);
            table->put(UnicodeString(geek), (void*)table, status);

            // not necessarily atomic, but this is a test...
            supportedIDs = table;
        }
        return supportedIDs;
    }

    UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const 
    {
        UnicodeString prefix = "";
        UnicodeString suffix = "";
        UnicodeString ls = locale.getName();
        if (LocaleUtility::isFallbackOf(californio, ls)) {
            if (!ls.caseCompare(valley, 0)) {
                prefix = "Like, you know, it's so totally ";
            } else if (!ls.caseCompare(surfer, 0)) {
                prefix = "Dude, it's ";
            } else if (!ls.caseCompare(geek, 0)) {
                prefix = "I'd estimate it is approximately ";
            } else {
                prefix = "Huh?  Maybe ";
            }
        }
        if (LocaleUtility::isFallbackOf(californio, id)) {
            if (!id.caseCompare(valley, 0)) {
                suffix = "like the Valley, you know?  Let's go to the mall!";
            } else if (!id.caseCompare(surfer, 0)) {
                suffix = "time to hit those gnarly waves, Dude!!!";
            } else if (!id.caseCompare(geek, 0)) {
                suffix = "all systems go.  T-Minus 9, 8, 7...";
            } else {
                suffix = "No Habla Englais";
            }
        } else {
            suffix = ICUResourceBundleFactory::getDisplayName(id, locale, result);
        }

        result = prefix + suffix;
        return result;
    }
};

const char* CalifornioLanguageFactory::californio = "en_US_CA";
const char* CalifornioLanguageFactory::valley = "en_US_CA_VALLEY";
const char* CalifornioLanguageFactory::surfer = "en_US_CA_SURFER";
const char* CalifornioLanguageFactory::geek = "en_US_CA_GEEK";
Hashtable* CalifornioLanguageFactory::supportedIDs = NULL;

void
ICUServiceTest::testRBF()
{
    // resource bundle factory.
    UErrorCode status = U_ZERO_ERROR;
    TestStringService service;
    service.registerFactory(new ICUResourceBundleFactory(), status);

    // list all of the resources 
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        logln("all visible ids:");
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            logln(*id);
        }
    }

    // get all the display names of these resources
    // this should be fast since the display names were cached.
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector names(status);
        service.getDisplayNames(names, Locale::getGermany(), status);
        logln("service display names for de_DE");
        for (int i = 0; i < names.size(); ++i) {
            const StringPair* pair = (const StringPair*)names[i];
            logln("  " + pair->displayName + " --> " + pair->id);
        }
    }

    service.registerFactory(new CalifornioLanguageFactory(), status);

    // get all the display names of these resources
    {
        logln("californio language factory:");
        const char* idNames[] = {
            CalifornioLanguageFactory::californio, 
            CalifornioLanguageFactory::valley, 
            CalifornioLanguageFactory::surfer, 
            CalifornioLanguageFactory::geek,
        };
        int32_t count = UPRV_LENGTHOF(idNames);

        for (int i = 0; i < count; ++i) {
            logln(UnicodeString("\n  --- ") + idNames[i] + " ---");
            {
                UErrorCode status = U_ZERO_ERROR;
                UVector names(status);
                service.getDisplayNames(names, idNames[i], status);
                for (int i = 0; i < names.size(); ++i) {
                    const StringPair* pair = (const StringPair*)names[i];
                    logln("  " + pair->displayName + " --> " + pair->id);
                }
            }
        }
    }
    CalifornioLanguageFactory::cleanup();
}

class SimpleListener : public ServiceListener {
    ICUServiceTest* _test;
    UnicodeString _name;

    public:
    SimpleListener(ICUServiceTest* test, const UnicodeString& name) : _test(test), _name(name) {}

    virtual void serviceChanged(const ICUService& service) const {
        UnicodeString serviceName = "listener ";
        serviceName.append(_name);
        serviceName.append(" n++");
        serviceName.append(" service changed: " );
        service.getName(serviceName);
        _test->logln(serviceName);
    }
};

void
ICUServiceTest::testNotification()
{
    SimpleListener one(this, "one");
    SimpleListener two(this, "two");
    {
        UErrorCode status = U_ZERO_ERROR;

        logln("simple registration notification");
        TestStringService ls;
        ls.addListener(&one, status);
        ls.addListener(&two, status);

        logln("registering foo... ");
        ls.registerInstance(new UnicodeString("Foo"), "en_FOO", status);
        logln("registering bar... ");
        ls.registerInstance(new UnicodeString("Bar"), "en_BAR", status);
        logln("getting foo...");
        UnicodeString* result = (UnicodeString*)ls.get("en_FOO", status);
        logln(*result);
        delete result;

        logln("removing listener 2...");
        ls.removeListener(&two, status);
        logln("registering baz...");
        ls.registerInstance(new UnicodeString("Baz"), "en_BAZ", status);
        logln("removing listener 1");
        ls.removeListener(&one, status);
        logln("registering burp...");
        ls.registerInstance(new UnicodeString("Burp"), "en_BURP", status);

        // should only get one notification even if register multiple times
        logln("... trying multiple registration");
        ls.addListener(&one, status);
        ls.addListener(&one, status);
        ls.addListener(&one, status);
        ls.addListener(&two, status);
        ls.registerInstance(new UnicodeString("Foo"), "en_FOO", status);
        logln("... registered foo");
    }
#if 0
    // same thread, so we can't callback within notification, unlike Java
    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.registerInstance("boink", "en_BOINK");
    }
}
    };
    ls.addListener(l3);
    logln("registering boo...");
    ls.registerInstance("Boo", "en_BOO");
#endif

    logln("...done");
}

class TestStringLocaleService : public ICULocaleService {
    public:
    virtual UObject* cloneInstance(UObject* instance) const {
        return instance ? new UnicodeString(*(UnicodeString*)instance) : NULL;
    }
};

void ICUServiceTest::testLocale() {
    UErrorCode status = U_ZERO_ERROR;
    TestStringLocaleService service;

    UnicodeString* root = new UnicodeString("root");
    UnicodeString* german = new UnicodeString("german");
    UnicodeString* germany = new UnicodeString("german_Germany");
    UnicodeString* japanese = new UnicodeString("japanese");
    UnicodeString* japan = new UnicodeString("japanese_Japan");

    service.registerInstance(root, "", status);
    service.registerInstance(german, "de", status);
    service.registerInstance(germany, Locale::getGermany(), status);
    service.registerInstance(japanese, (UnicodeString)"ja", TRUE, status);
    service.registerInstance(japan, Locale::getJapan(), status);

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", status);
        confirmEqual("test de_US", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", LocaleKey::KIND_ANY, status);
        confirmEqual("test de_US 2", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 1234, status);
        confirmEqual("test de_US 3", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        Locale actualReturn;
        UnicodeString* target = (UnicodeString*)service.get("de_US", &actualReturn, status);
        confirmEqual("test de_US 5", german, target);
        confirmEqual("test de_US 6", &actualReturn, &Locale::getGerman());
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        Locale actualReturn;
        UnicodeString* target = (UnicodeString*)service.get("de_US", LocaleKey::KIND_ANY, &actualReturn, status);
        confirmEqual("test de_US 7", &actualReturn, &Locale::getGerman());
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        Locale actualReturn;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 1234, &actualReturn, status);
        confirmEqual("test de_US 8", german, target);
        confirmEqual("test de_US 9", &actualReturn, &Locale::getGerman());
        delete target;
    }

    UnicodeString* one = new UnicodeString("one/de_US");
    UnicodeString* two = new UnicodeString("two/de_US");

    service.registerInstance(one, Locale("de_US"), 1, status);
    service.registerInstance(two, Locale("de_US"), 2, status);

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 1, status);
        confirmEqual("test de_US kind 1", one, target);
        delete target;
    }
        
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", 2, status);
        confirmEqual("test de_US kind 2", two, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("de_US", status);
        confirmEqual("test de_US kind 3", german, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString english = "en";
        Locale localeResult;
        UnicodeString result;
        LocaleKey* lkey = LocaleKey::createWithCanonicalFallback(&english, NULL, 1234, status);
        logln("lkey prefix: " + lkey->prefix(result));
        result.remove();
        logln("lkey descriptor: " + lkey->currentDescriptor(result));
        result.remove();
        logln(UnicodeString("lkey current locale: ") + lkey->currentLocale(localeResult).getName());
        result.remove();

        lkey->fallback();
        logln("lkey descriptor 2: " + lkey->currentDescriptor(result));
        result.remove();

        lkey->fallback();
        logln("lkey descriptor 3: " + lkey->currentDescriptor(result));
        result.remove();
        delete lkey; // tentatively weiv
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("za_PPP", status);
        confirmEqual("test zappp", root, target);
        delete target;
    }

    Locale loc = Locale::getDefault();
    Locale::setDefault(Locale::getJapanese(), status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("za_PPP", status);
        confirmEqual("test with ja locale", japanese, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        logln("all visible ids:");
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            logln(*id);
        }
    }

    Locale::setDefault(loc, status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, 0, status);
        service.getVisibleIDs(ids, status);
        logln("all visible ids:");
        for (int i = 0; i < ids.size(); ++i) {
            const UnicodeString* id = (const UnicodeString*)ids[i];
            logln(*id);
        }
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* target = (UnicodeString*)service.get("za_PPP", status);
        confirmEqual("test with en locale", root, target);
        delete target;
    }

    {
        UErrorCode status = U_ZERO_ERROR;
        StringEnumeration* locales = service.getAvailableLocales();
        if (locales) {
            confirmIdentical("test available locales", locales->count(status), 6);
            logln("locales: ");
            {
                const char* p;
                while ((p = locales->next(NULL, status))) {
                    logln(p);
                }
            }
            logln(" ");
            delete locales;
        } else {
            errln("could not create available locales");
        }
    }
}

class WrapFactory : public ICUServiceFactory {
    public:
    static const UnicodeString& getGreetingID() {
      if (greetingID == NULL) {
    greetingID = new UnicodeString("greeting");
      }
      return *greetingID;
    }

  static void cleanup() {
    delete greetingID;
    greetingID = NULL;
  }

    UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const {
        if (U_SUCCESS(status)) {
            UnicodeString temp;
            if (key.currentID(temp).compare(getGreetingID()) == 0) {
                UnicodeString* previous = (UnicodeString*)service->getKey((ICUServiceKey&)key, NULL, this, status);
                if (previous) {
                    previous->insert(0, "A different greeting: \"");
                    previous->append("\"");
                    return previous;
                }
            }
        }
        return NULL;
    }

    void updateVisibleIDs(Hashtable& result, UErrorCode& status) const {
        if (U_SUCCESS(status)) {
            result.put("greeting", (void*)this, status);
        }
    }

    UnicodeString& getDisplayName(const UnicodeString& id, const Locale& /* locale */, UnicodeString& result) const {
        result.append("wrap '");
        result.append(id);
        result.append("'");
        return result;
    }

    /**
     * UObject boilerplate.
     */
    static UClassID getStaticClassID() { 
        return (UClassID)&fgClassID;
    }

    virtual UClassID getDynamicClassID() const {
        return getStaticClassID();
    }

    private:
    static const char fgClassID;
    static UnicodeString* greetingID;
};

UnicodeString* WrapFactory::greetingID = NULL;
const char WrapFactory::fgClassID = '\0';

void 
ICUServiceTest::testWrapFactory() 
{
    UnicodeString* greeting = new UnicodeString("Hello There");
    UnicodeString greetingID = "greeting";
    UErrorCode status = U_ZERO_ERROR;
    TestStringService service;
    service.registerInstance(greeting, greetingID, status);

    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get(greetingID, status);
        if (result) {
            logln("test one: " + *result);
            delete result;
        }
    }

    service.registerFactory(new WrapFactory(), status);
    {
        UErrorCode status = U_ZERO_ERROR;
        UnicodeString* result = (UnicodeString*)service.get(greetingID, status);
        UnicodeString target = "A different greeting: \"Hello There\"";
        confirmEqual("wrap test: ", result, &target);
        delete result;
    }

    WrapFactory::cleanup();
}

  // misc coverage tests
void ICUServiceTest::testCoverage() 
{
  // ICUServiceKey
  {
    UnicodeString temp;
    ICUServiceKey key("foobar");
    logln("ID: " + key.getID());
    logln("canonicalID: " + key.canonicalID(temp));
    logln("currentID: " + key.currentID(temp.remove()));
    logln("has fallback: " + UnicodeString(key.fallback() ? "true" : "false"));

    if (key.getDynamicClassID() != ICUServiceKey::getStaticClassID()) {
      errln("service key rtt failed.");
    }
  }

  // SimpleFactory
  {
    UErrorCode status = U_ZERO_ERROR;

    UnicodeString* obj = new UnicodeString("An Object");
    SimpleFactory* sf = new SimpleFactory(obj, "object");

    UnicodeString temp;
    logln(sf->getDisplayName("object", Locale::getDefault(), temp));

    if (sf->getDynamicClassID() != SimpleFactory::getStaticClassID()) {
      errln("simple factory rtti failed.");
    }

    // ICUService
        {
                TestStringService service;
                service.registerFactory(sf,     status);

                {
                        UnicodeString* result   = (UnicodeString*)service.get("object", status);
                        if (result) {
                                logln("object is: "     + *result);
                                delete result;
                        }       else {
                                errln("could not get object");
                        }
                }
        }
  }
  
  // ICUServiceKey
  {
      UErrorCode status = U_ZERO_ERROR;
          UnicodeString* howdy = new UnicodeString("Howdy");

          TestStringSimpleKeyService service;
          service.registerInstance(howdy, "Greetings", status);
          {
                  UnicodeString* result = (UnicodeString*)service.get("Greetings",      status);
                  if (result) {
                          logln("object is: "   + *result);
                          delete result;
                  }     else {
                          errln("could not get object");
                  }
          }

      UVector ids(uprv_deleteUObject, uhash_compareUnicodeString, status);
          // yuck, this is awkward to use.  All because we pass null in an overload.
          // TODO: change this.
          UnicodeString str("Greet");
      service.getVisibleIDs(ids, &str, status);
      confirmIdentical("no fallback of greet", ids.size(), 0);
  }

  // ICULocaleService

  // LocaleKey
  {
    UnicodeString primary("en_US");
    UnicodeString fallback("ja_JP");
    UErrorCode status = U_ZERO_ERROR;
    LocaleKey* key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status);

    if (key->getDynamicClassID() != LocaleKey::getStaticClassID()) {
      errln("localekey rtti error");
    }

    if (!key->isFallbackOf("en_US_FOOBAR")) {
      errln("localekey should be fallback for en_US_FOOBAR");
    }
    if (!key->isFallbackOf("en_US")) {
      errln("localekey should be fallback for en_US");
    }
    if (key->isFallbackOf("en")) {
      errln("localekey should not be fallback for en");
    }

    do {
      Locale loc;
      logln(UnicodeString("current locale: ") + key->currentLocale(loc).getName());
      logln(UnicodeString("canonical locale: ") + key->canonicalLocale(loc).getName());
      logln(UnicodeString("is fallback of en: ") + (key->isFallbackOf("en") ? "true" : " false"));
    } while (key->fallback());
    delete key;

    // LocaleKeyFactory 
    key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status);

    UnicodeString result;
    LKFSubclass lkf(TRUE); // empty
    Hashtable table;

    UObject *obj = lkf.create(*key, NULL, status);
    logln("obj: " + UnicodeString(obj ? "obj" : "null"));
    logln(lkf.getDisplayName("en_US", Locale::getDefault(), result));
    lkf.updateVisibleIDs(table, status);
    delete obj;
    if (table.count() != 1) {
      errln("visible IDs does not contain en_US");
    }

    LKFSubclass invisibleLKF(FALSE);
    obj = lkf.create(*key, NULL, status);
    logln("obj: " + UnicodeString(obj ? "obj" : "null"));
    logln(invisibleLKF.getDisplayName("en_US", Locale::getDefault(), result.remove()));
    invisibleLKF.updateVisibleIDs(table, status);
    if (table.count() != 0) {
      errln("visible IDs contains en_US");
    }
    delete obj;
    delete key;

        key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, 123, status);
        if (U_SUCCESS(status)) {
                UnicodeString str;
                key->currentDescriptor(str);
                key->parsePrefix(str);
                if (str != "123") {
                        errln("did not get expected prefix");
                }
                delete key;
        }

        // coverage, getSupportedIDs is either overridden or the calling method is
        LKFSubclass0 lkFactory;
        Hashtable table0;
        lkFactory.updateVisibleIDs(table0, status);
        if (table0.count() != 0) {
                errln("LKF returned non-empty hashtable");
        }


        // ResourceBundleFactory
    key = LocaleKey::createWithCanonicalFallback(&primary, &fallback, status);
        ICUResourceBundleFactory rbf;
        UObject* icurb = rbf.create(*key, NULL, status);
        if (icurb != NULL) {
                logln("got resource bundle for key");
                delete icurb;
        }
        delete key;
  }

 #if 0
 // 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());
#endif
}


/* !UCONFIG_NO_SERVICE */
#endif


