/**
*******************************************************************************
* Copyright (C) 2001-2010, International Business Machines Corporation.
* All Rights Reserved.
*******************************************************************************
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_SERVICE

#include "serv.h"
#include "umutex.h"

#undef SERVICE_REFCOUNT

// in case we use the refcount stuff

U_NAMESPACE_BEGIN

/*
******************************************************************
*/

const UChar ICUServiceKey::PREFIX_DELIMITER = 0x002F;   /* '/' */

ICUServiceKey::ICUServiceKey(const UnicodeString& id) 
: _id(id) {
}

ICUServiceKey::~ICUServiceKey() 
{
}

const UnicodeString& 
ICUServiceKey::getID() const 
{
    return _id;
}

UnicodeString& 
ICUServiceKey::canonicalID(UnicodeString& result) const 
{
    return result.append(_id);
}

UnicodeString& 
ICUServiceKey::currentID(UnicodeString& result) const 
{
    return canonicalID(result);
}

UnicodeString& 
ICUServiceKey::currentDescriptor(UnicodeString& result) const 
{
    prefix(result);
    result.append(PREFIX_DELIMITER);
    return currentID(result);
}

UBool 
ICUServiceKey::fallback() 
{
    return FALSE;
}

UBool 
ICUServiceKey::isFallbackOf(const UnicodeString& id) const 
{
    return id == _id;
}

UnicodeString& 
ICUServiceKey::prefix(UnicodeString& result) const 
{
    return result;
}

UnicodeString& 
ICUServiceKey::parsePrefix(UnicodeString& result) 
{
    int32_t n = result.indexOf(PREFIX_DELIMITER);
    if (n < 0) {
        n = 0;
    }
    result.remove(n);
    return result;
}

UnicodeString& 
ICUServiceKey::parseSuffix(UnicodeString& result) 
{
    int32_t n = result.indexOf(PREFIX_DELIMITER);
    if (n >= 0) {
        result.remove(0, n+1);
    }
    return result;
}

#ifdef SERVICE_DEBUG
UnicodeString& 
ICUServiceKey::debug(UnicodeString& result) const 
{
    debugClass(result);
    result.append(" id: ");
    result.append(_id);
    return result;
}

UnicodeString& 
ICUServiceKey::debugClass(UnicodeString& result) const 
{
    return result.append("ICUServiceKey");
}
#endif

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ICUServiceKey)

/*
******************************************************************
*/

SimpleFactory::SimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible) 
: _instance(instanceToAdopt), _id(id), _visible(visible)
{
}

SimpleFactory::~SimpleFactory() 
{
    delete _instance;
}

UObject* 
SimpleFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const 
{
    if (U_SUCCESS(status)) {
        UnicodeString temp;
        if (_id == key.currentID(temp)) {
            return service->cloneInstance(_instance); 
        }
    }
    return NULL;
}

void 
SimpleFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const 
{
    if (_visible) {
        result.put(_id, (void*)this, status); // cast away const
    } else {
        result.remove(_id);
    }
}

UnicodeString& 
SimpleFactory::getDisplayName(const UnicodeString& id, const Locale& /* locale */, UnicodeString& result) const 
{
    if (_visible && _id == id) {
        result = _id;
    } else {
        result.setToBogus();
    }
    return result;
}

#ifdef SERVICE_DEBUG
UnicodeString& 
SimpleFactory::debug(UnicodeString& toAppendTo) const 
{
    debugClass(toAppendTo);
    toAppendTo.append(" id: ");
    toAppendTo.append(_id);
    toAppendTo.append(", visible: ");
    toAppendTo.append(_visible ? "T" : "F");
    return toAppendTo;
}

UnicodeString& 
SimpleFactory::debugClass(UnicodeString& toAppendTo) const 
{
    return toAppendTo.append("SimpleFactory");
}
#endif

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleFactory)

/*
******************************************************************
*/

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceListener)

/*
******************************************************************
*/

