KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > util > GlobalizationPreferences


1 //##header 1189099963000 FOUNDATION
2
/*
3  *******************************************************************************
4  * Copyright (C) 2004-2006, International Business Machines Corporation and *
5  * others. All Rights Reserved. *
6  *******************************************************************************
7 */

8 package com.ibm.icu.util;
9 import java.util.ArrayList JavaDoc;
10 import java.util.Arrays JavaDoc;
11 import java.util.BitSet JavaDoc;
12 import java.util.Date JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.LinkedList JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18 import java.util.MissingResourceException JavaDoc;
19 import java.util.ResourceBundle JavaDoc;
20 import java.util.TreeMap JavaDoc;
21 //#ifndef FOUNDATION
22
//##import java.util.regex.Matcher;
23
//##import java.util.regex.Pattern;
24
//#endif
25
import com.ibm.icu.impl.Utility;
26 import com.ibm.icu.impl.ZoneMeta;
27 import com.ibm.icu.text.BreakIterator;
28 import com.ibm.icu.text.Collator;
29 import com.ibm.icu.text.DateFormat;
30 import com.ibm.icu.text.NumberFormat;
31 import com.ibm.icu.text.SimpleDateFormat;
32
33 /**
34  * This convenience class provides a mechanism for bundling together different
35  * globalization preferences. It includes:
36  * <ul>
37  * <li>A list of locales/languages in preference order</li>
38  * <li>A territory</li>
39  * <li>A currency</li>
40  * <li>A timezone</li>
41  * <li>A calendar</li>
42  * <li>A collator (for language-sensitive sorting, searching, and matching).</li>
43  * <li>Explicit overrides for date/time formats, etc.</li>
44  * </ul>
45  * The class will heuristically compute implicit, heuristic values for the above
46  * based on available data if explicit values are not supplied. These implicit
47  * values can be presented to users for confirmation, or replacement if the
48  * values are incorrect.
49  * <p>
50  * To reset any explicit field so that it will get heuristic values, pass in
51  * null. For example, myPreferences.setLocale(null);
52  * <p>
53  * All of the heuristics can be customized by subclasses, by overriding
54  * getTerritory(), guessCollator(), etc.
55  * <p>
56  * The class also supplies display names for languages, scripts, territories,
57  * currencies, timezones, etc. These are computed according to the
58  * locale/language preference list. Thus, if the preference is Breton; French;
59  * English, then the display name for a language will be returned in Breton if
60  * available, otherwise in French if available, otherwise in English.
61  * <p>
62  * The codes used to reference territory, currency, etc. are as defined elsewhere
63  * in ICU, and are taken from CLDR (which reflects RFC 3066bis usage, ISO 4217,
64  * and the TZ Timezone database identifiers).
65  * <p>
66  * <b>This is at a prototype stage, and has not incorporated all the design
67  * changes that we would like yet; further feedback is welcome.</b></p>
68  * <p>
69  * TODO:<ul>
70  * <li>Add Holidays</li>
71  * <li>Add convenience to get/take Locale as well as ULocale.</li>
72  * <li>Add Lenient datetime formatting when that is available.</li>
73  * <li>Should this be serializable?</li>
74  * <li>Other utilities?</li>
75  * </ul>
76  * Note:
77  * <ul>
78  * <li>to get the display name for the first day of the week, use the calendar +
79  * display names.</li>
80  * <li>to get the work days, ask the calendar (when that is available).</li>
81  * <li>to get papersize / measurement system/bidi-orientation, ask the locale
82  * (when that is available there)</li>
83  * <li>to get the field order in a date, and whether a time is 24hour or not,
84  * ask the DateFormat (when that is available there)</li>
85  * <li>it will support HOST locale when it becomes available (it is a special
86  * locale that will ask the services to use the host platform's values).</li>
87  * </ul>
88  *
89  * @draft ICU 3.6
90  * @provisional This API might change or be removed in a future release.
91  */

