KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > impl > ICULocaleService


1 /**
2  *******************************************************************************
3  * Copyright (C) 2001-2007, International Business Machines Corporation and *
4  * others. All Rights Reserved. *
5  *******************************************************************************
6  */

7 package com.ibm.icu.impl;
8
9 import java.util.Collections JavaDoc;
10 import java.util.Iterator JavaDoc;
11 import java.util.Locale JavaDoc;
12 import java.util.Map JavaDoc;
13 import java.util.Set JavaDoc;
14
15 import com.ibm.icu.util.ULocale;
16
17 public class ICULocaleService extends ICUService {
18     private ULocale fallbackLocale;
19     private String JavaDoc fallbackLocaleName;
20
21     /**
22      * Construct an ICULocaleService.
23      */

24     public ICULocaleService() {
25     }
26
27     /**
28      * Construct an ICULocaleService with a name (useful for debugging).
29      */

30     public ICULocaleService(String JavaDoc name) {
31         super(name);
32     }
33
34     /**
35      * Convenience override for callers using locales. This calls
36      * get(ULocale, int, ULocale[]) with KIND_ANY for kind and null for
37      * actualReturn.
38      */

39     public Object JavaDoc get(ULocale locale) {
40         return get(locale, LocaleKey.KIND_ANY, null);
41     }
42
43     /**
44      * Convenience override for callers using locales. This calls
45      * get(ULocale, int, ULocale[]) with a null actualReturn.
46      */

47     public Object JavaDoc get(ULocale locale, int kind) {
48         return get(locale, kind, null);
49     }
50
51     /**
52      * Convenience override for callers using locales. This calls
53      * get(ULocale, int, ULocale[]) with KIND_ANY for kind.
54      */

55     public Object JavaDoc get(ULocale locale, ULocale[] actualReturn) {
56         return get(locale, LocaleKey.KIND_ANY, actualReturn);
57     }
58
59     /**
60      * Convenience override for callers using locales. This uses
61      * createKey(ULocale.toString(), kind) to create a key, calls getKey, and then
62      * if actualReturn is not null, returns the actualResult from
63      * getKey (stripping any prefix) into a ULocale.
64      */

65     public Object JavaDoc get(ULocale locale, int kind, ULocale[] actualReturn) {
66         Key key = createKey(locale, kind);
67         if (actualReturn == null) {
68             return getKey(key);
69         }
70
71         String JavaDoc[] temp = new String JavaDoc[1];
72         Object JavaDoc result = getKey(key, temp);
73         if (result != null) {
74             int n = temp[0].indexOf("/");
75             if (n >= 0) {
76                 temp[0] = temp[0].substring(n+1);
77             }
78             actualReturn[0] = new ULocale(temp[0]);
79         }
80         return result;
81     }
82
83     /**
84      * Convenience override for callers using locales. This calls
85      * registerObject(Object, ULocale, int kind, boolean visible)
86      * passing KIND_ANY for the kind, and true for the visibility.
87      */

88     public Factory registerObject(Object JavaDoc obj, ULocale locale) {
89         return registerObject(obj, locale, LocaleKey.KIND_ANY, true);
90     }
91
92     /**
93      * Convenience override for callers using locales. This calls
94      * registerObject(Object, ULocale, int kind, boolean visible)
95      * passing KIND_ANY for the kind.
96      */

97     public Factory registerObject(Object JavaDoc obj, ULocale locale, boolean visible) {
98         return registerObject(obj, locale, LocaleKey.KIND_ANY, visible);
99     }
100
101     /**
102      * Convenience function for callers using locales. This calls
103      * registerObject(Object, ULocale, int kind, boolean visible)
104      * passing true for the visibility.
105      */

106     public Factory registerObject(Object JavaDoc obj, ULocale locale, int kind) {
107         return registerObject(obj, locale, kind, true);
108     }
109
110     /**
111      * Convenience function for callers using locales. This instantiates
112      * a SimpleLocaleKeyFactory, and registers the factory.
113      */

114     public Factory registerObject(Object JavaDoc obj, ULocale locale, int kind, boolean visible) {
115         Factory factory = new SimpleLocaleKeyFactory(obj, locale, kind, visible);
116         return registerFactory(factory);
117     }
118
119     /**
120      * Convenience method for callers using locales. This returns the standard
121      * Locale list, built from the Set of visible ids.
122      */

123     public Locale JavaDoc[] getAvailableLocales() {
124         // TODO make this wrap getAvailableULocales later
125
Set JavaDoc visIDs = getVisibleIDs();
126         Iterator JavaDoc iter = visIDs.iterator();
127         Locale JavaDoc[] locales = new Locale JavaDoc[visIDs.size()];
128         int n = 0;
129         while (iter.hasNext()) {
130             Locale JavaDoc loc = LocaleUtility.getLocaleFromName((String JavaDoc)iter.next());
131             locales[n++] = loc;
132         }
133         return locales;
134     }
135
136     /**
137      * Convenience method for callers using locales. This returns the standard
138      * ULocale list, built from the Set of visible ids.
139      */

140     public ULocale[] getAvailableULocales() {
141         Set JavaDoc visIDs = getVisibleIDs();
142         Iterator JavaDoc iter = visIDs.iterator();
143         ULocale[] locales = new ULocale[visIDs.size()];
144         int n = 0;
145         while (iter.hasNext()) {
146             locales[n++] = new ULocale((String JavaDoc)iter.next());
147         }
148         return locales;
149     }
150         
151     /**
152      * A subclass of Key that implements a locale fallback mechanism.
153      * The first locale to search for is the locale provided by the
154      * client, and the fallback locale to search for is the current
155      * default locale. If a prefix is present, the currentDescriptor
156      * includes it before the locale proper, separated by "/". This
157      * is the default key instantiated by ICULocaleService.</p>
158      *
159      * <p>Canonicalization adjusts the locale string so that the
160      * section before the first understore is in lower case, and the rest
161      * is in upper case, with no trailing underscores.</p>
162      */

163     public static class LocaleKey extends ICUService.Key {
164         private int kind;
165         private int varstart;
166         private String JavaDoc primaryID;
167         private String JavaDoc fallbackID;
168         private String JavaDoc currentID;
169
170         public static final int KIND_ANY = -1;
171
172         /**
173          * Create a LocaleKey with canonical primary and fallback IDs.
174          */

175         public static LocaleKey createWithCanonicalFallback(String JavaDoc primaryID, String JavaDoc canonicalFallbackID) {
176             return createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY);
177         }
178             
179         /**
180          * Create a LocaleKey with canonical primary and fallback IDs.
181          */

182         public static LocaleKey createWithCanonicalFallback(String JavaDoc primaryID, String JavaDoc canonicalFallbackID, int kind) {
183             if (primaryID == null) {
184                 return null;
185             }
186             if (primaryID.length() == 0) {
187                 primaryID = "root";
188             }
189             String JavaDoc canonicalPrimaryID = ULocale.getName(primaryID);
190             return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
191         }
192             
193         /**
194          * Create a LocaleKey with canonical primary and fallback IDs.
195          */

196         public static LocaleKey createWithCanonical(ULocale locale, String JavaDoc canonicalFallbackID, int kind) {
197             if (locale == null) {
198                 return null;
199             }
200             String JavaDoc canonicalPrimaryID = locale.getName();
201             return new LocaleKey(canonicalPrimaryID, canonicalPrimaryID, canonicalFallbackID, kind);
202         }
203             
204         /**
205          * PrimaryID is the user's requested locale string,
206          * canonicalPrimaryID is this string in canonical form,
207          * fallbackID is the current default locale's string in
208          * canonical form.
209          */

210         protected LocaleKey(String JavaDoc primaryID, String JavaDoc canonicalPrimaryID, String JavaDoc canonicalFallbackID, int kind) {
211             super(primaryID);
212
213             this.kind = kind;
214             if (canonicalPrimaryID == null) {
215                 this.primaryID = "";
216             } else {
217                 this.primaryID = canonicalPrimaryID;
218                 this.varstart = this.primaryID.indexOf('@');
219             }
220             if (this.primaryID == "") {
221                 this.fallbackID = null;
222             } else {
223                 if (canonicalFallbackID == null || this.primaryID.equals(canonicalFallbackID)) {
224                     this.fallbackID = "";
225                 } else {
226                     this.fallbackID = canonicalFallbackID;
227                 }
228             }
229
230             this.currentID = varstart == -1 ? this.primaryID : this.primaryID.substring(0, varstart);
231         }
232
233         /**
234          * Return the prefix associated with the kind, or null if the kind is KIND_ANY.
235          */

236         public String JavaDoc prefix() {
237             return kind == KIND_ANY ? null : Integer.toString(kind());
238         }
239
240         /**
241          * Return the kind code associated with this key.
242          */

243         public int kind() {
244             return kind;
245         }
246
247         /**
248          * Return the (canonical) original ID.
249          */

250         public String JavaDoc canonicalID() {
251             return primaryID;
252         }
253
254         /**
255          * Return the (canonical) current ID, or null if no current id.
256          */

257         public String JavaDoc currentID() {
258             return currentID;
259         }
260
261         /**
262          * Return the (canonical) current descriptor, or null if no current id.
263          * Includes the keywords, whereas the ID does not include keywords.
264          */

265         public String JavaDoc currentDescriptor() {
266             String JavaDoc result = currentID();
267             if (result != null) {
268                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc(); // default capacity 16 is usually good enough
269
if (kind != KIND_ANY) {
270                     buf.append(prefix());
271                 }
272                 buf.append('/');
273                 buf.append(result);
274                 if (varstart != -1) {
275                     buf.append(primaryID.substring(varstart, primaryID.length()));
276                 }
277                 result = buf.toString();
278             }
279             return result;
280         }
281
282         /**
283          * Convenience method to return the locale corresponding to the (canonical) original ID.
284          */

285         public ULocale canonicalLocale() {
286             return new ULocale(primaryID);
287         }
288
289         /**
290          * Convenience method to return the ulocale corresponding to the (canonical) currentID.
291          */

292         public ULocale currentLocale() {
293             if (varstart == -1) {
294                 return new ULocale(currentID);
295             } else {
296                 return new ULocale(currentID + primaryID.substring(varstart));
297             }
298         }
299
300         /**
301          * If the key has a fallback, modify the key and return true,
302          * otherwise return false.</p>
303          *
304          * <p>First falls back through the primary ID, then through
305          * the fallbackID. The final fallback is "root"
306          * unless the primary id was "root", in which case
307          * there is no fallback.
308          */

309         public boolean fallback() {
310             int x = currentID.lastIndexOf('_');
311             if (x != -1) {
312                 while (--x >= 0 && currentID.charAt(x) == '_') { // handle zh__PINYIN
313
}
314                 currentID = currentID.substring(0, x+1);
315                 return true;
316             }
317             if (fallbackID != null) {
318                 if (fallbackID.length() == 0) {
319                     currentID = "root";
320                     fallbackID = null;
321                 } else {
322                     currentID = fallbackID;
323                     fallbackID = "";
324                 }
325                 return true;
326             }
327             currentID = null;
328             return false;
329         }
330
331         /**
332          * If a key created from id would eventually fallback to match the
333          * canonical ID of this key, return true.
334          */

335         public boolean isFallbackOf(String JavaDoc id) {
336             return LocaleUtility.isFallbackOf(canonicalID(), id);
337         }
338     }
339
340     /**
341      * A subclass of Factory that uses LocaleKeys. If 'visible' the
342      * factory reports its IDs.
343      */