// Record the actual id for this service in the cache, so we can return it
// even if we succeed later with a different id.
class CacheEntry : public UMemory {
private:
    int32_t refcount;

public:
    UnicodeString actualDescriptor;
    UObject* service;

    /**
    * Releases a reference to the shared resource.
    */
    ~CacheEntry() {
        delete service;
    }

    CacheEntry(const UnicodeString& _actualDescriptor, UObject* _service) 
        : refcount(1), actualDescriptor(_actualDescriptor), service(_service) {
    }

    /**
    * Instantiation creates an initial reference, so don't call this
    * unless you're creating a new pointer to this.  Management of
    * that pointer will have to know how to deal with refcounts.  
    * Return true if the resource has not already been released.
    */
    CacheEntry* ref() {
        ++refcount;
        return this;
    }

    /**
    * Destructions removes a reference, so don't call this unless
    * you're removing pointer to this somewhere.  Management of that
    * pointer will have to know how to deal with refcounts.  Once
    * the refcount drops to zero, the resource is released.  Return
    * false if the resouce has been released.
    */
    CacheEntry* unref() {
        if ((--refcount) == 0) {
            delete this;
            return NULL;
        }
        return this;
    }

    /**
    * Return TRUE if there is at least one reference to this and the
    * resource has not been released.
    */
    UBool isShared() const {
        return refcount > 1;
    }
};

// UObjectDeleter for serviceCache
U_CDECL_BEGIN
static void U_CALLCONV
cacheDeleter(void* obj) {
    U_NAMESPACE_USE ((CacheEntry*)obj)->unref();
}

/**
* Deleter for UObjects
*/
static void U_CALLCONV
deleteUObject(void *obj) {
    U_NAMESPACE_USE delete (UObject*) obj;
}
U_CDECL_END

/*
******************************************************************
*/

class DNCache : public UMemory {
public:
    Hashtable cache;
    const Locale locale;

    DNCache(const Locale& _locale) 
        : cache(), locale(_locale) 
    {
        // cache.setKeyDeleter(uhash_deleteUnicodeString);
    }
};


/*
******************************************************************
*/

StringPair* 
StringPair::create(const UnicodeString& displayName, 
                   const UnicodeString& id,
                   UErrorCode& status)
{
    if (U_SUCCESS(status)) {
        StringPair* sp = new StringPair(displayName, id);
        if (sp == NULL || sp->isBogus()) {
            status = U_MEMORY_ALLOCATION_ERROR;
            delete sp;
            return NULL;
        }
        return sp;
    }
    return NULL;
}

UBool 
StringPair::isBogus() const {
    return displayName.isBogus() || id.isBogus();
}

StringPair::StringPair(const UnicodeString& _displayName, 
                       const UnicodeString& _id)
: displayName(_displayName)
, id(_id)
{
}

U_CDECL_BEGIN
static void U_CALLCONV
userv_deleteStringPair(void *obj) {
    U_NAMESPACE_USE delete (StringPair*) obj;
}
U_CDECL_END

/*
******************************************************************
*/

ICUService::ICUService()
: name()
, lock(0)
, timestamp(0)
, factories(NULL)
, serviceCache(NULL)
, idCache(NULL)
, dnCache(NULL)
{
    umtx_init(&lock);
}

ICUService::ICUService(const UnicodeString& newName) 
: name(newName)
, lock(0)
, timestamp(0)
, factories(NULL)
, serviceCache(NULL)
, idCache(NULL)
, dnCache(NULL)
{
    umtx_init(&lock);
}

ICUService::~ICUService()
{
    {
        Mutex mutex(&lock);
        clearCaches();
        delete factories;
        factories = NULL;
    }
    umtx_destroy(&lock);
}

UObject* 
ICUService::get(const UnicodeString& descriptor, UErrorCode& status) const 
{
    return get(descriptor, NULL, status);
}

UObject* 
ICUService::get(const UnicodeString& descriptor, UnicodeString* actualReturn, UErrorCode& status) const 
{
    UObject* result = NULL;
    ICUServiceKey* key = createKey(&descriptor, status);
    if (key) {
        result = getKey(*key, actualReturn, status);
        delete key;
    }
    return result;
}

