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