Home | History | Annotate | Download | only in common
      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