UObject* 
ICUService::getKey(ICUServiceKey& key, UErrorCode& status) const 
{
    return getKey(key, NULL, status);
}

// this is a vector that subclasses of ICUService can override to further customize the result object
// before returning it.  All other public get functions should call this one.

UObject* 
ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const 
{
    return getKey(key, actualReturn, NULL, status);
}

// make it possible to call reentrantly on systems that don't have reentrant mutexes.
// we can use this simple approach since we know the situation where we're calling
// reentrantly even without knowing the thread.
class XMutex : public UMemory {
public:
    inline XMutex(UMTX *mutex, UBool reentering) 
        : fMutex(mutex)
        , fActive(!reentering) 
    {
        if (fActive) umtx_lock(fMutex);
    }
    inline ~XMutex() {
        if (fActive) umtx_unlock(fMutex);
    }

private:
    UMTX  *fMutex;
    UBool fActive;
};

struct UVectorDeleter {
    UVector* _obj;
    UVectorDeleter() : _obj(NULL) {}
    ~UVectorDeleter() { delete _obj; }
};

// called only by factories, treat as private
UObject* 
ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUServiceFactory* factory, UErrorCode& status) const 
{
    if (U_FAILURE(status)) {
        return NULL;
    }

    if (isDefault()) {
        return handleDefault(key, actualReturn, status);
    }

    ICUService* ncthis = (ICUService*)this; // cast away semantic const

    CacheEntry* result = NULL;
    {
        // The factory list can't be modified until we're done, 
        // otherwise we might update the cache with an invalid result.
        // The cache has to stay in synch with the factory list.
        // ICU doesn't have monitors so we can't use rw locks, so 
        // we single-thread everything using this service, for now.

        // if factory is not null, we're calling from within the mutex,
        // and since some unix machines don't have reentrant mutexes we
        // need to make sure not to try to lock it again.
        XMutex mutex(&ncthis->lock, factory != NULL);

        if (serviceCache == NULL) {
            ncthis->serviceCache = new Hashtable(status);
            if (ncthis->serviceCache == NULL) {
                return NULL;
            }
            if (U_FAILURE(status)) {
                delete serviceCache;
                return NULL;
            }
            serviceCache->setValueDeleter(cacheDeleter);
        }

        UnicodeString currentDescriptor;
        UVectorDeleter cacheDescriptorList;
        UBool putInCache = FALSE;

        int32_t startIndex = 0;
        int32_t limit = factories->size();
        UBool cacheResult = TRUE;

        if (factory != NULL) {
            for (int32_t i = 0; i < limit; ++i) {
                if (factory == (const ICUServiceFactory*)factories->elementAt(i)) {
                    startIndex = i + 1;
                    break;
                }
            }
            if (startIndex == 0) {
                // throw new InternalError("Factory " + factory + "not registered with service: " + this);
                status = U_ILLEGAL_ARGUMENT_ERROR;
                return NULL;
            }
            cacheResult = FALSE;
        }

        do {
            currentDescriptor.remove();
            key.currentDescriptor(currentDescriptor);
            result = (CacheEntry*)serviceCache->get(currentDescriptor);
            if (result != NULL) {
                break;
            }

            // first test of cache failed, so we'll have to update
            // the cache if we eventually succeed-- that is, if we're 
            // going to update the cache at all.
            putInCache = TRUE;

            int32_t index = startIndex;
            while (index < limit) {
                ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++);
                UObject* service = f->create(key, this, status);
                if (U_FAILURE(status)) {
                    delete service;
                    return NULL;
                }
                if (service != NULL) {
                    result = new CacheEntry(currentDescriptor, service);
                    if (result == NULL) {
                        delete service;
                        status = U_MEMORY_ALLOCATION_ERROR;
                        return NULL;
                    }

                    goto outerEnd;
                }
            }

            // prepare to load the cache with all additional ids that 
            // will resolve to result, assuming we'll succeed.  We
            // don't want to keep querying on an id that's going to
            // fallback to the one that succeeded, we want to hit the
            // cache the first time next goaround.
            if (cacheDescriptorList._obj == NULL) {
                cacheDescriptorList._obj = new UVector(uhash_deleteUnicodeString, NULL, 5, status);
                if (U_FAILURE(status)) {
                    return NULL;
                }
            }
            UnicodeString* idToCache = new UnicodeString(currentDescriptor);
            if (idToCache == NULL || idToCache->isBogus()) {
                status = U_MEMORY_ALLOCATION_ERROR;
                return NULL;
            }

            cacheDescriptorList._obj->addElement(idToCache, status);
            if (U_FAILURE(status)) {
                return NULL;
            }
        } while (key.fallback());
outerEnd:

        if (result != NULL) {
            if (putInCache && cacheResult) {
                serviceCache->put(result->actualDescriptor, result, status);
                if (U_FAILURE(status)) {
                    delete result;
                    return NULL;
                }

                if (cacheDescriptorList._obj != NULL) {
                    for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) {
                        UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i);
                        serviceCache->put(*desc, result, status);
                        if (U_FAILURE(status)) {
                            delete result;
                            return NULL;
                        }

                        result->ref();
                        cacheDescriptorList._obj->removeElementAt(i);
                    }
                }
            }

            if (actualReturn != NULL) {
                // strip null prefix
                if (result->actualDescriptor.indexOf((UChar)0x2f) == 0) { // U+002f=slash (/)
                    actualReturn->remove();
                    actualReturn->append(result->actualDescriptor, 
                        1, 
                        result->actualDescriptor.length() - 1);
                } else {
                    *actualReturn = result->actualDescriptor;
                }

                if (actualReturn->isBogus()) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                    delete result;
                    return NULL;
                }
            }

            UObject* service = cloneInstance(result->service);
            if (putInCache && !cacheResult) {
                delete result;
            }
            return service;
        }
    }

    return handleDefault(key, actualReturn, status);
}

