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;
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;
120 
121     /**
122      * Return the currentID.
123      */
124     virtual UnicodeString& currentID(UnicodeString& result) const;
125 
126     /**
127      * Return the (canonical) current descriptor, or null if no current id.
128      */
129     virtual UnicodeString& currentDescriptor(UnicodeString& result) const;
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();
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;
157 
158  public:
159     /**
160      * UObject boilerplate.
161      */
162     static UClassID U_EXPORT2 getStaticClassID();
163 
164     virtual UClassID getDynamicClassID() const;
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;
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;
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;
257 
258 protected:
259     /**
260      * Utility method used by create(ICUServiceKey, ICUService).  Subclasses can implement
261      * this instead of create.  The default returns NULL.
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;
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;
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;
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;
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;
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;
404 
405 public:
406     /**
407      * UObject boilerplate.
408      */
409     static UClassID U_EXPORT2 getStaticClassID();
410     virtual UClassID getDynamicClassID() const;
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);
516 
517   /**
518    * Convenience method for callers using locales.  This returns the standard
519    * service ID enumeration.
520    */
521   virtual StringEnumeration* getAvailableLocales(void) 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;
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