1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html |
3 | /** |
4 | ******************************************************************************* |
5 | * Copyright (C) 2001-2011, International Business Machines Corporation and * |
6 | * others. All Rights Reserved. * |
7 | ******************************************************************************* |
8 | * |
9 | ******************************************************************************* |
10 | */ |
11 | #ifndef ICULSERV_H |
12 | #define ICULSERV_H |
13 | |
14 | #include "unicode/utypes.h" |
15 | |
16 | #if UCONFIG_NO_SERVICE |
17 | |
18 | U_NAMESPACE_BEGIN |
19 | |
20 | /* |
21 | * Allow the declaration of APIs with pointers to ICUService |
22 | * even when service is removed from the build. |
23 | */ |
24 | class ICULocaleService; |
25 | |
26 | U_NAMESPACE_END |
27 | |
28 | #else |
29 | |
30 | #include "unicode/unistr.h" |
31 | #include "unicode/locid.h" |
32 | #include "unicode/strenum.h" |
33 | |
34 | #include "hash.h" |
35 | #include "uvector.h" |
36 | |
37 | #include "serv.h" |
38 | #include "locutil.h" |
39 | |
40 | U_NAMESPACE_BEGIN |
41 | |
42 | class ICULocaleService; |
43 | |
44 | class LocaleKey; |
45 | class LocaleKeyFactory; |
46 | class SimpleLocaleKeyFactory; |
47 | class ServiceListener; |
48 | |
49 | /* |
50 | ****************************************************************** |
51 | */ |
52 | |
53 | /** |
54 | * A subclass of Key that implements a locale fallback mechanism. |
55 | * The first locale to search for is the locale provided by the |
56 | * client, and the fallback locale to search for is the current |
57 | * default locale. If a prefix is present, the currentDescriptor |
58 | * includes it before the locale proper, separated by "/". This |
59 | * is the default key instantiated by ICULocaleService.</p> |
60 | * |
61 | * <p>Canonicalization adjusts the locale string so that the |
62 | * section before the first understore is in lower case, and the rest |
63 | * is in upper case, with no trailing underscores.</p> |
64 | */ |
65 | |
66 | class U_COMMON_API LocaleKey : public ICUServiceKey { |
67 | private: |
68 | int32_t _kind; |
69 | UnicodeString _primaryID; |
70 | UnicodeString _fallbackID; |
71 | UnicodeString _currentID; |
72 | |
73 | public: |
74 | enum { |
75 | KIND_ANY = -1 |
76 | }; |
77 | |
78 | /** |
79 | * Create a LocaleKey with canonical primary and fallback IDs. |
80 | */ |
81 | static LocaleKey* createWithCanonicalFallback(const UnicodeString* primaryID, |
82 | const UnicodeString* canonicalFallbackID, |
83 | UErrorCode& status); |
84 | |
85 | /** |
86 | * Create a LocaleKey with canonical primary and fallback IDs. |
87 | */ |
88 | static LocaleKey* createWithCanonicalFallback(const UnicodeString* primaryID, |
89 | const UnicodeString* canonicalFallbackID, |
90 | int32_t kind, |
91 | UErrorCode& status); |
92 | |
93 | protected: |
94 | /** |
95 | * PrimaryID is the user's requested locale string, |
96 | * canonicalPrimaryID is this string in canonical form, |
97 | * fallbackID is the current default locale's string in |
98 | * canonical form. |
99 | */ |
100 | LocaleKey(const UnicodeString& primaryID, |
101 | const UnicodeString& canonicalPrimaryID, |
102 | const UnicodeString* canonicalFallbackID, |
103 | int32_t kind); |
104 | |
105 | public: |
106 | /** |
107 | * Append the prefix associated with the kind, or nothing if the kind is KIND_ANY. |
108 | */ |
109 | virtual UnicodeString& prefix(UnicodeString& result) const override; |
110 | |
111 | /** |
112 | * Return the kind code associated with this key. |
113 | */ |
114 | virtual int32_t kind() const; |
115 | |
116 | /** |
117 | * Return the canonicalID. |
118 | */ |
119 | virtual UnicodeString& canonicalID(UnicodeString& result) const override; |
120 | |
121 | /** |
122 | * Return the currentID. |
123 | */ |
124 | virtual UnicodeString& currentID(UnicodeString& result) const override; |
125 | |
126 | /** |
127 | * Return the (canonical) current descriptor, or null if no current id. |
128 | */ |
129 | virtual UnicodeString& currentDescriptor(UnicodeString& result) const override; |
130 | |
131 | /** |
132 | * Convenience method to return the locale corresponding to the (canonical) original ID. |
133 | */ |
134 | virtual Locale& canonicalLocale(Locale& result) const; |
135 | |
136 | /** |
137 | * Convenience method to return the locale corresponding to the (canonical) current ID. |
138 | */ |
139 | virtual Locale& currentLocale(Locale& result) const; |
140 | |
141 | /** |
142 | * If the key has a fallback, modify the key and return true, |
143 | * otherwise return false.</p> |
144 | * |
145 | * <p>First falls back through the primary ID, then through |
146 | * the fallbackID. The final fallback is the empty string, |
147 | * unless the primary id was the empty string, in which case |
148 | * there is no fallback. |
149 | */ |
150 | virtual UBool fallback() override; |
151 | |
152 | /** |
153 | * Return true if a key created from id matches, or would eventually |
154 | * fallback to match, the canonical ID of this key. |
155 | */ |
156 | virtual UBool isFallbackOf(const UnicodeString& id) const override; |
157 | |
158 | public: |
159 | /** |
160 | * UObject boilerplate. |
161 | */ |
162 | static UClassID U_EXPORT2 getStaticClassID(); |
163 | |
164 | virtual UClassID getDynamicClassID() const override; |
165 | |
166 | /** |
167 | * Destructor. |
168 | */ |
169 | virtual ~LocaleKey(); |
170 | |
171 | #ifdef SERVICE_DEBUG |
172 | public: |
173 | virtual UnicodeString& debug(UnicodeString& result) const; |
174 | virtual UnicodeString& debugClass(UnicodeString& result) const; |
175 | #endif |
176 | |
177 | }; |
178 | |
179 | /* |
180 | ****************************************************************** |
181 | */ |
182 | |
183 | /** |
184 | * A subclass of ICUServiceFactory that uses LocaleKeys, and is able to |
185 | * 'cover' more specific locales with more general locales that it |
186 | * supports. |
187 | * |
188 | * <p>Coverage may be either of the values VISIBLE or INVISIBLE. |
189 | * |
190 | * <p>'Visible' indicates that the specific locale(s) supported by |
191 | * the factory are registered in getSupportedIDs, 'Invisible' |
192 | * indicates that they are not. |
193 | * |
194 | * <p>Localization of visible ids is handled |
195 | * by the handling factory, regardless of kind. |
196 | */ |
197 | class U_COMMON_API LocaleKeyFactory : public ICUServiceFactory { |
198 | protected: |
199 | const UnicodeString _name; |
200 | const int32_t _coverage; |
201 | |
202 | public: |
203 | enum { |
204 | /** |
205 | * Coverage value indicating that the factory makes |
206 | * its locales visible, and does not cover more specific |
207 | * locales. |
208 | */ |
209 | VISIBLE = 0, |
210 | |
211 | /** |
212 | * Coverage value indicating that the factory does not make |
213 | * its locales visible, and does not cover more specific |
214 | * locales. |
215 | */ |
216 | INVISIBLE = 1 |
217 | }; |
218 | |
219 | /** |
220 | * Destructor. |
221 | */ |
222 | virtual ~LocaleKeyFactory(); |
223 | |
224 | protected: |
225 | /** |
226 | * Constructor used by subclasses. |
227 | */ |
228 | LocaleKeyFactory(int32_t coverage); |
229 | |
230 | /** |
231 | * Constructor used by subclasses. |
232 | */ |
233 | LocaleKeyFactory(int32_t coverage, const UnicodeString& name); |
234 | |
235 | /** |
236 | * Implement superclass abstract method. This checks the currentID of |
237 | * the key against the supported IDs, and passes the canonicalLocale and |
238 | * kind off to handleCreate (which subclasses must implement). |
239 | */ |
240 | public: |
241 | virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const override; |
242 | |
243 | protected: |
244 | virtual UBool handlesKey(const ICUServiceKey& key, UErrorCode& status) const; |
245 | |
246 | public: |
247 | /** |
248 | * Override of superclass method. This adjusts the result based |
249 | * on the coverage rule for this factory. |
250 | */ |
251 | virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const override; |
252 | |
253 | /** |
254 | * Return a localized name for the locale represented by id. |
255 | */ |
256 | virtual UnicodeString& getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const override; |
257 | |
258 | protected: |
259 | /** |
260 | * Utility method used by create(ICUServiceKey, ICUService). Subclasses can implement |
261 | * this instead of create. The default returns nullptr. |
262 | */ |
263 | virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* service, UErrorCode& status) const; |
264 | |
265 | /** |
266 | * Return true if this id is one the factory supports (visible or |
267 | * otherwise). |
268 | */ |
269 | // virtual UBool isSupportedID(const UnicodeString& id, UErrorCode& status) const; |
270 | |
271 | /** |
272 | * Return the set of ids that this factory supports (visible or |
273 | * otherwise). This can be called often and might need to be |
274 | * cached if it is expensive to create. |
275 | */ |
276 | virtual const Hashtable* getSupportedIDs(UErrorCode& status) const; |
277 | |
278 | public: |
279 | /** |
280 | * UObject boilerplate. |
281 | */ |
282 | static UClassID U_EXPORT2 getStaticClassID(); |
283 | |
284 | virtual UClassID getDynamicClassID() const override; |
285 | |
286 | #ifdef SERVICE_DEBUG |
287 | public: |
288 | virtual UnicodeString& debug(UnicodeString& result) const; |
289 | virtual UnicodeString& debugClass(UnicodeString& result) const; |
290 | #endif |
291 | |
292 | }; |
293 | |
294 | /* |
295 | ****************************************************************** |
296 | */ |
297 | |
298 | /** |
299 | * A LocaleKeyFactory that just returns a single object for a kind/locale. |
300 | */ |
301 | |
302 | class U_COMMON_API SimpleLocaleKeyFactory : public LocaleKeyFactory { |
303 | private: |
304 | UObject* _obj; |
305 | UnicodeString _id; |
306 | const int32_t _kind; |
307 | |
308 | public: |
309 | SimpleLocaleKeyFactory(UObject* objToAdopt, |
310 | const UnicodeString& locale, |
311 | int32_t kind, |
312 | int32_t coverage); |
313 | |
314 | SimpleLocaleKeyFactory(UObject* objToAdopt, |
315 | const Locale& locale, |
316 | int32_t kind, |
317 | int32_t coverage); |
318 | |
319 | /** |
320 | * Destructor. |
321 | */ |
322 | virtual ~SimpleLocaleKeyFactory(); |
323 | |
324 | /** |
325 | * Override of superclass method. Returns the service object if kind/locale match. Service is not used. |
326 | */ |
327 | virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const override; |
328 | |
329 | /** |
330 | * Override of superclass method. This adjusts the result based |
331 | * on the coverage rule for this factory. |
332 | */ |
333 | virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const override; |
334 | |
335 | protected: |
336 | /** |
337 | * Return true if this id is equal to the locale name. |
338 | */ |
339 | //virtual UBool isSupportedID(const UnicodeString& id, UErrorCode& status) const; |
340 | |
341 | |
342 | public: |
343 | /** |
344 | * UObject boilerplate. |
345 | */ |
346 | static UClassID U_EXPORT2 getStaticClassID(); |
347 | |
348 | virtual UClassID getDynamicClassID() const override; |
349 | |
350 | #ifdef SERVICE_DEBUG |
351 | public: |
352 | virtual UnicodeString& debug(UnicodeString& result) const; |
353 | virtual UnicodeString& debugClass(UnicodeString& result) const; |
354 | #endif |
355 | |
356 | }; |
357 | |
358 | /* |
359 | ****************************************************************** |
360 | */ |
361 | |
362 | /** |
363 | * A LocaleKeyFactory that creates a service based on the ICU locale data. |
364 | * This is a base class for most ICU factories. Subclasses instantiate it |
365 | * with a constructor that takes a bundle name, which determines the supported |
366 | * IDs. Subclasses then override handleCreate to create the actual service |
367 | * object. The default implementation returns a resource bundle. |
368 | */ |
369 | class U_COMMON_API ICUResourceBundleFactory : public LocaleKeyFactory |
370 | { |
371 | protected: |
372 | UnicodeString _bundleName; |
373 | |
374 | public: |
375 | /** |
376 | * Convenience constructor that uses the main ICU bundle name. |
377 | */ |
378 | ICUResourceBundleFactory(); |
379 | |
380 | /** |
381 | * A service factory based on ICU resource data in resources with |
382 | * the given name. This should be a 'path' that can be passed to |
383 | * ures_openAvailableLocales, such as U_ICUDATA or U_ICUDATA_COLL. |
384 | * The empty string is equivalent to U_ICUDATA. |
385 | */ |
386 | ICUResourceBundleFactory(const UnicodeString& bundleName); |
387 | |
388 | /** |
389 | * Destructor |
390 | */ |
391 | virtual ~ICUResourceBundleFactory(); |
392 | |
393 | protected: |
394 | /** |
395 | * Return the supported IDs. This is the set of all locale names in ICULocaleData. |
396 | */ |
397 | virtual const Hashtable* getSupportedIDs(UErrorCode& status) const override; |
398 | |
399 | /** |
400 | * Create the service. The default implementation returns the resource bundle |
401 | * for the locale, ignoring kind, and service. |
402 | */ |
403 | virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* service, UErrorCode& status) const override; |
404 | |
405 | public: |
406 | /** |
407 | * UObject boilerplate. |
408 | */ |
409 | static UClassID U_EXPORT2 getStaticClassID(); |
410 | virtual UClassID getDynamicClassID() const override; |
411 | |
412 | |
413 | #ifdef SERVICE_DEBUG |
414 | public: |
415 | virtual UnicodeString& debug(UnicodeString& result) const; |
416 | virtual UnicodeString& debugClass(UnicodeString& result) const; |
417 | #endif |
418 | |
419 | }; |
420 | |
421 | /* |
422 | ****************************************************************** |
423 | */ |
424 | |
425 | class U_COMMON_API ICULocaleService : public ICUService |
426 | { |
427 | private: |
428 | Locale fallbackLocale; |
429 | UnicodeString fallbackLocaleName; |
430 | |
431 | public: |
432 | /** |
433 | * Construct an ICULocaleService. |
434 | */ |
435 | ICULocaleService(); |
436 | |
437 | /** |
438 | * Construct an ICULocaleService with a name (useful for debugging). |
439 | */ |
440 | ICULocaleService(const UnicodeString& name); |
441 | |
442 | /** |
443 | * Destructor. |
444 | */ |
445 | virtual ~ICULocaleService(); |
446 | |
447 | #if 0 |
448 | // redeclare because of overload resolution rules? |
449 | // no, causes ambiguities since both UnicodeString and Locale have constructors that take a const char* |
450 | // need some compiler flag to remove warnings |
451 | UObject* get(const UnicodeString& descriptor, UErrorCode& status) const { |
452 | return ICUService::get(descriptor, status); |
453 | } |
454 | |
455 | UObject* get(const UnicodeString& descriptor, UnicodeString* actualReturn, UErrorCode& status) const { |
456 | return ICUService::get(descriptor, actualReturn, status); |
457 | } |
458 | #endif |
459 | |
460 | /** |
461 | * Convenience override for callers using locales. This calls |
462 | * get(Locale, int, Locale[]) with KIND_ANY for kind and null for |
463 | * actualReturn. |
464 | */ |
465 | UObject* get(const Locale& locale, UErrorCode& status) const; |
466 | |
467 | /** |
468 | * Convenience override for callers using locales. This calls |
469 | * get(Locale, int, Locale[]) with a null actualReturn. |
470 | */ |
471 | UObject* get(const Locale& locale, int32_t kind, UErrorCode& status) const; |
472 | |
473 | /** |
474 | * Convenience override for callers using locales. This calls |
475 | * get(Locale, String, Locale[]) with a null kind. |
476 | */ |
477 | UObject* get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const; |
478 | |
479 | /** |
480 | * Convenience override for callers using locales. This uses |
481 | * createKey(Locale.toString(), kind) to create a key, calls getKey, and then |
482 | * if actualReturn is not null, returns the actualResult from |
483 | * getKey (stripping any prefix) into a Locale. |
484 | */ |
485 | UObject* get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const; |
486 | |
487 | /** |
488 | * Convenience override for callers using locales. This calls |
489 | * registerObject(Object, Locale, int32_t kind, int coverage) |
490 | * passing KIND_ANY for the kind, and VISIBLE for the coverage. |
491 | */ |
492 | virtual URegistryKey registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status); |
493 | |
494 | /** |
495 | * Convenience function for callers using locales. This calls |
496 | * registerObject(Object, Locale, int kind, int coverage) |
497 | * passing VISIBLE for the coverage. |
498 | */ |
499 | virtual URegistryKey registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status); |
500 | |
501 | /** |
502 | * Convenience function for callers using locales. This instantiates |
503 | * a SimpleLocaleKeyFactory, and registers the factory. |
504 | */ |
505 | virtual URegistryKey registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status); |
506 | |
507 | |
508 | /** |
509 | * (Stop compiler from complaining about hidden overrides.) |
510 | * Since both UnicodeString and Locale have constructors that take const char*, adding a public |
511 | * method that takes UnicodeString causes ambiguity at call sites that use const char*. |
512 | * We really need a flag that is understood by all compilers that will suppress the warning about |
513 | * hidden overrides. |
514 | */ |
515 | virtual URegistryKey registerInstance(UObject* objToAdopt, const UnicodeString& locale, UBool visible, UErrorCode& status) override; |
516 | |
517 | /** |
518 | * Convenience method for callers using locales. This returns the standard |
519 | * service ID enumeration. |
520 | */ |
521 | virtual StringEnumeration* getAvailableLocales() const; |
522 | |
523 | protected: |
524 | |
525 | /** |
526 | * Return the name of the current fallback locale. If it has changed since this was |
527 | * last accessed, the service cache is cleared. |
528 | */ |
529 | const UnicodeString& validateFallbackLocale() const; |
530 | |
531 | /** |
532 | * Override superclass createKey method. |
533 | */ |
534 | virtual ICUServiceKey* createKey(const UnicodeString* id, UErrorCode& status) const override; |
535 | |
536 | /** |
537 | * Additional createKey that takes a kind. |
538 | */ |
539 | virtual ICUServiceKey* createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const; |
540 | |
541 | friend class ServiceEnumeration; |
542 | }; |
543 | |
544 | U_NAMESPACE_END |
545 | |
546 | /* UCONFIG_NO_SERVICE */ |
547 | #endif |
548 | |
549 | /* ICULSERV_H */ |
550 | #endif |
551 | |
552 | |