UObject* 
ICUService::handleDefault(const ICUServiceKey& /* key */, UnicodeString* /* actualIDReturn */, UErrorCode& /* status */) const 
{
    return NULL;
}

UVector& 
ICUService::getVisibleIDs(UVector& result, UErrorCode& status) const {
    return getVisibleIDs(result, NULL, status);
}

UVector& 
ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorCode& status) const 
{
    result.removeAllElements();

    if (U_FAILURE(status)) {
        return result;
    }

    ICUService * ncthis = (ICUService*)this; // cast away semantic const
    {
        Mutex mutex(&ncthis->lock);
        const Hashtable* map = getVisibleIDMap(status);
        if (map != NULL) {
            ICUServiceKey* fallbackKey = createKey(matchID, status);

            for (int32_t pos = -1;;) {
                const UHashElement* e = map->nextElement(pos);
                if (e == NULL) {
                    break;
                }

                const UnicodeString* id = (const UnicodeString*)e->key.pointer;
                if (fallbackKey != NULL) {
                    if (!fallbackKey->isFallbackOf(*id)) {
                        continue;
                    }
                }

                UnicodeString* idClone = new UnicodeString(*id);
                if (idClone == NULL || idClone->isBogus()) {
                    delete idClone;
                    status = U_MEMORY_ALLOCATION_ERROR;
                    break;
                }
                result.addElement(idClone, status);
                if (U_FAILURE(status)) {
                    delete idClone;
                    break;
                }
            }
            delete fallbackKey;
        }
    }
    if (U_FAILURE(status)) {
        result.removeAllElements();
    }
    return result;
}

const Hashtable* 
ICUService::getVisibleIDMap(UErrorCode& status) const {
    if (U_FAILURE(status)) return NULL;

    // must only be called when lock is already held

    ICUService* ncthis = (ICUService*)this; // cast away semantic const
    if (idCache == NULL) {
        ncthis->idCache = new Hashtable(status);
        if (idCache == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
        } else if (factories != NULL) {
            for (int32_t pos = factories->size(); --pos >= 0;) {
                ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(pos);
                f->updateVisibleIDs(*idCache, status);
            }
            if (U_FAILURE(status)) {
                delete idCache;
                ncthis->idCache = NULL;
            }
        }
    }

    return idCache;
}