344     public static abstract class LocaleKeyFactory implements Factory {
345         protected final String JavaDoc name;
346         protected final boolean visible;
347
348         public static final boolean VISIBLE = true;
349         public static final boolean INVISIBLE = false;
350
351         /**
352          * Constructor used by subclasses.
353          */

354         protected LocaleKeyFactory(boolean visible) {
355             this.visible = visible;
356             this.name = null;
357         }
358
359         /**
360          * Constructor used by subclasses.
361          */

362         protected LocaleKeyFactory(boolean visible, String JavaDoc name) {
363             this.visible = visible;
364             this.name = name;
365         }
366
367         /**
368          * Implement superclass abstract method. This checks the currentID of
369          * the key against the supported IDs, and passes the canonicalLocale and
370          * kind off to handleCreate (which subclasses must implement).
371          */

372         public Object JavaDoc create(Key key, ICUService service) {
373             if (handlesKey(key)) {
374                 LocaleKey lkey = (LocaleKey)key;
375                 int kind = lkey.kind();
376                 
377                 ULocale uloc = lkey.currentLocale();
378                 return handleCreate(uloc, kind, service);
379             } else {
380                 // System.out.println("factory: " + this + " did not support id: " + key.currentID());
381
// System.out.println("supported ids: " + getSupportedIDs());
382
}
383             return null;
384         }
385
386         protected boolean handlesKey(Key key) {
387             if (key != null) {
388                 String JavaDoc id = key.currentID();
389                 Set JavaDoc supported = getSupportedIDs();
390                 return supported.contains(id);
391             }
392             return false;
393         }
394
395         /**
396          * Override of superclass method.
397          */

398         public void updateVisibleIDs(Map JavaDoc result) {
399             Set JavaDoc cache = getSupportedIDs();
400             Iterator JavaDoc iter = cache.iterator();
401             while (iter.hasNext()) {
402                 String JavaDoc id = (String JavaDoc)iter.next();
403                 if (visible) {
404                     result.put(id, this);
405                 } else {
406                     result.remove(id);
407                 }
408             }
409         }
410
411         /**
412          * Return a localized name for the locale represented by id.
413          */

414         public String JavaDoc getDisplayName(String JavaDoc id, ULocale locale) {
415             // assume if the user called this on us, we must have handled some fallback of this id
416
// if (isSupportedID(id)) {
417
if (locale == null) {
418                 return id;
419             }
420             ULocale loc = new ULocale(id);
421             return loc.getDisplayName(locale);
422             // }
423
// return null;
424
}
425
426         ///CLOVER:OFF
427
/**
428          * Utility method used by create(Key, ICUService). Subclasses can
429          * implement this instead of create.
430          */

431         protected Object JavaDoc handleCreate(ULocale loc, int kind, ICUService service) {
432             return null;
433         }
434         ///CLOVER:ON
435

436         /**
437          * Return true if this id is one the factory supports (visible or
438          * otherwise).
439          */

440         protected boolean isSupportedID(String JavaDoc id) {
441             return getSupportedIDs().contains(id);
442         }
443         
444         /**
445          * Return the set of ids that this factory supports (visible or
446          * otherwise). This can be called often and might need to be
447          * cached if it is expensive to create.
448          */

449         protected Set JavaDoc getSupportedIDs() {
450             return Collections.EMPTY_SET;
451         }
452
453         /**
454          * For debugging.
455          */

456         public String JavaDoc toString() {
457             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(super.toString());
458             if (name != null) {
459                 buf.append(", name: ");
460                 buf.append(name);
461             }
462             buf.append(", visible: ");
463             buf.append(visible);
464             return buf.toString();
465         }
466     }
467
468     /**
469      * A LocaleKeyFactory that just returns a single object for a kind/locale.
470      */

