• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /**
5  *******************************************************************************
6  * Copyright (C) 2001-2016, International Business Machines Corporation and
7  * others. All Rights Reserved.
8  *******************************************************************************
9  */
10 package ohos.global.icu.impl;
11 
12 import java.util.Collections;
13 import java.util.Locale;
14 import java.util.Map;
15 import java.util.Set;
16 
17 import ohos.global.icu.util.ULocale;
18 
19 /**
20  * @hide exposed on OHOS
21  */
22 public class ICULocaleService extends ICUService {
23     private ULocale fallbackLocale;
24     private String fallbackLocaleName;
25 
26     /**
27      * Construct an ICULocaleService.
28      */
ICULocaleService()29     public ICULocaleService() {
30     }
31 
32     /**
33      * Construct an ICULocaleService with a name (useful for debugging).
34      */
ICULocaleService(String name)35     public ICULocaleService(String name) {
36         super(name);
37     }
38 
39     /**
40      * Convenience override for callers using locales.  This calls
41      * get(ULocale, int, ULocale[]) with KIND_ANY for kind and null for
42      * actualReturn.
43      */
get(ULocale locale)44     public Object get(ULocale locale) {
45         return get(locale, LocaleKey.KIND_ANY, null);
46     }
47 
48     /**
49      * Convenience override for callers using locales.  This calls
50      * get(ULocale, int, ULocale[]) with a null actualReturn.
51      */
get(ULocale locale, int kind)52     public Object get(ULocale locale, int kind) {
53         return get(locale, kind, null);
54     }
55 
56     /**
57      * Convenience override for callers using locales.  This calls
58      * get(ULocale, int, ULocale[]) with KIND_ANY for kind.
59      */
get(ULocale locale, ULocale[] actualReturn)60     public Object get(ULocale locale, ULocale[] actualReturn) {
61         return get(locale, LocaleKey.KIND_ANY, actualReturn);
62     }
63 
64     /**
65      * Convenience override for callers using locales.  This uses
66      * createKey(ULocale.toString(), kind) to create a key, calls getKey, and then
67      * if actualReturn is not null, returns the actualResult from
68      * getKey (stripping any prefix) into a ULocale.
69      */
get(ULocale locale, int kind, ULocale[] actualReturn)70     public Object get(ULocale locale, int kind, ULocale[] actualReturn) {
71         Key key = createKey(locale, kind);
72         if (actualReturn == null) {
73             return getKey(key);
74         }
75 
76         String[] temp = new String[1];
77         Object result = getKey(key, temp);
78         if (result != null) {
79             int n = temp[0].indexOf("/");
80             if (n >= 0) {
81                 temp[0] = temp[0].substring(n+1);
82             }
83             actualReturn[0] = new ULocale(temp[0]);
84         }
85         return result;
86     }
87 
88     /**
89      * Convenience override for callers using locales.  This calls
90      * registerObject(Object, ULocale, int kind, boolean visible)
91      * passing KIND_ANY for the kind, and true for the visibility.
92      */
registerObject(Object obj, ULocale locale)93     public Factory registerObject(Object obj, ULocale locale) {
94         return registerObject(obj, locale, LocaleKey.KIND_ANY, true);
95     }
96 
97     /**
98      * Convenience override for callers using locales.  This calls
99      * registerObject(Object, ULocale, int kind, boolean visible)
100      * passing KIND_ANY for the kind.
101      */
registerObject(Object obj, ULocale locale, boolean visible)102     public Factory registerObject(Object obj, ULocale locale, boolean visible) {
103         return registerObject(obj, locale, LocaleKey.KIND_ANY, visible);
104     }
105 
106     /**
107      * Convenience function for callers using locales.  This calls
108      * registerObject(Object, ULocale, int kind, boolean visible)
109      * passing true for the visibility.
110      */
registerObject(Object obj, ULocale locale, int kind)111     public Factory registerObject(Object obj, ULocale locale, int kind) {
112         return registerObject(obj, locale, kind, true);
113     }
114 
115     /**
116      * Convenience function for callers using locales.  This  instantiates
117      * a SimpleLocaleKeyFactory, and registers the factory.
118      */
registerObject(Object obj, ULocale locale, int kind, boolean visible)119     public Factory registerObject(Object obj, ULocale locale, int kind, boolean visible) {
120         Factory factory = new SimpleLocaleKeyFactory(obj, locale, kind, visible);
121         return registerFactory(factory);
122     }
123 
124     /**
125      * Convenience method for callers using locales.  This returns the standard
126      * Locale list, built from the Set of visible ids.
127      */
getAvailableLocales()128     public Locale[] getAvailableLocales() {
129         // TODO make this wrap getAvailableULocales later
130         Set<String> visIDs = getVisibleIDs();
131         Locale[] locales = new Locale[visIDs.size()];
132         int n = 0;
133         for (String id : visIDs) {
134             Locale loc = LocaleUtility.getLocaleFromName(id);
135             locales[n++] = loc;
136         }
137         return locales;
138     }
139 
140     /**
141      * Convenience method for callers using locales.  This returns the standard
142      * ULocale list, built from the Set of visible ids.
143      */
getAvailableULocales()144     public ULocale[] getAvailableULocales() {
145         Set<String> visIDs = getVisibleIDs();
146         ULocale[] locales = new ULocale[visIDs.size()];
147         int n = 0;
148         for (String id : visIDs) {
149             locales[n++] = new ULocale(id);
150         }
151         return locales;
152     }
153 
154     /**
155      * A subclass of Key that implements a locale fallback mechanism.
156      * The first locale to search for is the locale provided by the
157      * client, and the fallback locale to search for is the current
158      * default locale.  If a prefix is present, the currentDescriptor
159      * includes it before the locale proper, separated by "/".  This
160      * is the default key instantiated by ICULocaleService.</p>
161      *
162      * <p>Canonicalization adjusts the locale string so that the
163      * section before the first understore is in lower case, and the rest
164      * is in upper case, with no trailing underscores.</p>
165      * @hide exposed on OHOS
166      */
167     public static class LocaleKey extends ICUService.Key {
168         private int kind;
169         private int varstart;
170         private String primaryID;
171         private String fallbackID;
172         private String currentID;
173 
174         public static final int KIND_ANY = -1;
175 
176         /**
177          * Create a LocaleKey with canonical primary and fallback IDs.
178          */
createWithCanonicalFallback(String primaryID, String canonicalFallbackID)179         public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID) {
180             return createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY);
181         }
182 
183         /**
184          * Create a LocaleKey with canonical primary and fallback IDs.
185          */
createWithCanonicalFallback(String primaryID, String canonicalFallbackID, int kind)186         public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID, int kind) {
187             if (primaryID == null) {
188                 return null;
189             }
190             String canonicalPrimaryID = ULocale.getName(primaryID);
191             return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
192         }
193 
194         /**
195          * Create a LocaleKey with canonical primary and fallback IDs.
196          */
createWithCanonical(ULocale locale, String canonicalFallbackID, int kind)197         public static LocaleKey createWithCanonical(ULocale locale, String canonicalFallbackID, int kind) {
198             if (locale == null) {
199                 return null;
200             }
201             String canonicalPrimaryID = locale.getName();
202             return new LocaleKey(canonicalPrimaryID, canonicalPrimaryID, canonicalFallbackID, kind);
203         }
204 
205         /**
206          * PrimaryID is the user's requested locale string,
207          * canonicalPrimaryID is this string in canonical form,
208          * fallbackID is the current default locale's string in
209          * canonical form.
210          */
LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, int kind)211         protected LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, int kind) {
212             super(primaryID);
213             this.kind = kind;
214 
215             if (canonicalPrimaryID == null || canonicalPrimaryID.equalsIgnoreCase("root")) {
216                 this.primaryID = "";
217                 this.fallbackID = null;
218             } else {
219                 int idx = canonicalPrimaryID.indexOf('@');
220                 if (idx == 4 && canonicalPrimaryID.regionMatches(true, 0, "root", 0, 4)) {
221                     this.primaryID = canonicalPrimaryID.substring(4);
222                     this.varstart = 0;
223                     this.fallbackID = null;
224                 } else {
225                     this.primaryID = canonicalPrimaryID;
226                     this.varstart = idx;
227 
228                     if (canonicalFallbackID == null || this.primaryID.equals(canonicalFallbackID)) {
229                         this.fallbackID = "";
230                     } else {
231                         this.fallbackID = canonicalFallbackID;
232                     }
233                 }
234             }
235 
236             this.currentID = varstart == -1 ? this.primaryID : this.primaryID.substring(0, varstart);
237         }
238 
239         /**
240          * Return the prefix associated with the kind, or null if the kind is KIND_ANY.
241          */
prefix()242         public String prefix() {
243             return kind == KIND_ANY ? null : Integer.toString(kind());
244         }
245 
246         /**
247          * Return the kind code associated with this key.
248          */
kind()249         public int kind() {
250             return kind;
251         }
252 
253         /**
254          * Return the (canonical) original ID.
255          */
256         @Override
canonicalID()257         public String canonicalID() {
258             return primaryID;
259         }
260 
261         /**
262          * Return the (canonical) current ID, or null if no current id.
263          */
264         @Override
currentID()265         public String currentID() {
266             return currentID;
267         }
268 
269         /**
270          * Return the (canonical) current descriptor, or null if no current id.
271          * Includes the keywords, whereas the ID does not include keywords.
272          */
273         @Override
currentDescriptor()274         public String currentDescriptor() {
275             String result = currentID();
276             if (result != null) {
277                 StringBuilder buf = new StringBuilder(); // default capacity 16 is usually good enough
278                 if (kind != KIND_ANY) {
279                     buf.append(prefix());
280                 }
281                 buf.append('/');
282                 buf.append(result);
283                 if (varstart != -1) {
284                     buf.append(primaryID.substring(varstart, primaryID.length()));
285                 }
286                 result = buf.toString();
287             }
288             return result;
289         }
290 
291         /**
292          * Convenience method to return the locale corresponding to the (canonical) original ID.
293          */
canonicalLocale()294         public ULocale canonicalLocale() {
295             return new ULocale(primaryID);
296         }
297 
298         /**
299          * Convenience method to return the ulocale corresponding to the (canonical) currentID.
300          */
currentLocale()301         public ULocale currentLocale() {
302             if (varstart == -1) {
303                 return new ULocale(currentID);
304             } else {
305                 return new ULocale(currentID + primaryID.substring(varstart));
306             }
307         }
308 
309         /**
310          * If the key has a fallback, modify the key and return true,
311          * otherwise return false.</p>
312          *
313          * <p>First falls back through the primary ID, then through
314          * the fallbackID.  The final fallback is "" (root)
315          * unless the primary id was "" (root), in which case
316          * there is no fallback.
317          */
318         @Override
fallback()319         public boolean fallback() {
320             int x = currentID.lastIndexOf('_');
321             if (x != -1) {
322                 while (--x >= 0 && currentID.charAt(x) == '_') { // handle zh__PINYIN
323                 }
324                 currentID = currentID.substring(0, x+1);
325                 return true;
326             }
327             if (fallbackID != null) {
328                 currentID = fallbackID;
329                 if (fallbackID.length() == 0) {
330                     fallbackID = null;
331                 } else {
332                     fallbackID = "";
333                 }
334                 return true;
335             }
336             currentID = null;
337             return false;
338         }
339 
340         /**
341          * If a key created from id would eventually fallback to match the
342          * canonical ID of this key, return true.
343          */
344         @Override
isFallbackOf(String id)345         public boolean isFallbackOf(String id) {
346             return LocaleUtility.isFallbackOf(canonicalID(), id);
347         }
348     }
349 
350     /**
351      * A subclass of Factory that uses LocaleKeys.  If 'visible' the
352      * factory reports its IDs.
353      * @hide exposed on OHOS
354      */
355     public static abstract class LocaleKeyFactory implements Factory {
356         protected final String name;
357         protected final boolean visible;
358 
359         public static final boolean VISIBLE = true;
360         public static final boolean INVISIBLE = false;
361 
362         /**
363          * Constructor used by subclasses.
364          */
LocaleKeyFactory(boolean visible)365         protected LocaleKeyFactory(boolean visible) {
366             this.visible = visible;
367             this.name = null;
368         }
369 
370         /**
371          * Constructor used by subclasses.
372          */
LocaleKeyFactory(boolean visible, String name)373         protected LocaleKeyFactory(boolean visible, String name) {
374             this.visible = visible;
375             this.name = name;
376         }
377 
378         /**
379          * Implement superclass abstract method.  This checks the currentID of
380          * the key against the supported IDs, and passes the canonicalLocale and
381          * kind off to handleCreate (which subclasses must implement).
382          */
383         @Override
create(Key key, ICUService service)384         public Object create(Key key, ICUService service) {
385             if (handlesKey(key)) {
386                 LocaleKey lkey = (LocaleKey)key;
387                 int kind = lkey.kind();
388 
389                 ULocale uloc = lkey.currentLocale();
390                 return handleCreate(uloc, kind, service);
391             } else {
392                 // System.out.println("factory: " + this + " did not support id: " + key.currentID());
393                 // System.out.println("supported ids: " + getSupportedIDs());
394             }
395             return null;
396         }
397 
handlesKey(Key key)398         protected boolean handlesKey(Key key) {
399             if (key != null) {
400                 String id = key.currentID();
401                 Set<String> supported = getSupportedIDs();
402                 return supported.contains(id);
403             }
404             return false;
405         }
406 
407         /**
408          * Override of superclass method.
409          */
410         @Override
updateVisibleIDs(Map<String, Factory> result)411         public void updateVisibleIDs(Map<String, Factory> result) {
412             Set<String> cache = getSupportedIDs();
413             for (String id : cache) {
414                 if (visible) {
415                     result.put(id, this);
416                 } else {
417                     result.remove(id);
418                 }
419             }
420        }
421 
422         /**
423          * Return a localized name for the locale represented by id.
424          */
425         @Override
getDisplayName(String id, ULocale locale)426         public String getDisplayName(String id, ULocale locale) {
427             // assume if the user called this on us, we must have handled some fallback of this id
428             //          if (isSupportedID(id)) {
429             if (locale == null) {
430                 return id;
431             }
432             ULocale loc = new ULocale(id);
433             return loc.getDisplayName(locale);
434             //              }
435             //          return null;
436         }
437 
438         ///CLOVER:OFF
439         /**
440          * Utility method used by create(Key, ICUService).  Subclasses can
441          * implement this instead of create.
442          */
handleCreate(ULocale loc, int kind, ICUService service)443         protected Object handleCreate(ULocale loc, int kind, ICUService service) {
444             return null;
445         }
446         ///CLOVER:ON
447 
448         /**
449          * Return true if this id is one the factory supports (visible or
450          * otherwise).
451          */
isSupportedID(String id)452         protected boolean isSupportedID(String id) {
453             return getSupportedIDs().contains(id);
454         }
455 
456         /**
457          * Return the set of ids that this factory supports (visible or
458          * otherwise).  This can be called often and might need to be
459          * cached if it is expensive to create.
460          */
getSupportedIDs()461         protected Set<String> getSupportedIDs() {
462             return Collections.emptySet();
463         }
464 
465         /**
466          * For debugging.
467          */
468         @Override
toString()469         public String toString() {
470             StringBuilder buf = new StringBuilder(super.toString());
471             if (name != null) {
472                 buf.append(", name: ");
473                 buf.append(name);
474             }
475             buf.append(", visible: ");
476             buf.append(visible);
477             return buf.toString();
478         }
479     }
480 
481     /**
482      * A LocaleKeyFactory that just returns a single object for a kind/locale.
483      * @hide exposed on OHOS
484      */
485     public static class SimpleLocaleKeyFactory extends LocaleKeyFactory {
486         private final Object obj;
487         private final String id;
488         private final int kind;
489 
490         // TODO: remove when we no longer need this
SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible)491         public SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible) {
492             this(obj, locale, kind, visible, null);
493         }
494 
SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible, String name)495         public SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible, String name) {
496             super(visible, name);
497 
498             this.obj = obj;
499             this.id = locale.getBaseName();
500             this.kind = kind;
501         }
502 
503         /**
504          * Returns the service object if kind/locale match.  Service is not used.
505          */
506         @Override
create(Key key, ICUService service)507         public Object create(Key key, ICUService service) {
508             if (!(key instanceof LocaleKey)) {
509                 return null;
510             }
511 
512             LocaleKey lkey = (LocaleKey)key;
513             if (kind != LocaleKey.KIND_ANY && kind != lkey.kind()) {
514                 return null;
515             }
516             if (!id.equals(lkey.currentID())) {
517                 return null;
518             }
519 
520             return obj;
521         }
522 
523         @Override
isSupportedID(String idToCheck)524         protected boolean isSupportedID(String idToCheck) {
525             return this.id.equals(idToCheck);
526         }
527 
528         @Override
updateVisibleIDs(Map<String, Factory> result)529         public void updateVisibleIDs(Map<String, Factory> result) {
530             if (visible) {
531                 result.put(id, this);
532             } else {
533                 result.remove(id);
534             }
535         }
536 
537         @Override
toString()538         public String toString() {
539             StringBuilder buf = new StringBuilder(super.toString());
540             buf.append(", id: ");
541             buf.append(id);
542             buf.append(", kind: ");
543             buf.append(kind);
544             return buf.toString();
545         }
546     }
547 
548     /**
549      * A LocaleKeyFactory that creates a service based on the ICU locale data.
550      * This is a base class for most ICU factories.  Subclasses instantiate it
551      * with a constructor that takes a bundle name, which determines the supported
552      * IDs.  Subclasses then override handleCreate to create the actual service
553      * object.  The default implementation returns a resource bundle.
554      * @hide exposed on OHOS
555      */
556     public static class ICUResourceBundleFactory extends LocaleKeyFactory {
557         protected final String bundleName;
558 
559         /**
560          * Convenience constructor that uses the main ICU bundle name.
561          */
ICUResourceBundleFactory()562         public ICUResourceBundleFactory() {
563             this(ICUData.ICU_BASE_NAME);
564         }
565 
566         /**
567          * A service factory based on ICU resource data in resources
568          * with the given name.
569          */
ICUResourceBundleFactory(String bundleName)570         public ICUResourceBundleFactory(String bundleName) {
571             super(true);
572 
573             this.bundleName = bundleName;
574         }
575 
576         /**
577          * Return the supported IDs.  This is the set of all locale names for the bundleName.
578          */
579         @Override
getSupportedIDs()580         protected Set<String> getSupportedIDs() {
581             return ICUResourceBundle.getFullLocaleNameSet(bundleName, loader());
582         }
583 
584         /**
585          * Override of superclass method.
586          */
587         @Override
updateVisibleIDs(Map<String, Factory> result)588         public void updateVisibleIDs(Map<String, Factory> result) {
589           Set<String> visibleIDs = ICUResourceBundle.getAvailableLocaleNameSet(bundleName, loader()); // only visible ids
590             for (String id : visibleIDs) {
591                 result.put(id, this);
592             }
593         }
594 
595         /**
596          * Create the service.  The default implementation returns the resource bundle
597          * for the locale, ignoring kind, and service.
598          */
599         @Override
handleCreate(ULocale loc, int kind, ICUService service)600         protected Object handleCreate(ULocale loc, int kind, ICUService service) {
601             return ICUResourceBundle.getBundleInstance(bundleName, loc, loader());
602         }
603 
loader()604         protected ClassLoader loader() {
605             return ClassLoaderUtil.getClassLoader(getClass());
606         }
607 
608         @Override
toString()609         public String toString() {
610             return super.toString() + ", bundle: " + bundleName;
611         }
612     }
613 
614     /**
615      * Return the name of the current fallback locale.  If it has changed since this was
616      * last accessed, the service cache is cleared.
617      */
validateFallbackLocale()618     public String validateFallbackLocale() {
619         ULocale loc = ULocale.getDefault();
620         if (loc != fallbackLocale) {
621             synchronized (this) {
622                 if (loc != fallbackLocale) {
623                     fallbackLocale = loc;
624                     fallbackLocaleName = loc.getBaseName();
625                     clearServiceCache();
626                 }
627             }
628         }
629         return fallbackLocaleName;
630     }
631 
632     @Override
createKey(String id)633     public Key createKey(String id) {
634         return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale());
635     }
636 
createKey(String id, int kind)637     public Key createKey(String id, int kind) {
638         return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale(), kind);
639     }
640 
createKey(ULocale l, int kind)641     public Key createKey(ULocale l, int kind) {
642         return LocaleKey.createWithCanonical(l, validateFallbackLocale(), kind);
643     }
644 }
645