UnicodeString& 
ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result) const 
{
    return getDisplayName(id, result, Locale::getDefault());
}

UnicodeString& 
ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const Locale& locale) const 
{
    {
        ICUService* ncthis = (ICUService*)this; // cast away semantic const
        UErrorCode status = U_ZERO_ERROR;
        Mutex mutex(&ncthis->lock);
        const Hashtable* map = getVisibleIDMap(status);
        if (map != NULL) {
            ICUServiceFactory* f = (ICUServiceFactory*)map->get(id);
            if (f != NULL) {
                f->getDisplayName(id, locale, result);
                return result;
            }

            // fallback
            UErrorCode status = U_ZERO_ERROR;
            ICUServiceKey* fallbackKey = createKey(&id, status);
            while (fallbackKey->fallback()) {
                UnicodeString us;
                fallbackKey->currentID(us);
                f = (ICUServiceFactory*)map->get(us);
                if (f != NULL) {
                    f->getDisplayName(id, locale, result);
                    delete fallbackKey;
                    return result;
                }
            }
            delete fallbackKey;
        }
    }
    result.setToBogus();
    return result;
}

UVector& 
ICUService::getDisplayNames(UVector& result, UErrorCode& status) const 
{
    return getDisplayNames(result, Locale::getDefault(), NULL, status);
}


UVector& 
ICUService::getDisplayNames(UVector& result, const Locale& locale, UErrorCode& status) const 
{
    return getDisplayNames(result, locale, NULL, status);
}

UVector& 
ICUService::getDisplayNames(UVector& result, 
                            const Locale& locale, 
                            const UnicodeString* matchID, 
                            UErrorCode& status) const 
{
    result.removeAllElements();
    result.setDeleter(userv_deleteStringPair);
    if (U_SUCCESS(status)) {
        ICUService* ncthis = (ICUService*)this; // cast away semantic const
        Mutex mutex(&ncthis->lock);

        if (dnCache != NULL && dnCache->locale != locale) {
            delete dnCache;
            ncthis->dnCache = NULL;
        }

        if (dnCache == NULL) {
            const Hashtable* m = getVisibleIDMap(status);
            if (m != NULL) {
                ncthis->dnCache = new DNCache(locale); 
                if (dnCache == NULL) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                    return result;
                }

                int32_t pos = -1;
                const UHashElement* entry = NULL;
                while ((entry = m->nextElement(pos)) != NULL) {
                    const UnicodeString* id = (const UnicodeString*)entry->key.pointer;
                    ICUServiceFactory* f = (ICUServiceFactory*)entry->value.pointer;
                    UnicodeString dname;
                    f->getDisplayName(*id, locale, dname);
                    if (dname.isBogus()) {
                        status = U_MEMORY_ALLOCATION_ERROR;
                    } else {
                        dnCache->cache.put(dname, (void*)id, status); // share pointer with visibleIDMap
                        if (U_SUCCESS(status)) {
                            continue;
                        }
                    }
                    delete dnCache;
                    ncthis->dnCache = NULL;
                    return result;
                }
            }
        }
    }

    ICUServiceKey* matchKey = createKey(matchID, status);
    /* To ensure that all elements in the hashtable are iterated, set pos to -1.
     * nextElement(pos) will skip the position at pos and begin the iteration
     * at the next position, which in this case will be 0.
     */
    int32_t pos = -1; 
    const UHashElement *entry = NULL;
    while ((entry = dnCache->cache.nextElement(pos)) != NULL) {
        const UnicodeString* id = (const UnicodeString*)entry->value.pointer;
        if (matchKey != NULL && !matchKey->isFallbackOf(*id)) {
            continue;
        }
        const UnicodeString* dn = (const UnicodeString*)entry->key.pointer;
        StringPair* sp = StringPair::create(*id, *dn, status);
        result.addElement(sp, status);
        if (U_FAILURE(status)) {
            result.removeAllElements();
            break;
        }
    }
    delete matchKey;

    return result;
}