471     public static class SimpleLocaleKeyFactory extends LocaleKeyFactory {
472         private final Object JavaDoc obj;
473         private final String JavaDoc id;
474         private final int kind;
475
476         // TODO: remove when we no longer need this
477
public SimpleLocaleKeyFactory(Object JavaDoc obj, ULocale locale, int kind, boolean visible) {
478             this(obj, locale, kind, visible, null);
479         }
480
481         public SimpleLocaleKeyFactory(Object JavaDoc obj, ULocale locale, int kind, boolean visible, String JavaDoc name) {
482             super(visible, name);
483             
484             this.obj = obj;
485             this.id = locale.getBaseName();
486             this.kind = kind;
487         }
488
489         /**
490          * Returns the service object if kind/locale match. Service is not used.
491          */

492         public Object JavaDoc create(Key key, ICUService service) {
493             LocaleKey lkey = (LocaleKey)key;
494             if (kind == LocaleKey.KIND_ANY || kind == lkey.kind()) {
495                 String JavaDoc keyID = lkey.currentID();
496                 if (id.equals(keyID)) {
497                     return obj;
498                 }
499             }
500             return null;
501         }
502
503         protected boolean isSupportedID(String JavaDoc id) {
504             return this.id.equals(id);
505         }
506
507         public void updateVisibleIDs(Map JavaDoc result) {
508             if (visible) {
509                 result.put(id, this);
510             } else {
511                 result.remove(id);
512             }
513         }
514
515         public String JavaDoc toString() {
516             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(super.toString());
517             buf.append(", id: ");
518             buf.append(id);
519             buf.append(", kind: ");
520             buf.append(kind);
521             return buf.toString();
522         }
523     }
524
525     /**
526      * A LocaleKeyFactory that creates a service based on the ICU locale data.
527      * This is a base class for most ICU factories. Subclasses instantiate it
528      * with a constructor that takes a bundle name, which determines the supported
529      * IDs. Subclasses then override handleCreate to create the actual service
530      * object. The default implementation returns a resource bundle.
531      */

