1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
31b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 2001-2014, International Business Machines Corporation.
427f654740f2a26ad62a5c155af9199af9e69b889claireho* All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "serv.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "umutex.h"
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#undef SERVICE_REFCOUNT
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// in case we use the refcount stuff
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar ICUServiceKey::PREFIX_DELIMITER = 0x002F;   /* '/' */
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::ICUServiceKey(const UnicodeString& id)
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: _id(id) {
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::~ICUServiceKey()
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UnicodeString&
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::getID() const
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return _id;
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::canonicalID(UnicodeString& result) const
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result.append(_id);
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::currentID(UnicodeString& result) const
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return canonicalID(result);
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::currentDescriptor(UnicodeString& result) const
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    prefix(result);
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.append(PREFIX_DELIMITER);
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return currentID(result);
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::fallback()
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::isFallbackOf(const UnicodeString& id) const
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return id == _id;
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::prefix(UnicodeString& result) const
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::parsePrefix(UnicodeString& result)
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t n = result.indexOf(PREFIX_DELIMITER);
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (n < 0) {
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        n = 0;
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.remove(n);
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::parseSuffix(UnicodeString& result)
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t n = result.indexOf(PREFIX_DELIMITER);
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (n >= 0) {
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.remove(0, n+1);
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef SERVICE_DEBUG
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::debug(UnicodeString& result) const
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    debugClass(result);
1051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    result.append((UnicodeString)" id: ");
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.append(_id);
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey::debugClass(UnicodeString& result) const
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    return result.append((UnicodeString)"ICUServiceKey");
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(ICUServiceKey)
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusICUServiceFactory::~ICUServiceFactory() {}
124103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::SimpleFactory(UObject* instanceToAdopt, const UnicodeString& id, UBool visible)
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: _instance(instanceToAdopt), _id(id), _visible(visible)
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::~SimpleFactory()
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete _instance;
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString temp;
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (_id == key.currentID(temp)) {
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return service->cloneInstance(_instance);
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::updateVisibleIDs(Hashtable& result, UErrorCode& status) const
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (_visible) {
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.put(_id, (void*)this, status); // cast away const
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.remove(_id);
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::getDisplayName(const UnicodeString& id, const Locale& /* locale */, UnicodeString& result) const
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (_visible && _id == id) {
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = _id;
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.setToBogus();
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef SERVICE_DEBUG
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::debug(UnicodeString& toAppendTo) const
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    debugClass(toAppendTo);
1731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    toAppendTo.append((UnicodeString)" id: ");
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    toAppendTo.append(_id);
1751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    toAppendTo.append((UnicodeString)", visible: ");
1761b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    toAppendTo.append(_visible ? (UnicodeString)"T" : (UnicodeString)"F");
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSimpleFactory::debugClass(UnicodeString& toAppendTo) const
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    return toAppendTo.append((UnicodeString)"SimpleFactory");
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleFactory)
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
193103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusServiceListener::~ServiceListener() {}
194103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceListener)
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Record the actual id for this service in the cache, so we can return it
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// even if we succeed later with a different id.
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass CacheEntry : public UMemory {
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t refcount;
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString actualDescriptor;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UObject* service;
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /**
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Releases a reference to the shared resource.
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~CacheEntry() {
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete service;
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CacheEntry(const UnicodeString& _actualDescriptor, UObject* _service)
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : refcount(1), actualDescriptor(_actualDescriptor), service(_service) {
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /**
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Instantiation creates an initial reference, so don't call this
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * unless you're creating a new pointer to this.  Management of
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * that pointer will have to know how to deal with refcounts.
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Return true if the resource has not already been released.
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CacheEntry* ref() {
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++refcount;
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return this;
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /**
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Destructions removes a reference, so don't call this unless
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * you're removing pointer to this somewhere.  Management of that
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * pointer will have to know how to deal with refcounts.  Once
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * the refcount drops to zero, the resource is released.  Return
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * false if the resouce has been released.
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CacheEntry* unref() {
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ((--refcount) == 0) {
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete this;
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return this;
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /**
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Return TRUE if there is at least one reference to this and the
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * resource has not been released.
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool isShared() const {
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return refcount > 1;
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// UObjectDeleter for serviceCache
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_BEGIN
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void U_CALLCONV
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerucacheDeleter(void* obj) {
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_NAMESPACE_USE ((CacheEntry*)obj)->unref();
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Deleter for UObjects
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void U_CALLCONV
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerudeleteUObject(void *obj) {
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_NAMESPACE_USE delete (UObject*) obj;
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_END
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass DNCache : public UMemory {
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Hashtable cache;
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const Locale locale;
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DNCache(const Locale& _locale)
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : cache(), locale(_locale)
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
285103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // cache.setKeyDeleter(uprv_deleteUObject);
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringPair*
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringPair::create(const UnicodeString& displayName,
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   const UnicodeString& id,
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UErrorCode& status)
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        StringPair* sp = new StringPair(displayName, id);
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (sp == NULL || sp->isBogus()) {
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete sp;
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return sp;
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringPair::isBogus() const {
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return displayName.isBogus() || id.isBogus();
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringPair::StringPair(const UnicodeString& _displayName,
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                       const UnicodeString& _id)
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: displayName(_displayName)
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, id(_id)
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_BEGIN
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void U_CALLCONV
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruuserv_deleteStringPair(void *obj) {
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_NAMESPACE_USE delete (StringPair*) obj;
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_END
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
33454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex lock = U_MUTEX_INITIALIZER;
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::ICUService()
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: name()
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, timestamp(0)
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, factories(NULL)
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, serviceCache(NULL)
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, idCache(NULL)
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, dnCache(NULL)
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::ICUService(const UnicodeString& newName)
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: name(newName)
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, timestamp(0)
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, factories(NULL)
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, serviceCache(NULL)
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, idCache(NULL)
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru, dnCache(NULL)
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::~ICUService()
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Mutex mutex(&lock);
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        clearCaches();
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete factories;
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        factories = NULL;
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::get(const UnicodeString& descriptor, UErrorCode& status) const
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return get(descriptor, NULL, status);
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::get(const UnicodeString& descriptor, UnicodeString* actualReturn, UErrorCode& status) const
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UObject* result = NULL;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ICUServiceKey* key = createKey(&descriptor, status);
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (key) {
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = getKey(*key, actualReturn, status);
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete key;
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getKey(ICUServiceKey& key, UErrorCode& status) const
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return getKey(key, NULL, status);
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// this is a vector that subclasses of ICUService can override to further customize the result object
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// before returning it.  All other public get functions should call this one.
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return getKey(key, actualReturn, NULL, status);
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// make it possible to call reentrantly on systems that don't have reentrant mutexes.
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// we can use this simple approach since we know the situation where we're calling
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// reentrantly even without knowing the thread.
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass XMutex : public UMemory {
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
40454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    inline XMutex(UMutex *mutex, UBool reentering)
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : fMutex(mutex)
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        , fActive(!reentering)
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fActive) umtx_lock(fMutex);
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline ~XMutex() {
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fActive) umtx_unlock(fMutex);
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
41554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UMutex  *fMutex;
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool fActive;
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct UVectorDeleter {
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UVector* _obj;
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UVectorDeleter() : _obj(NULL) {}
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~UVectorDeleter() { delete _obj; }
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// called only by factories, treat as private
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUServiceFactory* factory, UErrorCode& status) const
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (isDefault()) {
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return handleDefault(key, actualReturn, status);
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ICUService* ncthis = (ICUService*)this; // cast away semantic const
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CacheEntry* result = NULL;
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // The factory list can't be modified until we're done,
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // otherwise we might update the cache with an invalid result.
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // The cache has to stay in synch with the factory list.
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // ICU doesn't have monitors so we can't use rw locks, so
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we single-thread everything using this service, for now.
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // if factory is not null, we're calling from within the mutex,
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // and since some unix machines don't have reentrant mutexes we
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // need to make sure not to try to lock it again.
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        XMutex mutex(&lock, factory != NULL);
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (serviceCache == NULL) {
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ncthis->serviceCache = new Hashtable(status);
45485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (ncthis->serviceCache == NULL) {
45585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                return NULL;
45685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (U_FAILURE(status)) {
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                delete serviceCache;
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            serviceCache->setValueDeleter(cacheDeleter);
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString currentDescriptor;
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UVectorDeleter cacheDescriptorList;
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool putInCache = FALSE;
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t startIndex = 0;
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t limit = factories->size();
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool cacheResult = TRUE;
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (factory != NULL) {
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int32_t i = 0; i < limit; ++i) {
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (factory == (const ICUServiceFactory*)factories->elementAt(i)) {
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    startIndex = i + 1;
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (startIndex == 0) {
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // throw new InternalError("Factory " + factory + "not registered with service: " + this);
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_ILLEGAL_ARGUMENT_ERROR;
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cacheResult = FALSE;
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        do {
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            currentDescriptor.remove();
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            key.currentDescriptor(currentDescriptor);
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = (CacheEntry*)serviceCache->get(currentDescriptor);
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (result != NULL) {
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // first test of cache failed, so we'll have to update
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the cache if we eventually succeed-- that is, if we're
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // going to update the cache at all.
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            putInCache = TRUE;
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t index = startIndex;
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (index < limit) {
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++);
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UObject* service = f->create(key, this, status);
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (U_FAILURE(status)) {
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    delete service;
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return NULL;
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (service != NULL) {
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    result = new CacheEntry(currentDescriptor, service);
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (result == NULL) {
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        delete service;
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        status = U_MEMORY_ALLOCATION_ERROR;
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        return NULL;
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    goto outerEnd;
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // prepare to load the cache with all additional ids that
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // will resolve to result, assuming we'll succeed.  We
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // don't want to keep querying on an id that's going to
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // fallback to the one that succeeded, we want to hit the
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // cache the first time next goaround.
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (cacheDescriptorList._obj == NULL) {
526103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                cacheDescriptorList._obj = new UVector(uprv_deleteUObject, NULL, 5, status);
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (U_FAILURE(status)) {
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return NULL;
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UnicodeString* idToCache = new UnicodeString(currentDescriptor);
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (idToCache == NULL || idToCache->isBogus()) {
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cacheDescriptorList._obj->addElement(idToCache, status);
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (U_FAILURE(status)) {
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } while (key.fallback());
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruouterEnd:
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result != NULL) {
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (putInCache && cacheResult) {
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                serviceCache->put(result->actualDescriptor, result, status);
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (U_FAILURE(status)) {
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    delete result;
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return NULL;
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (cacheDescriptorList._obj != NULL) {
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) {
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i);
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        serviceCache->put(*desc, result, status);
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (U_FAILURE(status)) {
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            delete result;
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            return NULL;
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        result->ref();
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cacheDescriptorList._obj->removeElementAt(i);
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (actualReturn != NULL) {
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // strip null prefix
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (result->actualDescriptor.indexOf((UChar)0x2f) == 0) { // U+002f=slash (/)
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    actualReturn->remove();
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    actualReturn->append(result->actualDescriptor,
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        1,
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        result->actualDescriptor.length() - 1);
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *actualReturn = result->actualDescriptor;
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (actualReturn->isBogus()) {
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    status = U_MEMORY_ALLOCATION_ERROR;
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    delete result;
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return NULL;
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UObject* service = cloneInstance(result->service);
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (putInCache && !cacheResult) {
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                delete result;
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return service;
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return handleDefault(key, actualReturn, status);
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUObject*
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::handleDefault(const ICUServiceKey& /* key */, UnicodeString* /* actualIDReturn */, UErrorCode& /* status */) const
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUVector&
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getVisibleIDs(UVector& result, UErrorCode& status) const {
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return getVisibleIDs(result, NULL, status);
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUVector&
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorCode& status) const
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.removeAllElements();
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return result;
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Mutex mutex(&lock);
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const Hashtable* map = getVisibleIDMap(status);
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (map != NULL) {
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ICUServiceKey* fallbackKey = createKey(matchID, status);
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            for (int32_t pos = UHASH_FIRST;;) {
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const UHashElement* e = map->nextElement(pos);
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (e == NULL) {
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const UnicodeString* id = (const UnicodeString*)e->key.pointer;
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (fallbackKey != NULL) {
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (!fallbackKey->isFallbackOf(*id)) {
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        continue;
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString* idClone = new UnicodeString(*id);
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (idClone == NULL || idClone->isBogus()) {
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    delete idClone;
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    status = U_MEMORY_ALLOCATION_ERROR;
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                result.addElement(idClone, status);
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (U_FAILURE(status)) {
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    delete idClone;
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete fallbackKey;
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.removeAllElements();
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst Hashtable*
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getVisibleIDMap(UErrorCode& status) const {
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) return NULL;
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // must only be called when lock is already held
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ICUService* ncthis = (ICUService*)this; // cast away semantic const
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (idCache == NULL) {
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ncthis->idCache = new Hashtable(status);
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (idCache == NULL) {
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (factories != NULL) {
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int32_t pos = factories->size(); --pos >= 0;) {
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(pos);
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                f->updateVisibleIDs(*idCache, status);
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (U_FAILURE(status)) {
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                delete idCache;
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ncthis->idCache = NULL;
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return idCache;
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getDisplayName(const UnicodeString& id, UnicodeString& result) const
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return getDisplayName(id, result, Locale::getDefault());
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const Locale& locale) const
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
694b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Mutex mutex(&lock);
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const Hashtable* map = getVisibleIDMap(status);
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (map != NULL) {
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ICUServiceFactory* f = (ICUServiceFactory*)map->get(id);
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (f != NULL) {
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                f->getDisplayName(id, locale, result);
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return result;
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // fallback
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UErrorCode status = U_ZERO_ERROR;
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ICUServiceKey* fallbackKey = createKey(&id, status);
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (fallbackKey->fallback()) {
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString us;
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fallbackKey->currentID(us);
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                f = (ICUServiceFactory*)map->get(us);
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (f != NULL) {
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    f->getDisplayName(id, locale, result);
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    delete fallbackKey;
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return result;
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete fallbackKey;
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.setToBogus();
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUVector&
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getDisplayNames(UVector& result, UErrorCode& status) const
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return getDisplayNames(result, Locale::getDefault(), NULL, status);
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUVector&
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getDisplayNames(UVector& result, const Locale& locale, UErrorCode& status) const
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return getDisplayNames(result, locale, NULL, status);
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUVector&
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getDisplayNames(UVector& result,
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const Locale& locale,
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            const UnicodeString* matchID,
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode& status) const
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.removeAllElements();
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.setDeleter(userv_deleteStringPair);
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ICUService* ncthis = (ICUService*)this; // cast away semantic const
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Mutex mutex(&lock);
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (dnCache != NULL && dnCache->locale != locale) {
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete dnCache;
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ncthis->dnCache = NULL;
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (dnCache == NULL) {
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const Hashtable* m = getVisibleIDMap(status);
755103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (U_FAILURE(status)) {
756103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                return result;
757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
758103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            ncthis->dnCache = new DNCache(locale);
759103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (dnCache == NULL) {
760103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                status = U_MEMORY_ALLOCATION_ERROR;
761103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                return result;
762103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            int32_t pos = UHASH_FIRST;
765103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            const UHashElement* entry = NULL;
766103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            while ((entry = m->nextElement(pos)) != NULL) {
767103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                const UnicodeString* id = (const UnicodeString*)entry->key.pointer;
768103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                ICUServiceFactory* f = (ICUServiceFactory*)entry->value.pointer;
769103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                UnicodeString dname;
770103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                f->getDisplayName(*id, locale, dname);
771103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                if (dname.isBogus()) {
772103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    status = U_MEMORY_ALLOCATION_ERROR;
773103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                } else {
774103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    dnCache->cache.put(dname, (void*)id, status); // share pointer with visibleIDMap
775103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    if (U_SUCCESS(status)) {
776103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        continue;
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
779103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                delete dnCache;
780103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                ncthis->dnCache = NULL;
781103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                return result;
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ICUServiceKey* matchKey = createKey(matchID, status);
78785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* To ensure that all elements in the hashtable are iterated, set pos to -1.
78885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * nextElement(pos) will skip the position at pos and begin the iteration
78985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * at the next position, which in this case will be 0.
79085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     */
7911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    int32_t pos = UHASH_FIRST;
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UHashElement *entry = NULL;
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while ((entry = dnCache->cache.nextElement(pos)) != NULL) {
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UnicodeString* id = (const UnicodeString*)entry->value.pointer;
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (matchKey != NULL && !matchKey->isFallbackOf(*id)) {
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue;
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UnicodeString* dn = (const UnicodeString*)entry->key.pointer;
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        StringPair* sp = StringPair::create(*id, *dn, status);
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.addElement(sp, status);
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE(status)) {
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result.removeAllElements();
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete matchKey;
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruURegistryKey
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::registerInstance(UObject* objToAdopt, const UnicodeString& id, UErrorCode& status)
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return registerInstance(objToAdopt, id, TRUE, status);
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruURegistryKey
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::registerInstance(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status)
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ICUServiceKey* key = createKey(&id, status);
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (key != NULL) {
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString canonicalID;
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        key->canonicalID(canonicalID);
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete key;
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ICUServiceFactory* f = createSimpleFactory(objToAdopt, canonicalID, visible, status);
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (f != NULL) {
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return registerFactory(f, status);
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete objToAdopt;
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceFactory*
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::createSimpleFactory(UObject* objToAdopt, const UnicodeString& id, UBool visible, UErrorCode& status)
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ((objToAdopt != NULL) && (!id.isBogus())) {
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return new SimpleFactory(objToAdopt, id, visible);
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruURegistryKey
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status)
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status) && factoryToAdopt != NULL) {
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Mutex mutex(&lock);
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (factories == NULL) {
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            factories = new UVector(deleteUObject, NULL, status);
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (U_FAILURE(status)) {
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                delete factories;
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return NULL;
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        factories->insertElementAt(factoryToAdopt, 0, status);
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(status)) {
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            clearCaches();
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete factoryToAdopt;
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            factoryToAdopt = NULL;
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (factoryToAdopt != NULL) {
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        notifyChanged();
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (URegistryKey)factoryToAdopt;
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::unregister(URegistryKey rkey, UErrorCode& status)
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ICUServiceFactory *factory = (ICUServiceFactory*)rkey;
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool result = FALSE;
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (factory != NULL && factories != NULL) {
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Mutex mutex(&lock);
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (factories->removeElement(factory)) {
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            clearCaches();
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = TRUE;
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete factory;
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result) {
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        notifyChanged();
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::reset()
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Mutex mutex(&lock);
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        reInitializeFactories();
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        clearCaches();
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    notifyChanged();
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::reInitializeFactories()
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (factories != NULL) {
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        factories->removeAllElements();
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::isDefault() const
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return countFactories() == 0;
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUServiceKey*
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::createKey(const UnicodeString* id, UErrorCode& status) const
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (U_FAILURE(status) || id == NULL) ? NULL : new ICUServiceKey(*id);
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::clearCaches()
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // callers synchronize before use
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ++timestamp;
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete dnCache;
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dnCache = NULL;
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete idCache;
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    idCache = NULL;
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete serviceCache; serviceCache = NULL;
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::clearServiceCache()
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // callers synchronize before use
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete serviceCache; serviceCache = NULL;
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::acceptsListener(const EventListener& l) const
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
95127f654740f2a26ad62a5c155af9199af9e69b889claireho    return dynamic_cast<const ServiceListener*>(&l) != NULL;
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::notifyListener(EventListener& l) const
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ((ServiceListener&)l).serviceChanged(*this);
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getName(UnicodeString& result) const
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result.append(name);
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::countFactories() const
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return factories == NULL ? 0 : factories->size();
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruICUService::getTimestamp() const
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return timestamp;
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* UCONFIG_NO_SERVICE */
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
982