92 public class GlobalizationPreferences implements Freezable {
93     
94     /**
95      * Default constructor
96      * @draft ICU 3.6
97      * @provisional This API might change or be removed in a future release.
98      */

99     public GlobalizationPreferences(){}
100     /**
101      * Number Format types
102      * @draft ICU 3.6
103      * @provisional This API might change or be removed in a future release.
104      */

105     public static final int
106         NF_NUMBER = 0, // NumberFormat.NUMBERSTYLE
107
NF_CURRENCY = 1, // NumberFormat.CURRENCYSTYLE
108
NF_PERCENT = 2, // NumberFormat.PERCENTSTYLE
109
NF_SCIENTIFIC = 3, // NumberFormat.SCIENTIFICSTYLE
110
NF_INTEGER = 4; // NumberFormat.INTEGERSTYLE
111

112     private static final int NF_LIMIT = NF_INTEGER + 1;
113
114     /**
115      * Date Format types
116      * @draft ICU 3.6
117      * @provisional This API might change or be removed in a future release.
118      */

119     public static final int
120         DF_FULL = DateFormat.FULL, // 0
121
DF_LONG = DateFormat.LONG, // 1
122
DF_MEDIUM = DateFormat.MEDIUM, // 2
123
DF_SHORT = DateFormat.SHORT, // 3
124
DF_NONE = 4;
125
126     private static final int DF_LIMIT = DF_NONE + 1;
127
128     /**
129      * For selecting a choice of display names
130      * @draft ICU 3.6
131      * @provisional This API might change or be removed in a future release.
132      */

133     public static final int
134         ID_LOCALE = 0,
135         ID_LANGUAGE = 1,
136         ID_SCRIPT = 2,
137         ID_TERRITORY = 3,
138         ID_VARIANT = 4,
139         ID_KEYWORD = 5,
140         ID_KEYWORD_VALUE = 6,
141         ID_CURRENCY = 7,
142         ID_CURRENCY_SYMBOL = 8,
143         ID_TIMEZONE = 9;
144
145     private static final int ID_LIMIT = ID_TIMEZONE + 1;
146
147     /**
148      * Break iterator types
149      * @draft ICU 3.6
150      * @deprecated This API is ICU internal only
151      */

152     public static final int
153         BI_CHARACTER = BreakIterator.KIND_CHARACTER, // 0
154
BI_WORD = BreakIterator.KIND_WORD, // 1
155
BI_LINE = BreakIterator.KIND_LINE, // 2
156
BI_SENTENCE = BreakIterator.KIND_SENTENCE, // 3
157
BI_TITLE = BreakIterator.KIND_TITLE; // 4
158

159     private static final int BI_LIMIT = BI_TITLE + 1;
160
161     /**
162      * Sets the language/locale priority list. If other information is
163      * not (yet) available, this is used to to produce a default value
164      * for the appropriate territory, currency, timezone, etc. The
165      * user should be given the opportunity to correct those defaults
166      * in case they are incorrect.
167      *
168      * @param inputLocales list of locales in priority order, eg {"be", "fr"}
169      * for Breton first, then French if that fails.
170      * @return this, for chaining
171      * @draft ICU 3.6
172      * @provisional This API might change or be removed in a future release.
173      */

174     public GlobalizationPreferences setLocales(List JavaDoc inputLocales) {
175         if (isFrozen()) {
176             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
177         }
178         locales = processLocales(inputLocales);
179         return this;
180     }
181
182     /**
183      * Get a copy of the language/locale priority list
184      *
185      * @return a copy of the language/locale priority list.
186      * @draft ICU 3.6
187      * @provisional This API might change or be removed in a future release.
188      */

189     public List JavaDoc getLocales() {
190         List JavaDoc result;
191         if (locales == null) {
192             result = guessLocales();
193         } else {
194             result = new ArrayList JavaDoc();
195             result.addAll(locales);
196         }
197         return result;
198     }
199
200     /**
201      * Convenience function for getting the locales in priority order
202      * @param index The index (0..n) of the desired item.
203      * @return desired item. null if index is out of range
204      * @draft ICU 3.6
205      * @provisional This API might change or be removed in a future release.
206      */

207     public ULocale getLocale(int index) {
208         List JavaDoc lcls = locales;
209         if (lcls == null) {
210             lcls = guessLocales();
211         }
212         if (index >= 0 && index < lcls.size()) {
213             return (ULocale)lcls.get(index);
214         }
215         return null;
216     }
217
218     /**
219      * Convenience routine for setting the language/locale priority
220      * list from an array.
221      *
222      * @see #setLocales(List locales)
223      * @param uLocales list of locales in an array
224      * @return this, for chaining
225      * @draft ICU 3.6
226      * @provisional This API might change or be removed in a future release.
227      */

228     public GlobalizationPreferences setLocales(ULocale[] uLocales) {
229         if (isFrozen()) {
230             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
231         }
232         return setLocales(Arrays.asList(uLocales));
233     }
234
235     /**
236      * Convenience routine for setting the language/locale priority
237      * list from a single locale/language.
238      *
239      * @see #setLocales(List locales)
240      * @param uLocale single locale
241      * @return this, for chaining
242      * @draft ICU 3.6
243      * @provisional This API might change or be removed in a future release.
244      */

245     public GlobalizationPreferences setLocale(ULocale uLocale) {
246         if (isFrozen()) {
247             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
248         }
249         return setLocales(new ULocale[]{uLocale});
250     }
251
252 //#ifndef FOUNDATION
253
//## /**
254
//## * Convenience routine for setting the locale priority list from
255
//## * an Accept-Language string.
256
//## * @see #setLocales(List locales)
257
//## * @param acceptLanguageString Accept-Language list, as defined by
258
//## * Section 14.4 of the RFC 2616 (HTTP 1.1)
259
//## * @return this, for chaining
260
//## * @draft ICU 3.6
261
//## * @provisional This API might change or be removed in a future release.
262
//## */
263
//## public GlobalizationPreferences setLocales(String acceptLanguageString) {
264
//## if (isFrozen()) {
265
//## throw new UnsupportedOperationException("Attempt to modify immutable object");
266
//## }
267
//## /*
268
//## Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q" "=" qvalue ] )
269
//## x matches x-...
270
//## */
271
//## // reorders in quality order
272
//## // don't care that it is not very efficient right now
273
//## Matcher acceptMatcher = Pattern.compile("\\s*([-_a-zA-Z]+)(;q=([.0-9]+))?\\s*").matcher("");
274
//## Map reorder = new TreeMap();
275
//## String[] pieces = acceptLanguageString.split(",");
276
//##
277
//## for (int i = 0; i < pieces.length; ++i) {
278
//## Double qValue = new Double(1);
279
//## try {
280
//## if (!acceptMatcher.reset(pieces[i]).matches()) {
281
//## throw new IllegalArgumentException();
282
//## }
283
//## String qValueString = acceptMatcher.group(3);
284
//## if (qValueString != null) {
285
//## qValue = new Double(Double.parseDouble(qValueString));
286
//## }
287
//## } catch (Exception e) {
288
//## throw new IllegalArgumentException("element '" + pieces[i] +
289
//## "' is not of the form '<locale>{;q=<number>}");
290
//## }
291
//## List items = (List)reorder.get(qValue);
292
//## if (items == null) {
293
//## reorder.put(qValue, items = new LinkedList());
294
//## }
295
//## items.add(0, acceptMatcher.group(1)); // reverse order, will reverse again
296
//## }
297
//## // now read out in reverse order
298
//## List result = new ArrayList();
299
//## for (Iterator it = reorder.keySet().iterator(); it.hasNext();) {
300
//## Object key = it.next();
301
//## List items = (List)reorder.get(key);
302
//## for (Iterator it2 = items.iterator(); it2.hasNext();) {
303
//## result.add(0, new ULocale((String)it2.next()));
304
//## }
305
//## }
306
//## return setLocales(result);
307
//## }
308
//#endif
309

310     /**
311      * Convenience function to get a ResourceBundle instance using
312      * the specified base name based on the language/locale priority list
313      * stored in this object.
314      *
315      * @param baseName the base name of the resource bundle, a fully qualified
316      * class name
317      * @return a resource bundle for the given base name and locale based on the
318      * language/locale priority list stored in this object
319      * @draft ICU 3.6
320      * @provisional This API might change or be removed in a future release.
321      */

322     public ResourceBundle JavaDoc getResourceBundle(String JavaDoc baseName) {
323         return getResourceBundle(baseName, null);
324     }
325
326     /**
327      * Convenience function to get a ResourceBundle instance using
328      * the specified base name and class loader based on the language/locale
329      * priority list stored in this object.
330      *
331      * @param baseName the base name of the resource bundle, a fully qualified
332      * class name
333      * @param loader the class object from which to load the resource bundle
334      * @return a resource bundle for the given base name and locale based on the
335      * language/locale priority list stored in this object
336      * @draft ICU 3.6
337      * @provisional This API might change or be removed in a future release.
338      */

339     public ResourceBundle JavaDoc getResourceBundle(String JavaDoc baseName, ClassLoader JavaDoc loader) {
340         UResourceBundle urb = null;
341         UResourceBundle candidate = null;
342         String JavaDoc actualLocaleName = null;
343         List JavaDoc fallbacks = getLocales();
344         for (int i = 0; i < fallbacks.size(); i++) {
345             String JavaDoc localeName = ((ULocale)fallbacks.get(i)).toString();
346             if (actualLocaleName != null && localeName.equals(actualLocaleName)) {
347                 // Actual locale name in the previous round may exactly matches
348
// with the next fallback locale
349
urb = candidate;
350                 break;
351             }
352             try {
353                 if (loader == null) {
354                     candidate = UResourceBundle.getBundleInstance(baseName, localeName);
355                 }
356                 else {
357                     candidate = UResourceBundle.getBundleInstance(baseName, localeName, loader);
358                 }
359                 if (candidate != null) {
360                     actualLocaleName = candidate.getULocale().getName();
361                     if (actualLocaleName.equals(localeName)) {
362                         urb = candidate;
363                         break;
364                     }
365                     if (urb == null) {
366                         // Preserve the available bundle as the last resort
367
urb = candidate;
368                     }
369                 }
370             } catch (MissingResourceException JavaDoc mre) {
371                 actualLocaleName = null;
372                 continue;
373             }
374         }
375         if (urb == null) {
376             throw new MissingResourceException JavaDoc("Can't find bundle for base name "
377                     + baseName, baseName, "");
378         }
379         return urb;
380     }
381     
382     /**
383      * Sets the territory, which is a valid territory according to for
384      * RFC 3066 (or successor). If not otherwise set, default
385      * currency and timezone values will be set from this. The user
386      * should be given the opportunity to correct those defaults in
387      * case they are incorrect.
388      *
389      * @param territory code
390      * @return this, for chaining
391      * @draft ICU 3.6
392      * @provisional This API might change or be removed in a future release.
393      */

394     public GlobalizationPreferences setTerritory(String JavaDoc territory) {
395         if (isFrozen()) {
396             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
397         }
398         this.territory = territory; // immutable, so don't need to clone
399
return this;
400     }
401
402     /**
403      * Gets the territory setting. If it wasn't explicitly set, it is
404      * computed from the general locale setting.
405      *
406      * @return territory code, explicit or implicit.
407      * @draft ICU 3.6
408      * @provisional This API might change or be removed in a future release.
409      */

410     public String JavaDoc getTerritory() {
411         if (territory == null) {
412             return guessTerritory();
413         }
414         return territory; // immutable, so don't need to clone
415
}
416
417     /**
418      * Sets the currency code. If this has not been set, uses default for territory.
419      *
420      * @param currency Valid ISO 4217 currency code.
421      * @return this, for chaining
422      * @draft ICU 3.6
423      * @provisional This API might change or be removed in a future release.
424      */

425     public GlobalizationPreferences setCurrency(Currency currency) {
426         if (isFrozen()) {
427             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
428         }
429         this.currency = currency; // immutable, so don't need to clone
430
return this;
431     }
432
433     /**
434      * Get a copy of the currency computed according to the settings.
435      *
436      * @return currency code, explicit or implicit.
437      * @draft ICU 3.6
438      * @provisional This API might change or be removed in a future release.
439      */

440     public Currency getCurrency() {
441         if (currency == null) {
442             return guessCurrency();
443         }
444         return currency; // immutable, so don't have to clone
445
}
446
447     /**
448      * Sets the calendar. If this has not been set, uses default for territory.
449      *
450      * @param calendar arbitrary calendar
451      * @return this, for chaining
452      * @draft ICU 3.6
453      * @provisional This API might change or be removed in a future release.
454      */

455     public GlobalizationPreferences setCalendar(Calendar calendar) {
456         if (isFrozen()) {
457             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
458         }
459         this.calendar = (Calendar) calendar.clone(); // clone for safety
460
return this;
461     }
462
463     /**
464      * Get a copy of the calendar according to the settings.
465      *
466      * @return calendar explicit or implicit.
467      * @draft ICU 3.6
468      * @provisional This API might change or be removed in a future release.
469      */

470     public Calendar getCalendar() {
471         if (calendar == null) {
472             return guessCalendar();
473         }
474         Calendar temp = (Calendar) calendar.clone(); // clone for safety
475
temp.setTimeZone(getTimeZone());
476         temp.setTimeInMillis(System.currentTimeMillis());
477         return temp;
478     }
479
480     /**
481      * Sets the timezone ID. If this has not been set, uses default for territory.
482      *
483      * @param timezone a valid TZID (see UTS#35).
484      * @return this, for chaining
485      * @draft ICU 3.6
486      * @provisional This API might change or be removed in a future release.
487      */

488     public GlobalizationPreferences setTimeZone(TimeZone timezone) {
489         if (isFrozen()) {
490             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
491         }
492         this.timezone = (TimeZone) timezone.clone(); // clone for safety;
493
return this;
494     }
495
496     /**
497      * Get the timezone. It was either explicitly set, or is
498      * heuristically computed from other settings.
499      *
500      * @return timezone, either implicitly or explicitly set
501      * @draft ICU 3.6
502      * @provisional This API might change or be removed in a future release.
503      */

504     public TimeZone getTimeZone() {
505         if (timezone == null) {
506             return guessTimeZone();
507         }
508         return (TimeZone) timezone.clone(); // clone for safety
509
}
510
511     /**
512      * Get a copy of the collator according to the settings.
513      *
514      * @return collator explicit or implicit.
515      * @draft ICU 3.6
516      * @provisional This API might change or be removed in a future release.
517      */

518     public Collator getCollator() {
519         if (collator == null) {
520             return guessCollator();
521         }
522         try {
523             return (Collator) collator.clone(); // clone for safety
524
} catch (CloneNotSupportedException JavaDoc e) {
525             throw new IllegalStateException JavaDoc("Error in cloning collator");
526         }
527     }
528
529     /**
530      * Explicitly set the collator for this object.
531      * @param collator
532      * @return this, for chaining
533      * @draft ICU 3.6
534      * @provisional This API might change or be removed in a future release.
535      */

536     public GlobalizationPreferences setCollator(Collator collator) {
537         if (isFrozen()) {
538             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
539         }
540         try {
541             this.collator = (Collator) collator.clone(); // clone for safety
542
} catch (CloneNotSupportedException JavaDoc e) {
543                 throw new IllegalStateException JavaDoc("Error in cloning collator");
544         }
545         return this;
546     }
547
548     /**
549      * Get a copy of the break iterator for the specified type according to the
550      * settings.
551      *
552      * @param type
553      * break type - BI_CHARACTER or BI_WORD, BI_LINE, BI_SENTENCE, BI_TITLE
554      * @return break iterator explicit or implicit
555      * @draft ICU 3.6
556      * @provisional This API might change or be removed in a future release.
557      */

558     public BreakIterator getBreakIterator(int type) {
559         if (type < BI_CHARACTER || type >= BI_LIMIT) {
560             throw new IllegalArgumentException JavaDoc("Illegal break iterator type");
561         }
562         if (breakIterators == null || breakIterators[type] == null) {
563             return guessBreakIterator(type);
564         }
565         return (BreakIterator) breakIterators[type].clone(); // clone for safety
566
}
567
568     /**
569      * Explicitly set the break iterator for this object.
570      *
571      * @param type
572      * break type - BI_CHARACTER or BI_WORD, BI_LINE, BI_SENTENCE, BI_TITLE
573      * @param iterator a break iterator
574      * @return this, for chaining
575      * @draft ICU 3.6
576      * @provisional This API might change or be removed in a future release.
577      */

578     public GlobalizationPreferences setBreakIterator(int type, BreakIterator iterator) {
579         if (type < BI_CHARACTER || type >= BI_LIMIT) {
580             throw new IllegalArgumentException JavaDoc("Illegal break iterator type");
581         }
582         if (isFrozen()) {
583             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
584         }
585         if (breakIterators == null)
586             breakIterators = new BreakIterator[BI_LIMIT];
587         breakIterators[type] = (BreakIterator) iterator.clone(); // clone for safety
588
return this;
589     }
590
591     /**
592      * Get the display name for an ID: language, script, territory, currency, timezone...
593      * Uses the language priority list to do so.
594      *
595      * @param id language code, script code, ...
596      * @param type specifies the type of the ID: ID_LANGUAGE, etc.
597      * @return the display name
598      * @draft ICU 3.6
599      * @provisional This API might change or be removed in a future release.
600      */

601     public String JavaDoc getDisplayName(String JavaDoc id, int type) {
602         String JavaDoc result = id;
603         for (Iterator JavaDoc it = getLocales().iterator(); it.hasNext();) {
604             ULocale locale = (ULocale) it.next();
605             if (!isAvailableLocale(locale, TYPE_GENERIC)) {
606                 continue;
607             }
608             switch (type) {
609             case ID_LOCALE:
610                 result = ULocale.getDisplayName(id, locale);
611                 break;
612             case ID_LANGUAGE:
613                 result = ULocale.getDisplayLanguage(id, locale);
614                 break;
615             case ID_SCRIPT:
616                 result = ULocale.getDisplayScript("und-" + id, locale);
617                 break;
618             case ID_TERRITORY:
619                 result = ULocale.getDisplayCountry("und-" + id, locale);
620                 break;
621             case ID_VARIANT:
622                 // TODO fix variant parsing
623
result = ULocale.getDisplayVariant("und-QQ-" + id, locale);
624                 break;
625             case ID_KEYWORD:
626                 result = ULocale.getDisplayKeyword(id, locale);
627                 break;
628             case ID_KEYWORD_VALUE:
629                 String JavaDoc[] parts = new String JavaDoc[2];
630                 Utility.split(id,'=',parts);
631                 result = ULocale.getDisplayKeywordValue("und@"+id, parts[0], locale);
632                 // TODO fix to tell when successful
633
if (result.equals(parts[1])) {
634                     continue;
635                 }
636                 break;
637             case ID_CURRENCY_SYMBOL:
638             case ID_CURRENCY:
639                 Currency temp = new Currency(id);
640                 result =temp.getName(locale, type==ID_CURRENCY
641                                      ? Currency.LONG_NAME
642                                      : Currency.SYMBOL_NAME, new boolean[1]);
643                 // TODO: have method that doesn't take parameter. Add
644
// function to determine whether string is choice
645
// format.
646
// TODO: have method that doesn't require us
647
// to create a currency
648
break;
649             case ID_TIMEZONE:
650                 SimpleDateFormat dtf = new SimpleDateFormat("vvvv",locale);
651                 dtf.setTimeZone(TimeZone.getTimeZone(id));
652                 result = dtf.format(new Date JavaDoc());
653                 // TODO, have method that doesn't require us to create a timezone
654
// fix other hacks
655
// hack for couldn't match
656
// note, compiling with FOUNDATION omits this check for now
657
//#ifndef FOUNDATION
658
//## if (badTimeZone.reset(result).matches()) continue;
659
//#endif
660
break;
661             default:
662                 throw new IllegalArgumentException JavaDoc("Unknown type: " + type);
663             }
664
665             // TODO need better way of seeing if we fell back to root!!
666
// This will not work at all for lots of stuff
667
if (!id.equals(result)) {
668                 return result;
669             }
670         }
671         return result;
672     }
673 //#ifndef FOUNDATION
674
//## // TODO remove need for this
675
//## private static final Matcher badTimeZone = Pattern.compile("[A-Z]{2}|.*\\s\\([A-Z]{2}\\)").matcher("");
676
//#endif
677

678
679     /**
680      * Set an explicit date format. Overrides the locale priority list for
681      * a particular combination of dateStyle and timeStyle. DF_NONE should
682      * be used if for the style, where only the date or time format individually
683      * is being set.
684      *
685      * @param dateStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
686      * @param timeStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
687      * @param format The date format
688      * @return this, for chaining
689      * @draft ICU 3.6
690      * @provisional This API might change or be removed in a future release.
691      */

692     public GlobalizationPreferences setDateFormat(int dateStyle, int timeStyle, DateFormat format) {
693         if (isFrozen()) {
694             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
695         }
696         if (dateFormats == null) {
697             dateFormats = new DateFormat[DF_LIMIT][DF_LIMIT];
698         }
699         dateFormats[dateStyle][timeStyle] = (DateFormat) format.clone(); // for safety
700
return this;
701     }
702
703     /**
704      * Gets a date format according to the current settings. If there
705      * is an explicit (non-null) date/time format set, a copy of that
706      * is returned. Otherwise, the language priority list is used.
707      * DF_NONE should be used for the style, where only the date or
708      * time format individually is being gotten.
709      *
710      * @param dateStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
711      * @param timeStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
712      * @return a DateFormat, according to the above description
713      * @draft ICU 3.6
714      * @provisional This API might change or be removed in a future release.
715      */

716     public DateFormat getDateFormat(int dateStyle, int timeStyle) {
717         if (dateStyle == DF_NONE && timeStyle == DF_NONE
718                 || dateStyle < 0 || dateStyle >= DF_LIMIT
719                 || timeStyle < 0 || timeStyle >= DF_LIMIT) {
720             throw new IllegalArgumentException JavaDoc("Illegal date format style arguments");
721         }
722         DateFormat result = null;
723         if (dateFormats != null) {
724             result = dateFormats[dateStyle][timeStyle];
725         }
726         if (result != null) {
727             result = (DateFormat) result.clone(); // clone for safety
728
// Not sure overriding configuration is what we really want...
729
result.setTimeZone(getTimeZone());
730         } else {
731             result = guessDateFormat(dateStyle, timeStyle);
732         }
733         return result;
734     }
735
736     /**
737      * Gets a number format according to the current settings. If
738      * there is an explicit (non-null) number format set, a copy of
739      * that is returned. Otherwise, the language priority list is
740      * used.
741      *
742      * @param style NF_NUMBER, NF_CURRENCY, NF_PERCENT, NF_SCIENTIFIC, NF_INTEGER
743      * @draft ICU 3.6
744      * @provisional This API might change or be removed in a future release.
745      */

746     public NumberFormat getNumberFormat(int style) {
747         if (style < 0 || style >= NF_LIMIT) {
748             throw new IllegalArgumentException JavaDoc("Illegal number format type");
749         }
750         NumberFormat result = null;
751         if (numberFormats != null) {
752             result = numberFormats[style];
753         }
754         if (result != null) {
755             result = (NumberFormat) result.clone(); // clone for safety (later optimize)
756
} else {
757             result = guessNumberFormat(style);
758         }
759         return result;
760     }
761
762     /**
763      * Sets a number format explicitly. Overrides the general locale settings.
764      *
765      * @param style NF_NUMBER, NF_CURRENCY, NF_PERCENT, NF_SCIENTIFIC, NF_INTEGER
766      * @param format The number format
767      * @return this, for chaining
768      * @draft ICU 3.6
769      * @provisional This API might change or be removed in a future release.
770      */

771     public GlobalizationPreferences setNumberFormat(int style, NumberFormat format) {
772         if (isFrozen()) {
773             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
774         }
775         if (numberFormats == null) {
776             numberFormats = new NumberFormat[NF_LIMIT];
777         }
778         numberFormats[style] = (NumberFormat) format.clone(); // for safety
779
return this;
780     }
781
782     /**
783      * Restore the object to the initial state.
784      *
785      * @return this, for chaining
786      * @draft ICU 3.6
787      * @provisional This API might change or be removed in a future release.
788      */

789     public GlobalizationPreferences reset() {
790         if (isFrozen()) {
791             throw new UnsupportedOperationException JavaDoc("Attempt to modify immutable object");
792         }
793         locales = null;
794         territory = null;
795         calendar = null;
796         collator = null;
797         breakIterators = null;
798         timezone = null;
799         currency = null;
800         dateFormats = null;
801         numberFormats = null;
802         implicitLocales = null;
803         return this;
804     }
805
806     /**
807      * Process a language/locale priority list specified via <code>setLocales</code>.
808      * The input locale list may be expanded or re-ordered to represent the prioritized
809      * language/locale order actually used by this object by the algorithm exaplained
810      * below.
811      * <br>
812      * <br>
813      * <b>Step 1</b>: Move later occurence of more specific locale before ealier occurence of less
814      * specific locale.
815      * <br>
816      * Before: en, fr_FR, en_US, en_GB
817      * <br>
818      * After: en_US, en_GB, en, fr_FR
819      * <br>
820      * <br>
821      * <b>Step 2</b>: Append a fallback locale to each locale.
822      * <br>
823      * Before: en_US, en_GB, en, fr_FR
824      * <br>
825      * After: en_US, en, en_GB, en, en, fr_FR, fr
826      * <br>
827      * <br>
828      * <b>Step 3</b>: Remove ealier occurence of duplicated locale entries.
829      * <br>
830      * Before: en_US, en, en_GB, en, en, fr_FR, fr
831      * <br>
832      * After: en_US, en_GB, en, fr_FR, fr
833      * <br>
834      * <br>
835      * The final locale list is used to produce a default value for the appropriate territory,
836      * currency, timezone, etc. The list also represents the lookup order used in
837      * <code>getResourceBundle</code> for this object. A subclass may override this method
838      * to customize the algorithm used for populating the locale list.
839      *
840      * @param inputLocales The list of input locales
841      * @draft ICU 3.6
842      * @provisional This API might change or be removed in a future release.
843      */

844     protected List JavaDoc processLocales(List JavaDoc inputLocales) {
845         List JavaDoc result = new ArrayList JavaDoc();
846         /*
847          * Step 1: Relocate later occurence of more specific locale
848          * before earlier occurence of less specific locale.
849          *
850          * Example:
851          * Before - en_US, fr_FR, zh, en_US_Boston, zh_TW, zh_Hant, fr_CA
852          * After - en_US_Boston, en_US, fr_FR, zh_TW, zh_Hant, zh, fr_CA
853          */

854         for (int i = 0; i < inputLocales.size(); i++) {
855             ULocale uloc = (ULocale)inputLocales.get(i);
856
857             String JavaDoc language = uloc.getLanguage();
858             String JavaDoc script = uloc.getScript();
859             String JavaDoc country = uloc.getCountry();
860             String JavaDoc variant = uloc.getVariant();
861
862             boolean bInserted = false;
863             for (int j = 0; j < result.size(); j++) {
864                 // Check if this locale is more specific
865
// than existing locale entries already inserted
866
// in the destination list
867
ULocale u = (ULocale)result.get(j);
868                 if (!u.getLanguage().equals(language)) {
869                     continue;
870                 }
871                 String JavaDoc s = u.getScript();
872                 String JavaDoc c = u.getCountry();
873                 String JavaDoc v = u.getVariant();
874                 if (!s.equals(script)) {
875                     if (s.length() == 0 && c.length() == 0 && v.length() == 0) {
876                         result.add(j, uloc);
877                         bInserted = true;
878                         break;
879                     } else if (s.length() == 0 && c.equals(country)) {
880                         // We want to see zh_Hant_HK before zh_HK
881
result.add(j, uloc);
882                         bInserted = true;
883                         break;
884                     } else if (script.length() == 0 && country.length() > 0 && c.length() == 0) {
885                         // We want to see zh_HK before zh_Hant
886
result.add(j, uloc);
887                         bInserted = true;
888                         break;
889                     }
890                     continue;
891                 }
892                 if (!c.equals(country)) {
893                     if (c.length() == 0 && v.length() == 0) {
894                         result.add(j, uloc);
895                         bInserted = true;
896                         break;
897                     }
898                 }
899                 if (!v.equals(variant) && v.length() == 0) {
900                     result.add(j, uloc);
901                     bInserted = true;
902                     break;
903                 }
904             }
905             if (!bInserted) {
906                 // Add this locale at the end of the list
907
result.add(uloc);
908             }
909         }
910
911         // TODO: Locale aliases might be resolved here
912
// For example, zh_Hant_TW = zh_TW
913

914         /*
915          * Step 2: Append fallback locales for each entry
916          *
917          * Example:
918          * Before - en_US_Boston, en_US, fr_FR, zh_TW, zh_Hant, zh, fr_CA
919          * After - en_US_Boston, en_US, en, en_US, en, fr_FR, fr,
920          * zh_TW, zn, zh_Hant, zh, zh, fr_CA, fr
921          */

922         int index = 0;
923         while (index < result.size()) {
924             ULocale uloc = (ULocale)result.get(index);
925             while (true) {
926                 uloc = uloc.getFallback();
927                 if (uloc.getLanguage().length() == 0) {
928                     break;
929                 }
930                 index++;
931                 result.add(index, uloc);
932             }
933             index++;
934         }
935
936         /*
937          * Step 3: Remove earlier occurence of duplicated locales
938          *
939          * Example:
940          * Before - en_US_Boston, en_US, en, en_US, en, fr_FR, fr,
941          * zh_TW, zn, zh_Hant, zh, zh, fr_CA, fr
942          * After - en_US_Boston, en_US, en, fr_FR, zh_TW, zh_Hant,
943          * zh, fr_CA, fr
944          */

945         index = 0;
946         while (index < result.size() - 1) {
947             ULocale uloc = (ULocale)result.get(index);
948             boolean bRemoved = false;
949             for (int i = index + 1; i < result.size(); i++) {
950                 if (uloc.equals((ULocale)result.get(i))) {
951                     // Remove ealier one
952
result.remove(index);
953                     bRemoved = true;
954                     break;
955                 }
956             }
957             if (!bRemoved) {
958                 index++;
959             }
960         }
961         return result;
962     }
963
964     
965     /**
966      * This function can be overridden by subclasses to use different heuristics.
967      * <b>It MUST return a 'safe' value,
968      * one whose modification will not affect this object.</b>
969      *
970      * @param dateStyle
971      * @param timeStyle
972      * @draft ICU 3.6
973      * @provisional This API might change or be removed in a future release.
974      */

975     protected DateFormat guessDateFormat(int dateStyle, int timeStyle) {
976         DateFormat result;
977         ULocale dfLocale = getAvailableLocale(TYPE_DATEFORMAT);
978         if (dfLocale == null) {
979             dfLocale = ULocale.ROOT;
980         }
981         if (timeStyle == DF_NONE) {
982             result = DateFormat.getDateInstance(getCalendar(), dateStyle, dfLocale);
983         } else if (dateStyle == DF_NONE) {
984             result = DateFormat.getTimeInstance(getCalendar(), timeStyle, dfLocale);
985         } else {
986             result = DateFormat.getDateTimeInstance(getCalendar(), dateStyle, timeStyle, dfLocale);
987         }
988         return result;
989     }
990
991     /**
992      * This function can be overridden by subclasses to use different heuristics.
993      * <b>It MUST return a 'safe' value,
994      * one whose modification will not affect this object.</b>
995      *
996      * @param style
997      * @draft ICU 3.6
998      * @provisional This API might change or be removed in a future release.
999      */

1000    protected NumberFormat guessNumberFormat(int style) {
1001        NumberFormat result;
1002        ULocale nfLocale = getAvailableLocale(TYPE_NUMBERFORMAT);
1003        if (nfLocale == null) {
1004            nfLocale = ULocale.ROOT;
1005        }
1006        switch (style) {
1007        case NF_NUMBER:
1008            result = NumberFormat.getInstance(nfLocale);
1009            break;
1010        case NF_SCIENTIFIC:
1011            result = NumberFormat.getScientificInstance(nfLocale);
1012            break;
1013        case NF_INTEGER:
1014            result = NumberFormat.getIntegerInstance(nfLocale);
1015            break;
1016        case NF_PERCENT:
1017            result = NumberFormat.getPercentInstance(nfLocale);
1018            break;
1019        case NF_CURRENCY:
1020            result = NumberFormat.getCurrencyInstance(nfLocale);
1021            result.setCurrency(getCurrency());
1022            break;
1023        default:
1024            throw new IllegalArgumentException JavaDoc("Unknown number format style");
1025        }
1026        return result;
1027    }
1028
1029    /**
1030     * This function can be overridden by subclasses to use different heuristics.
1031     *
1032     * @draft ICU 3.6
1033     * @provisional This API might change or be removed in a future release.
1034     */

1035    protected String JavaDoc guessTerritory() {
1036        String JavaDoc result;
1037        // pass through locales to see if there is a territory.
1038
for (Iterator JavaDoc it = getLocales().iterator(); it.hasNext();) {
1039            ULocale locale = (ULocale)it.next();
1040            result = locale.getCountry();
1041            if (result.length() != 0) {
1042                return result;
1043            }
1044        }
1045        // if not, guess from the first language tag, or maybe from
1046
// intersection of languages, eg nl + fr => BE
1047
// TODO: fix using real data
1048
// for now, just use fixed values
1049
ULocale firstLocale = getLocale(0);
1050        String JavaDoc language = firstLocale.getLanguage();
1051        String JavaDoc script = firstLocale.getScript();
1052        result = null;
1053        if (script.length() != 0) {
1054            result = (String JavaDoc) language_territory_hack_map.get(language + "_" + script);
1055        }
1056        if (result == null) {
1057            result = (String JavaDoc) language_territory_hack_map.get(language);
1058        }
1059        if (result == null) {
1060            result = "US"; // need *some* default
1061
}
1062        return result;
1063    }
1064
1065    /**
1066     * This function can be overridden by subclasses to use different heuristics
1067     *
1068     * @draft ICU 3.6
1069     * @provisional This API might change or be removed in a future release.
1070     */

1071    protected Currency guessCurrency() {
1072        return Currency.getInstance(new ULocale("und-" + getTerritory()));
1073    }
1074
1075    /**
1076     * This function can be overridden by subclasses to use different heuristics
1077     * <b>It MUST return a 'safe' value,
1078     * one whose modification will not affect this object.</b>
1079     *
1080     * @draft ICU 3.6
1081     * @provisional This API might change or be removed in a future release.
1082     */

1083    protected List JavaDoc guessLocales() {
1084        if (implicitLocales == null) {
1085            List JavaDoc result = new ArrayList JavaDoc(1);
1086            result.add(ULocale.getDefault());
1087            implicitLocales = processLocales(result);
1088        }
1089        return implicitLocales;
1090    }
1091
1092    /**
1093     * This function can be overridden by subclasses to use different heuristics.
1094     * <b>It MUST return a 'safe' value,
1095     * one whose modification will not affect this object.</b>
1096     *
1097     * @draft ICU 3.6
1098     * @provisional This API might change or be removed in a future release.
1099     */

1100    protected Collator guessCollator() {
1101        ULocale collLocale = getAvailableLocale(TYPE_COLLATOR);
1102        if (collLocale == null) {
1103            collLocale = ULocale.ROOT;
1104        }
1105        return Collator.getInstance(collLocale);
1106    }
1107
1108    /**
1109     * This function can be overridden by subclasses to use different heuristics.
1110     * <b>It MUST return a 'safe' value,
1111     * one whose modification will not affect this object.</b>
1112     *
1113     * @param type
1114     * @draft ICU 3.6
1115     * @provisional This API might change or be removed in a future release.
1116     */

1117    protected BreakIterator guessBreakIterator(int type) {
1118        BreakIterator bitr = null;
1119        ULocale brkLocale = getAvailableLocale(TYPE_BREAKITERATOR);
1120        if (brkLocale == null) {
1121            brkLocale = ULocale.ROOT;
1122        }
1123        switch (type) {
1124        case BI_CHARACTER:
1125            bitr = BreakIterator.getCharacterInstance(brkLocale);
1126            break;
1127        case BI_TITLE:
1128            bitr = BreakIterator.getTitleInstance(brkLocale);
1129            break;
1130        case BI_WORD:
1131            bitr = BreakIterator.getWordInstance(brkLocale);
1132            break;
1133        case BI_LINE:
1134            bitr = BreakIterator.getLineInstance(brkLocale);
1135            break;
1136        case BI_SENTENCE:
1137            bitr = BreakIterator.getSentenceInstance(brkLocale);
1138            break;
1139        default:
1140            throw new IllegalArgumentException JavaDoc("Unknown break iterator type");
1141        }
1142        return bitr;
1143    }
1144
1145    /**
1146     * This function can be overridden by subclasses to use different heuristics.
1147     * <b>It MUST return a 'safe' value,
1148     * one whose modification will not affect this object.</b>
1149     *
1150     * @draft ICU 3.6
1151     * @provisional This API might change or be removed in a future release.
1152     */

1153    protected TimeZone guessTimeZone() {
1154        // TODO fix using real data
1155
// for single-zone countries, pick that zone
1156
// for others, pick the most populous zone
1157
// for now, just use fixed value
1158
// NOTE: in a few cases can do better by looking at language.
1159
// Eg haw+US should go to Pacific/Honolulu
1160
// fr+CA should go to America/Montreal
1161
String JavaDoc timezoneString = (String JavaDoc) territory_tzid_hack_map.get(getTerritory());
1162        if (timezoneString == null) {
1163            String JavaDoc[] attempt = ZoneMeta.getAvailableIDs(getTerritory());
1164            if (attempt.length == 0) {
1165                timezoneString = "Etc/GMT"; // gotta do something
1166
} else {
1167                int i;
1168                // this all needs to be fixed to use real data. But for now, do slightly better by skipping cruft
1169
for (i = 0; i < attempt.length; ++i) {
1170                    if (attempt[i].indexOf("/") >= 0) break;
1171                }
1172                if (i > attempt.length) i = 0;
1173                timezoneString = attempt[i];
1174            }
1175        }
1176        return TimeZone.getTimeZone(timezoneString);
1177    }
1178
1179    /**
1180     * This function can be overridden by subclasses to use different heuristics.
1181     * <b>It MUST return a 'safe' value,
1182     * one whose modification will not affect this object.</b>
1183     *
1184     * @draft ICU 3.6
1185     * @provisional This API might change or be removed in a future release.
1186     */

1187    protected Calendar guessCalendar() {
1188        ULocale calLocale = getAvailableLocale(TYPE_CALENDAR);
1189        if (calLocale == null) {
1190            calLocale = ULocale.US;
1191        }
1192        return Calendar.getInstance(getTimeZone(), calLocale);
1193    }
1194    
1195    // PRIVATES
1196

1197    private List JavaDoc locales;
1198    private String JavaDoc territory;
1199    private Currency currency;
1200    private TimeZone timezone;
1201    private Calendar calendar;
1202    private Collator collator;
1203    private BreakIterator[] breakIterators;
1204    private DateFormat[][] dateFormats;
1205    private NumberFormat[] numberFormats;
1206    private List JavaDoc implicitLocales;
1207    
1208    {
1209        reset();
1210    }
1211
1212
1213    private ULocale getAvailableLocale(int type) {
1214        List JavaDoc locs = getLocales();
1215        ULocale result = null;
1216        for (int i = 0; i < locs.size(); i++) {
1217            ULocale l = (ULocale)locs.get(i);
1218            if (isAvailableLocale(l, type)) {
1219                result = l;
1220                break;
1221            }
1222        }
1223        return result;
1224    }
1225
1226    private boolean isAvailableLocale(ULocale loc, int type) {
1227        BitSet JavaDoc bits = (BitSet JavaDoc)available_locales.get(loc);
1228        if (bits != null && bits.get(type)) {
1229            return true;
1230        }
1231        return false;
1232    }
1233    
1234    /*
1235     * Available locales for service types
1236     */

1237    private static final HashMap JavaDoc available_locales = new HashMap JavaDoc();
1238    private static final int
1239        TYPE_GENERIC = 0,
1240        TYPE_CALENDAR = 1,
1241        TYPE_DATEFORMAT= 2,
1242        TYPE_NUMBERFORMAT = 3,
1243        TYPE_COLLATOR = 4,
1244        TYPE_BREAKITERATOR = 5,
1245        TYPE_LIMIT = TYPE_BREAKITERATOR + 1;
1246        
1247    static {
1248        BitSet JavaDoc bits;
1249        ULocale[] allLocales = ULocale.getAvailableLocales();
1250        for (int i = 0; i < allLocales.length; i++) {
1251            bits = new BitSet JavaDoc(TYPE_LIMIT);
1252            available_locales.put(allLocales[i], bits);
1253            bits.set(TYPE_GENERIC);
1254        }
1255
1256        ULocale[] calLocales = Calendar.getAvailableULocales();
1257        for (int i = 0; i < calLocales.length; i++) {
1258            bits = (BitSet JavaDoc)available_locales.get(calLocales[i]);
1259            if (bits == null) {
1260                bits = new BitSet JavaDoc(TYPE_LIMIT);
1261                available_locales.put(allLocales[i], bits);
1262            }
1263            bits.set(TYPE_CALENDAR);
1264        }
1265
1266        ULocale[] dateLocales = DateFormat.getAvailableULocales();
1267        for (int i = 0; i < dateLocales.length; i++) {
1268            bits = (BitSet JavaDoc)available_locales.get(dateLocales[i]);
1269            if (bits == null) {
1270                bits = new BitSet JavaDoc(TYPE_LIMIT);
1271                available_locales.put(allLocales[i], bits);
1272            }
1273            bits.set(TYPE_DATEFORMAT);
1274        }
1275
1276        ULocale[] numLocales = NumberFormat.getAvailableULocales();
1277        for (int i = 0; i < numLocales.length; i++) {
1278            bits = (BitSet JavaDoc)available_locales.get(numLocales[i]);
1279            if (bits == null) {
1280                bits = new BitSet JavaDoc(TYPE_LIMIT);
1281                available_locales.put(allLocales[i], bits);
1282            }
1283            bits.set(TYPE_NUMBERFORMAT);
1284        }
1285
1286        ULocale[] collLocales = Collator.getAvailableULocales();
1287        for (int i = 0; i < collLocales.length; i++) {
1288            bits = (BitSet JavaDoc)available_locales.get(collLocales[i]);
1289            if (bits == null) {
1290                bits = new BitSet JavaDoc(TYPE_LIMIT);
1291                available_locales.put(allLocales[i], bits);
1292            }
1293            bits.set(TYPE_COLLATOR);
1294        }
1295
1296        ULocale[] brkLocales = BreakIterator.getAvailableULocales();
1297        for (int i = 0; i < brkLocales.length; i++) {
1298            bits = (BitSet JavaDoc)available_locales.get(brkLocales[i]);
1299            bits.set(TYPE_BREAKITERATOR);
1300        }
1301    }
1302
1303    /** WARNING: All of this data is temporary, until we start importing from CLDR!!!
1304     *
1305     */

1306    private static final Map JavaDoc language_territory_hack_map = new HashMap JavaDoc();
1307    private static final String JavaDoc[][] language_territory_hack = {
1308        {"af", "ZA"},
1309        {"am", "ET"},
1310        {"ar", "SA"},
1311        {"as", "IN"},
1312        {"ay", "PE"},
1313        {"az", "AZ"},
1314        {"bal", "PK"},
1315        {"be", "BY"},
1316        {"bg", "BG"},
1317        {"bn", "IN"},
1318        {"bs", "BA"},
1319        {"ca", "ES"},
1320        {"ch", "MP"},
1321        {"cpe", "SL"},
1322        {"cs", "CZ"},
1323        {"cy", "GB"},
1324        {"da", "DK"},
1325        {"de", "DE"},
1326        {"dv", "MV"},
1327        {"dz", "BT"},
1328        {"el", "GR"},
1329        {"en", "US"},
1330        {"es", "ES"},
1331        {"et", "EE"},
1332        {"eu", "ES"},
1333        {"fa", "IR"},
1334        {"fi", "FI"},
1335        {"fil", "PH"},
1336        {"fj", "FJ"},
1337        {"fo", "FO"},
1338        {"fr", "FR"},
1339        {"ga", "IE"},
1340        {"gd", "GB"},
1341        {"gl", "ES"},
1342        {"gn", "PY"},
1343        {"gu", "IN"},
1344        {"gv", "GB"},
1345        {"ha", "NG"},
1346        {"he", "IL"},
1347        {"hi", "IN"},
1348        {"ho", "PG"},
1349        {"hr", "HR"},
1350        {"ht", "HT"},
1351        {"hu", "HU"},
1352        {"hy", "AM"},
1353        {"id", "ID"},
1354        {"is", "IS"},
1355        {"it", "IT"},
1356        {"ja", "JP"},
1357        {"ka", "GE"},
1358        {"kk", "KZ"},
1359        {"kl", "GL"},
1360        {"km", "KH"},
1361        {"kn", "IN"},
1362        {"ko", "KR"},
1363        {"kok", "IN"},
1364        {"ks", "IN"},
1365        {"ku", "TR"},
1366        {"ky", "KG"},
1367        {"la", "VA"},
1368        {"lb", "LU"},
1369        {"ln", "CG"},
1370        {"lo", "LA"},
1371        {"lt", "LT"},
1372        {"lv", "LV"},
1373        {"mai", "IN"},
1374        {"men", "GN"},
1375        {"mg", "MG"},
1376        {"mh", "MH"},
1377        {"mk", "MK"},
1378        {"ml", "IN"},
1379        {"mn", "MN"},
1380        {"mni", "IN"},
1381        {"mo", "MD"},
1382        {"mr", "IN"},
1383        {"ms", "MY"},
1384        {"mt", "MT"},
1385        {"my", "MM"},
1386        {"na", "NR"},
1387        {"nb", "NO"},
1388        {"nd", "ZA"},
1389        {"ne", "NP"},
1390        {"niu", "NU"},
1391        {"nl", "NL"},
1392        {"nn", "NO"},
1393        {"no", "NO"},
1394        {"nr", "ZA"},
1395        {"nso", "ZA"},
1396        {"ny", "MW"},
1397        {"om", "KE"},
1398        {"or", "IN"},
1399        {"pa", "IN"},
1400        {"pau", "PW"},
1401        {"pl", "PL"},
1402        {"ps", "PK"},
1403        {"pt", "BR"},
1404        {"qu", "PE"},
1405        {"rn", "BI"},
1406        {"ro", "RO"},
1407        {"ru", "RU"},
1408        {"rw", "RW"},
1409        {"sd", "IN"},
1410        {"sg", "CF"},
1411        {"si", "LK"},
1412        {"sk", "SK"},
1413        {"sl", "SI"},
1414        {"sm", "WS"},
1415        {"so", "DJ"},
1416        {"sq", "CS"},
1417        {"sr", "CS"},
1418        {"ss", "ZA"},
1419        {"st", "ZA"},
1420        {"sv", "SE"},
1421        {"sw", "KE"},
1422        {"ta", "IN"},
1423        {"te", "IN"},
1424        {"tem", "SL"},
1425        {"tet", "TL"},
1426        {"th", "TH"},
1427        {"ti", "ET"},
1428        {"tg", "TJ"},
1429        {"tk", "TM"},
1430        {"tkl", "TK"},
1431        {"tvl", "TV"},
1432        {"tl", "PH"},
1433        {"tn", "ZA"},
1434        {"to", "TO"},
1435        {"tpi", "PG"},
1436        {"tr", "TR"},
1437        {"ts", "ZA"},
1438        {"uk", "UA"},
1439        {"ur", "IN"},
1440        {"uz", "UZ"},
1441        {"ve", "ZA"},
1442        {"vi", "VN"},
1443        {"wo", "SN"},
1444        {"xh", "ZA"},
1445        {"zh", "CN"},
1446        {"zh_Hant", "TW"},
1447        {"zu", "ZA"},
1448        {"aa", "ET"},
1449        {"byn", "ER"},
1450        {"eo", "DE"},
1451        {"gez", "ET"},
1452        {"haw", "US"},
1453        {"iu", "CA"},
1454        {"kw", "GB"},
1455        {"sa", "IN"},
1456        {"sh", "HR"},
1457        {"sid", "ET"},
1458        {"syr", "SY"},
1459        {"tig", "ER"},
1460        {"tt", "RU"},
1461        {"wal", "ET"}, };
1462    static {
1463        for (int i = 0; i < language_territory_hack.length; ++i) {
1464            language_territory_hack_map.put(language_territory_hack[i][0],language_territory_hack[i][1]);
1465        }
1466    }
1467
1468    static final Map JavaDoc territory_tzid_hack_map = new HashMap JavaDoc();
1469    static final String JavaDoc[][] territory_tzid_hack = {
1470        {"AQ", "Antarctica/McMurdo"},
1471        {"AR", "America/Buenos_Aires"},
1472        {"AU", "Australia/Sydney"},
1473        {"BR", "America/Sao_Paulo"},
1474        {"CA", "America/Toronto"},
1475        {"CD", "Africa/Kinshasa"},
1476        {"CL", "America/Santiago"},
1477        {"CN", "Asia/Shanghai"},
1478        {"EC", "America/Guayaquil"},
1479        {"ES", "Europe/Madrid"},
1480        {"GB", "Europe/London"},
1481        {"GL", "America/Godthab"},
1482        {"ID", "Asia/Jakarta"},
1483        {"ML", "Africa/Bamako"},
1484        {"MX", "America/Mexico_City"},
1485        {"MY", "Asia/Kuala_Lumpur"},
1486        {"NZ", "Pacific/Auckland"},
1487        {"PT", "Europe/Lisbon"},
1488        {"RU", "Europe/Moscow"},
1489        {"UA", "Europe/Kiev"},
1490        {"US", "America/New_York"},
1491        {"UZ", "Asia/Tashkent"},
1492        {"PF", "Pacific/Tahiti"},
1493        {"FM", "Pacific/Kosrae"},
1494        {"KI", "Pacific/Tarawa"},
1495        {"KZ", "Asia/Almaty"},
1496        {"MH", "Pacific/Majuro"},
1497        {"MN", "Asia/Ulaanbaatar"},
1498        {"SJ", "Arctic/Longyearbyen"},
1499        {"UM", "Pacific/Midway"},
1500    };
1501    static {
1502        for (int i = 0; i < territory_tzid_hack.length; ++i) {
1503            territory_tzid_hack_map.put(territory_tzid_hack[i][0],territory_tzid_hack[i][1]);
1504        }
1505    }
1506
1507    // Freezable implmentation
1508

1509    private boolean frozen;
1510
1511    /**
1512     * @draft ICU 3.6
1513     * @provisional This API might change or be removed in a future release.
1514     */

1515    public boolean isFrozen() {
1516        return frozen;
1517    }
1518
1519    /**
1520     * @draft ICU 3.6
1521     * @provisional This API might change or be removed in a future release.
1522     */

1523    public Object JavaDoc freeze() {
1524        frozen = true;
1525        return this;
1526    }
1527
1528    /**
1529     * @draft ICU 3.6
1530     * @provisional This API might change or be removed in a future release.
1531     */

1532    public Object JavaDoc cloneAsThawed() {
1533        try {
1534            GlobalizationPreferences result = (GlobalizationPreferences) clone();
1535            result.frozen = false;
1536            return result;
1537        } catch (CloneNotSupportedException JavaDoc e) {
1538            // will always work
1539
return null;
1540        }
1541    }
1542}
1543
1544
Popular Tags