532     public static class ICUResourceBundleFactory extends LocaleKeyFactory {
533         protected final String JavaDoc bundleName;
534
535         /**
536          * Convenience constructor that uses the main ICU bundle name.
537          */

538         public ICUResourceBundleFactory() {
539             this(ICUResourceBundle.ICU_BASE_NAME);
540         }
541
542         /**
543          * A service factory based on ICU resource data in resources
544          * with the given name.
545          */

546         public ICUResourceBundleFactory(String JavaDoc bundleName) {
547             super(true);
548
549             this.bundleName = bundleName;
550         }
551
552         /**
553          * Return the supported IDs. This is the set of all locale names for the bundleName.
554          */

555         protected Set JavaDoc getSupportedIDs() {
556             // note: "root" is one of the ids, but "" is not. Must convert ULocale.ROOT.
557
return ICUResourceBundle.getFullLocaleNameSet(bundleName);
558         }
559
560         /**
561          * Override of superclass method.
562          */

563         public void updateVisibleIDs(Map JavaDoc result) {
564             Set JavaDoc visibleIDs = ICUResourceBundle.getAvailableLocaleNameSet(bundleName); // only visible ids
565
Iterator JavaDoc iter = visibleIDs.iterator();
566             while (iter.hasNext()) {
567                 String JavaDoc id = (String JavaDoc)iter.next();
568                 result.put(id, this);
569             }
570         }
571
572         /**
573          * Create the service. The default implementation returns the resource bundle
574          * for the locale, ignoring kind, and service.
575          */

576         protected Object JavaDoc handleCreate(ULocale loc, int kind, ICUService service) {
577             return ICUResourceBundle.getBundleInstance(bundleName, loc);
578         }
579
580         public String JavaDoc toString() {
581             return super.toString() + ", bundle: " + bundleName;
582         }
583     }
584
585     /**
586      * Return the name of the current fallback locale. If it has changed since this was
587      * last accessed, the service cache is cleared.
588      */

589     public String JavaDoc validateFallbackLocale() {
590         ULocale loc = ULocale.getDefault();
591         if (loc != fallbackLocale) {
592             synchronized (this) {
593                 if (loc != fallbackLocale) {
594                     fallbackLocale = loc;
595                     fallbackLocaleName = loc.getBaseName();
596                     clearServiceCache();
597                 }
598             }
599         }
600         return fallbackLocaleName;
601     }
602
603     public Key createKey(String JavaDoc id) {
604         return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale());
605     }
606
607     public Key createKey(String JavaDoc id, int kind) {
608         return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale(), kind);
609     }
610
611     public Key createKey(ULocale l, int kind) {
612         return LocaleKey.createWithCanonical(l, validateFallbackLocale(), kind);
613     }
614 }
615
Popular Tags