URegistryKey
ICUService::registerInstance(UObject* objToAdopt, const UnicodeString& id, UErrorCode& status) 
{
    return registerInstance(objToAdopt, id, TRUE, status);
}

URegistryKey
ICUService::registerInstance(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status) 
{
    ICUServiceKey* key = createKey(&id, status);
    if (key != NULL) {
        UnicodeString canonicalID;
        key->canonicalID(canonicalID);
        delete key;

        ICUServiceFactory* f = createSimpleFactory(objToAdopt, canonicalID, visible, status);
        if (f != NULL) {
            return registerFactory(f, status);
        }
    }
    delete objToAdopt;
    return NULL;
}

ICUServiceFactory* 
ICUService::createSimpleFactory(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status)
{
    if (U_SUCCESS(status)) {
        if ((objToAdopt != NULL) && (!id.isBogus())) {
            return new SimpleFactory(objToAdopt, id, visible);
        }
        status = U_ILLEGAL_ARGUMENT_ERROR;
    }
    return NULL;
}

URegistryKey
ICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status) 
{
    if (U_SUCCESS(status) && factoryToAdopt != NULL) {
        Mutex mutex(&lock);

        if (factories == NULL) {
            factories = new UVector(deleteUObject, NULL, status);
            if (U_FAILURE(status)) {
                delete factories;
                return NULL;
            }
        }
        factories->insertElementAt(factoryToAdopt, 0, status);
        if (U_SUCCESS(status)) {
            clearCaches();
        } else {
            delete factoryToAdopt;
            factoryToAdopt = NULL;
        }
    }

    if (factoryToAdopt != NULL) {
        notifyChanged();
    }

    return (URegistryKey)factoryToAdopt;
}

UBool 
ICUService::unregister(URegistryKey rkey, UErrorCode& status) 
{
    ICUServiceFactory *factory = (ICUServiceFactory*)rkey;
    UBool result = FALSE;
    if (factory != NULL && factories != NULL) {
        Mutex mutex(&lock);

        if (factories->removeElement(factory)) {
            clearCaches();
            result = TRUE;
        } else {
            status = U_ILLEGAL_ARGUMENT_ERROR;
            delete factory;
        }
    }
    if (result) {
        notifyChanged();
    }
    return result;
}

void 
ICUService::reset() 
{
    {
        Mutex mutex(&lock);
        reInitializeFactories();
        clearCaches();
    }
    notifyChanged();
}

void 
ICUService::reInitializeFactories() 
{
    if (factories != NULL) {
        factories->removeAllElements();
    }
}

UBool 
ICUService::isDefault() const 
{
    return countFactories() == 0;
}

ICUServiceKey* 
ICUService::createKey(const UnicodeString* id, UErrorCode& status) const 
{
    return (U_FAILURE(status) || id == NULL) ? NULL : new ICUServiceKey(*id);
}

void 
ICUService::clearCaches() 
{
    // callers synchronize before use
    ++timestamp;
    delete dnCache;
    dnCache = NULL;
    delete idCache;
    idCache = NULL;
    delete serviceCache; serviceCache = NULL;
}

void 
ICUService::clearServiceCache() 
{
    // callers synchronize before use
    delete serviceCache; serviceCache = NULL;
}

UBool 
ICUService::acceptsListener(const EventListener& l) const 
{
    return dynamic_cast<const ServiceListener*>(&l) != NULL;
}

void 
ICUService::notifyListener(EventListener& l) const 
{
    ((ServiceListener&)l).serviceChanged(*this);
}

UnicodeString&
ICUService::getName(UnicodeString& result) const 
{
    return result.append(name);
}

int32_t 
ICUService::countFactories() const 
{
    return factories == NULL ? 0 : factories->size();
}

int32_t
ICUService::getTimestamp() const
{
    return timestamp;
}

U_NAMESPACE_END

/* UCONFIG_NO_SERVICE */
#endif
