Source Code Cross Referenced for GlobalizationPreferences.java in  » Internationalization-Localization » icu4j » com » ibm » icu » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Internationalization Localization » icu4j » com.ibm.icu.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        //##header
0002:        /*
0003:         *******************************************************************************
0004:         * Copyright (C) 2004-2006, International Business Machines Corporation and    *
0005:         * others. All Rights Reserved.                                                *
0006:         *******************************************************************************
0007:         */
0008:        package com.ibm.icu.util;
0009:
0010:        import java.util.ArrayList;
0011:        import java.util.Arrays;
0012:        import java.util.BitSet;
0013:        import java.util.Date;
0014:        import java.util.HashMap;
0015:        import java.util.Iterator;
0016:        import java.util.LinkedList;
0017:        import java.util.List;
0018:        import java.util.Map;
0019:        import java.util.MissingResourceException;
0020:        import java.util.ResourceBundle;
0021:        import java.util.TreeMap; //#ifndef FOUNDATION
0022:        import java.util.regex.Matcher;
0023:        import java.util.regex.Pattern; //#endif
0024:        import com.ibm.icu.impl.Utility;
0025:        import com.ibm.icu.impl.ZoneMeta;
0026:        import com.ibm.icu.text.BreakIterator;
0027:        import com.ibm.icu.text.Collator;
0028:        import com.ibm.icu.text.DateFormat;
0029:        import com.ibm.icu.text.NumberFormat;
0030:        import com.ibm.icu.text.SimpleDateFormat;
0031:
0032:        /**
0033:         * This convenience class provides a mechanism for bundling together different
0034:         * globalization preferences. It includes:
0035:         * <ul>
0036:         * <li>A list of locales/languages in preference order</li>
0037:         * <li>A territory</li>
0038:         * <li>A currency</li>
0039:         * <li>A timezone</li>
0040:         * <li>A calendar</li>
0041:         * <li>A collator (for language-sensitive sorting, searching, and matching).</li>
0042:         * <li>Explicit overrides for date/time formats, etc.</li>
0043:         * </ul>
0044:         * The class will heuristically compute implicit, heuristic values for the above
0045:         * based on available data if explicit values are not supplied. These implicit
0046:         * values can be presented to users for confirmation, or replacement if the
0047:         * values are incorrect.
0048:         * <p>
0049:         * To reset any explicit field so that it will get heuristic values, pass in
0050:         * null. For example, myPreferences.setLocale(null);
0051:         * <p>
0052:         * All of the heuristics can be customized by subclasses, by overriding
0053:         * getTerritory(), guessCollator(), etc.
0054:         * <p>
0055:         * The class also supplies display names for languages, scripts, territories,
0056:         * currencies, timezones, etc. These are computed according to the
0057:         * locale/language preference list. Thus, if the preference is Breton; French;
0058:         * English, then the display name for a language will be returned in Breton if
0059:         * available, otherwise in French if available, otherwise in English.
0060:         * <p>
0061:         * The codes used to reference territory, currency, etc. are as defined elsewhere
0062:         * in ICU, and are taken from CLDR (which reflects RFC 3066bis usage, ISO 4217,
0063:         * and the TZ Timezone database identifiers).
0064:         * <p>
0065:         * <b>This is at a prototype stage, and has not incorporated all the design
0066:         * changes that we would like yet; further feedback is welcome.</b></p>
0067:         * <p>
0068:         * TODO:<ul>
0069:         * <li>Add Holidays</li>
0070:         * <li>Add convenience to get/take Locale as well as ULocale.</li>
0071:         * <li>Add Lenient datetime formatting when that is available.</li>
0072:         * <li>Should this be serializable?</li>
0073:         * <li>Other utilities?</li>
0074:         * </ul>
0075:         * Note:
0076:         * <ul>
0077:         * <li>to get the display name for the first day of the week, use the calendar +
0078:         * display names.</li>
0079:         * <li>to get the work days, ask the calendar (when that is available).</li>
0080:         * <li>to get papersize / measurement system/bidi-orientation, ask the locale
0081:         * (when that is available there)</li>
0082:         * <li>to get the field order in a date, and whether a time is 24hour or not,
0083:         * ask the DateFormat (when that is available there)</li>
0084:         * <li>it will support HOST locale when it becomes available (it is a special
0085:         * locale that will ask the services to use the host platform's values).</li>
0086:         * </ul>
0087:         *
0088:         * @draft ICU 3.6
0089:         * @provisional This API might change or be removed in a future release.
0090:         */
0091:        public class GlobalizationPreferences implements  Freezable {
0092:
0093:            /**
0094:             * Default constructor
0095:             * @draft ICU 3.6
0096:             * @provisional This API might change or be removed in a future release.
0097:             */
0098:            public GlobalizationPreferences() {
0099:            }
0100:
0101:            /**
0102:             * Number Format types
0103:             * @draft ICU 3.6
0104:             * @provisional This API might change or be removed in a future release.
0105:             */
0106:            public static final int NF_NUMBER = 0, // NumberFormat.NUMBERSTYLE
0107:                    NF_CURRENCY = 1, // NumberFormat.CURRENCYSTYLE
0108:                    NF_PERCENT = 2, // NumberFormat.PERCENTSTYLE
0109:                    NF_SCIENTIFIC = 3, // NumberFormat.SCIENTIFICSTYLE
0110:                    NF_INTEGER = 4; // NumberFormat.INTEGERSTYLE
0111:
0112:            private static final int NF_LIMIT = NF_INTEGER + 1;
0113:
0114:            /**
0115:             * Date Format types
0116:             * @draft ICU 3.6
0117:             * @provisional This API might change or be removed in a future release.
0118:             */
0119:            public static final int DF_FULL = DateFormat.FULL, // 0
0120:                    DF_LONG = DateFormat.LONG, // 1
0121:                    DF_MEDIUM = DateFormat.MEDIUM, // 2
0122:                    DF_SHORT = DateFormat.SHORT, // 3
0123:                    DF_NONE = 4;
0124:
0125:            private static final int DF_LIMIT = DF_NONE + 1;
0126:
0127:            /**
0128:             * For selecting a choice of display names
0129:             * @draft ICU 3.6
0130:             * @provisional This API might change or be removed in a future release.
0131:             */
0132:            public static final int ID_LOCALE = 0, ID_LANGUAGE = 1,
0133:                    ID_SCRIPT = 2, ID_TERRITORY = 3, ID_VARIANT = 4,
0134:                    ID_KEYWORD = 5, ID_KEYWORD_VALUE = 6, ID_CURRENCY = 7,
0135:                    ID_CURRENCY_SYMBOL = 8, ID_TIMEZONE = 9;
0136:
0137:            private static final int ID_LIMIT = ID_TIMEZONE + 1;
0138:
0139:            /**
0140:             * Break iterator types
0141:             * @draft ICU 3.6
0142:             * @deprecated This API is ICU internal only
0143:             */
0144:            public static final int BI_CHARACTER = BreakIterator.KIND_CHARACTER, // 0
0145:                    BI_WORD = BreakIterator.KIND_WORD, // 1
0146:                    BI_LINE = BreakIterator.KIND_LINE, // 2
0147:                    BI_SENTENCE = BreakIterator.KIND_SENTENCE, // 3
0148:                    BI_TITLE = BreakIterator.KIND_TITLE; // 4
0149:
0150:            private static final int BI_LIMIT = BI_TITLE + 1;
0151:
0152:            /**
0153:             * Sets the language/locale priority list. If other information is
0154:             * not (yet) available, this is used to to produce a default value
0155:             * for the appropriate territory, currency, timezone, etc.  The
0156:             * user should be given the opportunity to correct those defaults
0157:             * in case they are incorrect.
0158:             * 
0159:             * @param inputLocales list of locales in priority order, eg {"be", "fr"} 
0160:             *     for Breton first, then French if that fails.
0161:             * @return this, for chaining
0162:             * @draft ICU 3.6
0163:             * @provisional This API might change or be removed in a future release.
0164:             */
0165:            public GlobalizationPreferences setLocales(List inputLocales) {
0166:                if (isFrozen()) {
0167:                    throw new UnsupportedOperationException(
0168:                            "Attempt to modify immutable object");
0169:                }
0170:                locales = processLocales(inputLocales);
0171:                return this ;
0172:            }
0173:
0174:            /**
0175:             * Get a copy of the language/locale priority list
0176:             * 
0177:             * @return a copy of the language/locale priority list.
0178:             * @draft ICU 3.6
0179:             * @provisional This API might change or be removed in a future release.
0180:             */
0181:            public List getLocales() {
0182:                List result;
0183:                if (locales == null) {
0184:                    result = guessLocales();
0185:                } else {
0186:                    result = new ArrayList();
0187:                    result.addAll(locales);
0188:                }
0189:                return result;
0190:            }
0191:
0192:            /**
0193:             * Convenience function for getting the locales in priority order
0194:             * @param index The index (0..n) of the desired item.
0195:             * @return desired item. null if index is out of range
0196:             * @draft ICU 3.6
0197:             * @provisional This API might change or be removed in a future release.
0198:             */
0199:            public ULocale getLocale(int index) {
0200:                List lcls = locales;
0201:                if (lcls == null) {
0202:                    lcls = guessLocales();
0203:                }
0204:                if (index >= 0 && index < lcls.size()) {
0205:                    return (ULocale) lcls.get(index);
0206:                }
0207:                return null;
0208:            }
0209:
0210:            /**
0211:             * Convenience routine for setting the language/locale priority
0212:             * list from an array.
0213:             * 
0214:             * @see #setLocales(List locales)
0215:             * @param uLocales list of locales in an array
0216:             * @return this, for chaining
0217:             * @draft ICU 3.6
0218:             * @provisional This API might change or be removed in a future release.
0219:             */
0220:            public GlobalizationPreferences setLocales(ULocale[] uLocales) {
0221:                if (isFrozen()) {
0222:                    throw new UnsupportedOperationException(
0223:                            "Attempt to modify immutable object");
0224:                }
0225:                return setLocales(Arrays.asList(uLocales));
0226:            }
0227:
0228:            /**
0229:             * Convenience routine for setting the language/locale priority
0230:             * list from a single locale/language.
0231:             * 
0232:             * @see #setLocales(List locales)
0233:             * @param uLocale single locale
0234:             * @return this, for chaining
0235:             * @draft ICU 3.6
0236:             * @provisional This API might change or be removed in a future release.
0237:             */
0238:            public GlobalizationPreferences setLocale(ULocale uLocale) {
0239:                if (isFrozen()) {
0240:                    throw new UnsupportedOperationException(
0241:                            "Attempt to modify immutable object");
0242:                }
0243:                return setLocales(new ULocale[] { uLocale });
0244:            }
0245:
0246:            //#ifndef FOUNDATION
0247:            /**
0248:             * Convenience routine for setting the locale priority list from
0249:             * an Accept-Language string.
0250:             * @see #setLocales(List locales)
0251:             * @param acceptLanguageString Accept-Language list, as defined by 
0252:             *     Section 14.4 of the RFC 2616 (HTTP 1.1)
0253:             * @return this, for chaining
0254:             * @draft ICU 3.6
0255:             * @provisional This API might change or be removed in a future release.
0256:             */
0257:            public GlobalizationPreferences setLocales(
0258:                    String acceptLanguageString) {
0259:                if (isFrozen()) {
0260:                    throw new UnsupportedOperationException(
0261:                            "Attempt to modify immutable object");
0262:                }
0263:                /*
0264:                  Accept-Language = "Accept-Language" ":" 1#( language-range [ ";" "q" "=" qvalue ] )
0265:                  x matches x-...
0266:                 */
0267:                // reorders in quality order
0268:                // don't care that it is not very efficient right now
0269:                Matcher acceptMatcher = Pattern.compile(
0270:                        "\\s*([-_a-zA-Z]+)(;q=([.0-9]+))?\\s*").matcher("");
0271:                Map reorder = new TreeMap();
0272:                String[] pieces = acceptLanguageString.split(",");
0273:
0274:                for (int i = 0; i < pieces.length; ++i) {
0275:                    Double qValue = new Double(1);
0276:                    try {
0277:                        if (!acceptMatcher.reset(pieces[i]).matches()) {
0278:                            throw new IllegalArgumentException();
0279:                        }
0280:                        String qValueString = acceptMatcher.group(3);
0281:                        if (qValueString != null) {
0282:                            qValue = new Double(Double
0283:                                    .parseDouble(qValueString));
0284:                        }
0285:                    } catch (Exception e) {
0286:                        throw new IllegalArgumentException("element '"
0287:                                + pieces[i]
0288:                                + "' is not of the form '<locale>{;q=<number>}");
0289:                    }
0290:                    List items = (List) reorder.get(qValue);
0291:                    if (items == null) {
0292:                        reorder.put(qValue, items = new LinkedList());
0293:                    }
0294:                    items.add(0, acceptMatcher.group(1)); // reverse order, will reverse again
0295:                }
0296:                // now read out in reverse order
0297:                List result = new ArrayList();
0298:                for (Iterator it = reorder.keySet().iterator(); it.hasNext();) {
0299:                    Object key = it.next();
0300:                    List items = (List) reorder.get(key);
0301:                    for (Iterator it2 = items.iterator(); it2.hasNext();) {
0302:                        result.add(0, new ULocale((String) it2.next()));
0303:                    }
0304:                }
0305:                return setLocales(result);
0306:            }
0307:
0308:            //#endif
0309:
0310:            /**
0311:             * Convenience function to get a ResourceBundle instance using
0312:             * the specified base name based on the language/locale priority list
0313:             * stored in this object.
0314:             *  
0315:             * @param baseName the base name of the resource bundle, a fully qualified
0316:             * class name
0317:             * @return a resource bundle for the given base name and locale based on the
0318:             * language/locale priority list stored in this object
0319:             * @draft ICU 3.6
0320:             * @provisional This API might change or be removed in a future release.
0321:             */
0322:            public ResourceBundle getResourceBundle(String baseName) {
0323:                return getResourceBundle(baseName, null);
0324:            }
0325:
0326:            /**
0327:             * Convenience function to get a ResourceBundle instance using
0328:             * the specified base name and class loader based on the language/locale
0329:             * priority list stored in this object.
0330:             *  
0331:             * @param baseName the base name of the resource bundle, a fully qualified
0332:             * class name
0333:             * @param loader the class object from which to load the resource bundle
0334:             * @return a resource bundle for the given base name and locale based on the
0335:             * language/locale priority list stored in this object
0336:             * @draft ICU 3.6
0337:             * @provisional This API might change or be removed in a future release.
0338:             */
0339:            public ResourceBundle getResourceBundle(String baseName,
0340:                    ClassLoader loader) {
0341:                UResourceBundle urb = null;
0342:                UResourceBundle candidate = null;
0343:                String actualLocaleName = null;
0344:                List fallbacks = getLocales();
0345:                for (int i = 0; i < fallbacks.size(); i++) {
0346:                    String localeName = ((ULocale) fallbacks.get(i)).toString();
0347:                    if (actualLocaleName != null
0348:                            && localeName.equals(actualLocaleName)) {
0349:                        // Actual locale name in the previous round may exactly matches
0350:                        // with the next fallback locale
0351:                        urb = candidate;
0352:                        break;
0353:                    }
0354:                    try {
0355:                        if (loader == null) {
0356:                            candidate = UResourceBundle.getBundleInstance(
0357:                                    baseName, localeName);
0358:                        } else {
0359:                            candidate = UResourceBundle.getBundleInstance(
0360:                                    baseName, localeName, loader);
0361:                        }
0362:                        if (candidate != null) {
0363:                            actualLocaleName = candidate.getULocale().getName();
0364:                            if (actualLocaleName.equals(localeName)) {
0365:                                urb = candidate;
0366:                                break;
0367:                            }
0368:                            if (urb == null) {
0369:                                // Preserve the available bundle as the last resort
0370:                                urb = candidate;
0371:                            }
0372:                        }
0373:                    } catch (MissingResourceException mre) {
0374:                        actualLocaleName = null;
0375:                        continue;
0376:                    }
0377:                }
0378:                if (urb == null) {
0379:                    throw new MissingResourceException(
0380:                            "Can't find bundle for base name " + baseName,
0381:                            baseName, "");
0382:                }
0383:                return urb;
0384:            }
0385:
0386:            /**
0387:             * Sets the territory, which is a valid territory according to for
0388:             * RFC 3066 (or successor).  If not otherwise set, default
0389:             * currency and timezone values will be set from this.  The user
0390:             * should be given the opportunity to correct those defaults in
0391:             * case they are incorrect.
0392:             * 
0393:             * @param territory code
0394:             * @return this, for chaining
0395:             * @draft ICU 3.6
0396:             * @provisional This API might change or be removed in a future release.
0397:             */
0398:            public GlobalizationPreferences setTerritory(String territory) {
0399:                if (isFrozen()) {
0400:                    throw new UnsupportedOperationException(
0401:                            "Attempt to modify immutable object");
0402:                }
0403:                this .territory = territory; // immutable, so don't need to clone
0404:                return this ;
0405:            }
0406:
0407:            /**
0408:             * Gets the territory setting. If it wasn't explicitly set, it is
0409:             * computed from the general locale setting.
0410:             * 
0411:             * @return territory code, explicit or implicit.
0412:             * @draft ICU 3.6
0413:             * @provisional This API might change or be removed in a future release.
0414:             */
0415:            public String getTerritory() {
0416:                if (territory == null) {
0417:                    return guessTerritory();
0418:                }
0419:                return territory; // immutable, so don't need to clone
0420:            }
0421:
0422:            /**
0423:             * Sets the currency code. If this has not been set, uses default for territory.
0424:             * 
0425:             * @param currency Valid ISO 4217 currency code.
0426:             * @return this, for chaining
0427:             * @draft ICU 3.6
0428:             * @provisional This API might change or be removed in a future release.
0429:             */
0430:            public GlobalizationPreferences setCurrency(Currency currency) {
0431:                if (isFrozen()) {
0432:                    throw new UnsupportedOperationException(
0433:                            "Attempt to modify immutable object");
0434:                }
0435:                this .currency = currency; // immutable, so don't need to clone
0436:                return this ;
0437:            }
0438:
0439:            /**
0440:             * Get a copy of the currency computed according to the settings.
0441:             * 
0442:             * @return currency code, explicit or implicit.
0443:             * @draft ICU 3.6
0444:             * @provisional This API might change or be removed in a future release.
0445:             */
0446:            public Currency getCurrency() {
0447:                if (currency == null) {
0448:                    return guessCurrency();
0449:                }
0450:                return currency; // immutable, so don't have to clone
0451:            }
0452:
0453:            /**
0454:             * Sets the calendar. If this has not been set, uses default for territory.
0455:             * 
0456:             * @param calendar arbitrary calendar
0457:             * @return this, for chaining
0458:             * @draft ICU 3.6
0459:             * @provisional This API might change or be removed in a future release.
0460:             */
0461:            public GlobalizationPreferences setCalendar(Calendar calendar) {
0462:                if (isFrozen()) {
0463:                    throw new UnsupportedOperationException(
0464:                            "Attempt to modify immutable object");
0465:                }
0466:                this .calendar = (Calendar) calendar.clone(); // clone for safety
0467:                return this ;
0468:            }
0469:
0470:            /**
0471:             * Get a copy of the calendar according to the settings. 
0472:             * 
0473:             * @return calendar explicit or implicit.
0474:             * @draft ICU 3.6
0475:             * @provisional This API might change or be removed in a future release.
0476:             */
0477:            public Calendar getCalendar() {
0478:                if (calendar == null) {
0479:                    return guessCalendar();
0480:                }
0481:                Calendar temp = (Calendar) calendar.clone(); // clone for safety
0482:                temp.setTimeZone(getTimeZone());
0483:                temp.setTimeInMillis(System.currentTimeMillis());
0484:                return temp;
0485:            }
0486:
0487:            /**
0488:             * Sets the timezone ID.  If this has not been set, uses default for territory.
0489:             * 
0490:             * @param timezone a valid TZID (see UTS#35).
0491:             * @return this, for chaining
0492:             * @draft ICU 3.6
0493:             * @provisional This API might change or be removed in a future release.
0494:             */
0495:            public GlobalizationPreferences setTimeZone(TimeZone timezone) {
0496:                if (isFrozen()) {
0497:                    throw new UnsupportedOperationException(
0498:                            "Attempt to modify immutable object");
0499:                }
0500:                this .timezone = (TimeZone) timezone.clone(); // clone for safety;
0501:                return this ;
0502:            }
0503:
0504:            /**
0505:             * Get the timezone. It was either explicitly set, or is
0506:             * heuristically computed from other settings.
0507:             * 
0508:             * @return timezone, either implicitly or explicitly set
0509:             * @draft ICU 3.6
0510:             * @provisional This API might change or be removed in a future release.
0511:             */
0512:            public TimeZone getTimeZone() {
0513:                if (timezone == null) {
0514:                    return guessTimeZone();
0515:                }
0516:                return (TimeZone) timezone.clone(); // clone for safety
0517:            }
0518:
0519:            /**
0520:             * Get a copy of the collator according to the settings. 
0521:             * 
0522:             * @return collator explicit or implicit.
0523:             * @draft ICU 3.6
0524:             * @provisional This API might change or be removed in a future release.
0525:             */
0526:            public Collator getCollator() {
0527:                if (collator == null) {
0528:                    return guessCollator();
0529:                }
0530:                try {
0531:                    return (Collator) collator.clone(); // clone for safety
0532:                } catch (CloneNotSupportedException e) {
0533:                    throw new IllegalStateException("Error in cloning collator");
0534:                }
0535:            }
0536:
0537:            /**
0538:             * Explicitly set the collator for this object.
0539:             * @param collator
0540:             * @return this, for chaining
0541:             * @draft ICU 3.6
0542:             * @provisional This API might change or be removed in a future release.
0543:             */
0544:            public GlobalizationPreferences setCollator(Collator collator) {
0545:                if (isFrozen()) {
0546:                    throw new UnsupportedOperationException(
0547:                            "Attempt to modify immutable object");
0548:                }
0549:                try {
0550:                    this .collator = (Collator) collator.clone(); // clone for safety         
0551:                } catch (CloneNotSupportedException e) {
0552:                    throw new IllegalStateException("Error in cloning collator");
0553:                }
0554:                return this ;
0555:            }
0556:
0557:            /**
0558:             * Get a copy of the break iterator for the specified type according to the
0559:             * settings.
0560:             * 
0561:             * @param type
0562:             *          break type - BI_CHARACTER or BI_WORD, BI_LINE, BI_SENTENCE, BI_TITLE
0563:             * @return break iterator explicit or implicit
0564:             * @draft ICU 3.6
0565:             * @provisional This API might change or be removed in a future release.
0566:             */
0567:            public BreakIterator getBreakIterator(int type) {
0568:                if (type < BI_CHARACTER || type >= BI_LIMIT) {
0569:                    throw new IllegalArgumentException(
0570:                            "Illegal break iterator type");
0571:                }
0572:                if (breakIterators == null || breakIterators[type] == null) {
0573:                    return guessBreakIterator(type);
0574:                }
0575:                return (BreakIterator) breakIterators[type].clone(); // clone for safety
0576:            }
0577:
0578:            /**
0579:             * Explicitly set the break iterator for this object.
0580:             * 
0581:             * @param type
0582:             *          break type - BI_CHARACTER or BI_WORD, BI_LINE, BI_SENTENCE, BI_TITLE
0583:             * @param iterator a break iterator
0584:             * @return this, for chaining
0585:             * @draft ICU 3.6
0586:             * @provisional This API might change or be removed in a future release.
0587:             */
0588:            public GlobalizationPreferences setBreakIterator(int type,
0589:                    BreakIterator iterator) {
0590:                if (type < BI_CHARACTER || type >= BI_LIMIT) {
0591:                    throw new IllegalArgumentException(
0592:                            "Illegal break iterator type");
0593:                }
0594:                if (isFrozen()) {
0595:                    throw new UnsupportedOperationException(
0596:                            "Attempt to modify immutable object");
0597:                }
0598:                if (breakIterators == null)
0599:                    breakIterators = new BreakIterator[BI_LIMIT];
0600:                breakIterators[type] = (BreakIterator) iterator.clone(); // clone for safety
0601:                return this ;
0602:            }
0603:
0604:            /**
0605:             * Get the display name for an ID: language, script, territory, currency, timezone...
0606:             * Uses the language priority list to do so.
0607:             * 
0608:             * @param id language code, script code, ...
0609:             * @param type specifies the type of the ID: ID_LANGUAGE, etc.
0610:             * @return the display name
0611:             * @draft ICU 3.6
0612:             * @provisional This API might change or be removed in a future release.
0613:             */
0614:            public String getDisplayName(String id, int type) {
0615:                String result = id;
0616:                for (Iterator it = getLocales().iterator(); it.hasNext();) {
0617:                    ULocale locale = (ULocale) it.next();
0618:                    if (!isAvailableLocale(locale, TYPE_GENERIC)) {
0619:                        continue;
0620:                    }
0621:                    switch (type) {
0622:                    case ID_LOCALE:
0623:                        result = ULocale.getDisplayName(id, locale);
0624:                        break;
0625:                    case ID_LANGUAGE:
0626:                        result = ULocale.getDisplayLanguage(id, locale);
0627:                        break;
0628:                    case ID_SCRIPT:
0629:                        result = ULocale.getDisplayScript("und-" + id, locale);
0630:                        break;
0631:                    case ID_TERRITORY:
0632:                        result = ULocale.getDisplayCountry("und-" + id, locale);
0633:                        break;
0634:                    case ID_VARIANT:
0635:                        // TODO fix variant parsing
0636:                        result = ULocale.getDisplayVariant("und-QQ-" + id,
0637:                                locale);
0638:                        break;
0639:                    case ID_KEYWORD:
0640:                        result = ULocale.getDisplayKeyword(id, locale);
0641:                        break;
0642:                    case ID_KEYWORD_VALUE:
0643:                        String[] parts = new String[2];
0644:                        Utility.split(id, '=', parts);
0645:                        result = ULocale.getDisplayKeywordValue("und@" + id,
0646:                                parts[0], locale);
0647:                        // TODO fix to tell when successful
0648:                        if (result.equals(parts[1])) {
0649:                            continue;
0650:                        }
0651:                        break;
0652:                    case ID_CURRENCY_SYMBOL:
0653:                    case ID_CURRENCY:
0654:                        Currency temp = new Currency(id);
0655:                        result = temp.getName(locale,
0656:                                type == ID_CURRENCY ? Currency.LONG_NAME
0657:                                        : Currency.SYMBOL_NAME, new boolean[1]);
0658:                        // TODO: have method that doesn't take parameter. Add
0659:                        // function to determine whether string is choice
0660:                        // format.  
0661:                        // TODO: have method that doesn't require us
0662:                        // to create a currency
0663:                        break;
0664:                    case ID_TIMEZONE:
0665:                        SimpleDateFormat dtf = new SimpleDateFormat("vvvv",
0666:                                locale);
0667:                        dtf.setTimeZone(TimeZone.getTimeZone(id));
0668:                        result = dtf.format(new Date());
0669:                        // TODO, have method that doesn't require us to create a timezone
0670:                        // fix other hacks
0671:                        // hack for couldn't match
0672:                        // note, compiling with FOUNDATION omits this check for now
0673:                        //#ifndef FOUNDATION
0674:                        if (badTimeZone.reset(result).matches())
0675:                            continue;
0676:                        //#endif
0677:                        break;
0678:                    default:
0679:                        throw new IllegalArgumentException("Unknown type: "
0680:                                + type);
0681:                    }
0682:
0683:                    // TODO need better way of seeing if we fell back to root!!
0684:                    // This will not work at all for lots of stuff
0685:                    if (!id.equals(result)) {
0686:                        return result;
0687:                    }
0688:                }
0689:                return result;
0690:            }
0691:
0692:            //#ifndef FOUNDATION
0693:            // TODO remove need for this
0694:            private static final Matcher badTimeZone = Pattern.compile(
0695:                    "[A-Z]{2}|.*\\s\\([A-Z]{2}\\)").matcher("");
0696:
0697:            //#endif
0698:
0699:            /**
0700:             * Set an explicit date format. Overrides the locale priority list for
0701:             * a particular combination of dateStyle and timeStyle. DF_NONE should
0702:             * be used if for the style, where only the date or time format individually
0703:             * is being set.
0704:             * 
0705:             * @param dateStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
0706:             * @param timeStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
0707:             * @param format The date format
0708:             * @return this, for chaining
0709:             * @draft ICU 3.6
0710:             * @provisional This API might change or be removed in a future release.
0711:             */
0712:            public GlobalizationPreferences setDateFormat(int dateStyle,
0713:                    int timeStyle, DateFormat format) {
0714:                if (isFrozen()) {
0715:                    throw new UnsupportedOperationException(
0716:                            "Attempt to modify immutable object");
0717:                }
0718:                if (dateFormats == null) {
0719:                    dateFormats = new DateFormat[DF_LIMIT][DF_LIMIT];
0720:                }
0721:                dateFormats[dateStyle][timeStyle] = (DateFormat) format.clone(); // for safety
0722:                return this ;
0723:            }
0724:
0725:            /**
0726:             * Gets a date format according to the current settings. If there
0727:             * is an explicit (non-null) date/time format set, a copy of that
0728:             * is returned. Otherwise, the language priority list is used.
0729:             * DF_NONE should be used for the style, where only the date or
0730:             * time format individually is being gotten.
0731:             * 
0732:             * @param dateStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
0733:             * @param timeStyle DF_FULL, DF_LONG, DF_MEDIUM, DF_SHORT or DF_NONE
0734:             * @return a DateFormat, according to the above description
0735:             * @draft ICU 3.6
0736:             * @provisional This API might change or be removed in a future release.
0737:             */
0738:            public DateFormat getDateFormat(int dateStyle, int timeStyle) {
0739:                if (dateStyle == DF_NONE && timeStyle == DF_NONE
0740:                        || dateStyle < 0 || dateStyle >= DF_LIMIT
0741:                        || timeStyle < 0 || timeStyle >= DF_LIMIT) {
0742:                    throw new IllegalArgumentException(
0743:                            "Illegal date format style arguments");
0744:                }
0745:                DateFormat result = null;
0746:                if (dateFormats != null) {
0747:                    result = dateFormats[dateStyle][timeStyle];
0748:                }
0749:                if (result != null) {
0750:                    result = (DateFormat) result.clone(); // clone for safety
0751:                    // Not sure overriding configuration is what we really want...
0752:                    result.setTimeZone(getTimeZone());
0753:                } else {
0754:                    result = guessDateFormat(dateStyle, timeStyle);
0755:                }
0756:                return result;
0757:            }
0758:
0759:            /**
0760:             * Gets a number format according to the current settings.  If
0761:             * there is an explicit (non-null) number format set, a copy of
0762:             * that is returned.  Otherwise, the language priority list is
0763:             * used.
0764:             * 
0765:             * @param style NF_NUMBER, NF_CURRENCY, NF_PERCENT, NF_SCIENTIFIC, NF_INTEGER
0766:             * @draft ICU 3.6
0767:             * @provisional This API might change or be removed in a future release.
0768:             */
0769:            public NumberFormat getNumberFormat(int style) {
0770:                if (style < 0 || style >= NF_LIMIT) {
0771:                    throw new IllegalArgumentException(
0772:                            "Illegal number format type");
0773:                }
0774:                NumberFormat result = null;
0775:                if (numberFormats != null) {
0776:                    result = numberFormats[style];
0777:                }
0778:                if (result != null) {
0779:                    result = (NumberFormat) result.clone(); // clone for safety (later optimize)
0780:                } else {
0781:                    result = guessNumberFormat(style);
0782:                }
0783:                return result;
0784:            }
0785:
0786:            /**
0787:             * Sets a number format explicitly. Overrides the general locale settings.
0788:             * 
0789:             * @param style NF_NUMBER, NF_CURRENCY, NF_PERCENT, NF_SCIENTIFIC, NF_INTEGER
0790:             * @param format The number format
0791:             * @return this, for chaining
0792:             * @draft ICU 3.6
0793:             * @provisional This API might change or be removed in a future release.
0794:             */
0795:            public GlobalizationPreferences setNumberFormat(int style,
0796:                    NumberFormat format) {
0797:                if (isFrozen()) {
0798:                    throw new UnsupportedOperationException(
0799:                            "Attempt to modify immutable object");
0800:                }
0801:                if (numberFormats == null) {
0802:                    numberFormats = new NumberFormat[NF_LIMIT];
0803:                }
0804:                numberFormats[style] = (NumberFormat) format.clone(); // for safety
0805:                return this ;
0806:            }
0807:
0808:            /**
0809:             * Restore the object to the initial state.
0810:             * 
0811:             * @return this, for chaining
0812:             * @draft ICU 3.6
0813:             * @provisional This API might change or be removed in a future release.
0814:             */
0815:            public GlobalizationPreferences reset() {
0816:                if (isFrozen()) {
0817:                    throw new UnsupportedOperationException(
0818:                            "Attempt to modify immutable object");
0819:                }
0820:                locales = null;
0821:                territory = null;
0822:                calendar = null;
0823:                collator = null;
0824:                breakIterators = null;
0825:                timezone = null;
0826:                currency = null;
0827:                dateFormats = null;
0828:                numberFormats = null;
0829:                implicitLocales = null;
0830:                return this ;
0831:            }
0832:
0833:            /**
0834:             * Process a language/locale priority list specified via <code>setLocales</code>.
0835:             * The input locale list may be expanded or re-ordered to represent the prioritized
0836:             * language/locale order actually used by this object by the algorithm exaplained
0837:             * below.
0838:             * <br>
0839:             * <br>
0840:             * <b>Step 1</b>: Move later occurence of more specific locale before ealier occurence of less
0841:             * specific locale.
0842:             * <br>
0843:             * Before: en, fr_FR, en_US, en_GB
0844:             * <br>
0845:             * After: en_US, en_GB, en, fr_FR
0846:             * <br>
0847:             * <br>
0848:             * <b>Step 2</b>: Append a fallback locale to each locale.
0849:             * <br>
0850:             * Before: en_US, en_GB, en, fr_FR
0851:             * <br>
0852:             * After: en_US, en, en_GB, en, en, fr_FR, fr
0853:             * <br>
0854:             * <br>
0855:             * <b>Step 3</b>: Remove ealier occurence of duplicated locale entries.
0856:             * <br>
0857:             * Before: en_US, en, en_GB, en, en, fr_FR, fr
0858:             * <br>
0859:             * After: en_US, en_GB, en, fr_FR, fr
0860:             * <br> 
0861:             * <br>
0862:             * The final locale list is used to produce a default value for the appropriate territory,
0863:             * currency, timezone, etc.  The list also represents the lookup order used in
0864:             * <code>getResourceBundle</code> for this object.  A subclass may override this method
0865:             * to customize the algorithm used for populating the locale list.
0866:             * 
0867:             * @param inputLocales The list of input locales
0868:             * @draft ICU 3.6
0869:             * @provisional This API might change or be removed in a future release.
0870:             */
0871:            protected List processLocales(List inputLocales) {
0872:                List result = new ArrayList();
0873:                /*
0874:                 * Step 1: Relocate later occurence of more specific locale
0875:                 * before earlier occurence of less specific locale.
0876:                 *
0877:                 * Example:
0878:                 *   Before - en_US, fr_FR, zh, en_US_Boston, zh_TW, zh_Hant, fr_CA
0879:                 *   After  - en_US_Boston, en_US, fr_FR, zh_TW, zh_Hant, zh, fr_CA
0880:                 */
0881:                for (int i = 0; i < inputLocales.size(); i++) {
0882:                    ULocale uloc = (ULocale) inputLocales.get(i);
0883:
0884:                    String language = uloc.getLanguage();
0885:                    String script = uloc.getScript();
0886:                    String country = uloc.getCountry();
0887:                    String variant = uloc.getVariant();
0888:
0889:                    boolean bInserted = false;
0890:                    for (int j = 0; j < result.size(); j++) {
0891:                        // Check if this locale is more specific
0892:                        // than existing locale entries already inserted
0893:                        // in the destination list
0894:                        ULocale u = (ULocale) result.get(j);
0895:                        if (!u.getLanguage().equals(language)) {
0896:                            continue;
0897:                        }
0898:                        String s = u.getScript();
0899:                        String c = u.getCountry();
0900:                        String v = u.getVariant();
0901:                        if (!s.equals(script)) {
0902:                            if (s.length() == 0 && c.length() == 0
0903:                                    && v.length() == 0) {
0904:                                result.add(j, uloc);
0905:                                bInserted = true;
0906:                                break;
0907:                            } else if (s.length() == 0 && c.equals(country)) {
0908:                                // We want to see zh_Hant_HK before zh_HK
0909:                                result.add(j, uloc);
0910:                                bInserted = true;
0911:                                break;
0912:                            } else if (script.length() == 0
0913:                                    && country.length() > 0 && c.length() == 0) {
0914:                                // We want to see zh_HK before zh_Hant
0915:                                result.add(j, uloc);
0916:                                bInserted = true;
0917:                                break;
0918:                            }
0919:                            continue;
0920:                        }
0921:                        if (!c.equals(country)) {
0922:                            if (c.length() == 0 && v.length() == 0) {
0923:                                result.add(j, uloc);
0924:                                bInserted = true;
0925:                                break;
0926:                            }
0927:                        }
0928:                        if (!v.equals(variant) && v.length() == 0) {
0929:                            result.add(j, uloc);
0930:                            bInserted = true;
0931:                            break;
0932:                        }
0933:                    }
0934:                    if (!bInserted) {
0935:                        // Add this locale at the end of the list
0936:                        result.add(uloc);
0937:                    }
0938:                }
0939:
0940:                // TODO: Locale aliases might be resolved here
0941:                // For example, zh_Hant_TW = zh_TW
0942:
0943:                /*
0944:                 * Step 2: Append fallback locales for each entry
0945:                 *
0946:                 * Example:
0947:                 *   Before - en_US_Boston, en_US, fr_FR, zh_TW, zh_Hant, zh, fr_CA
0948:                 *   After  - en_US_Boston, en_US, en, en_US, en, fr_FR, fr,
0949:                 *            zh_TW, zn, zh_Hant, zh, zh, fr_CA, fr
0950:                 */
0951:                int index = 0;
0952:                while (index < result.size()) {
0953:                    ULocale uloc = (ULocale) result.get(index);
0954:                    while (true) {
0955:                        uloc = uloc.getFallback();
0956:                        if (uloc.getLanguage().length() == 0) {
0957:                            break;
0958:                        }
0959:                        index++;
0960:                        result.add(index, uloc);
0961:                    }
0962:                    index++;
0963:                }
0964:
0965:                /*
0966:                 * Step 3: Remove earlier occurence of duplicated locales
0967:                 * 
0968:                 * Example:
0969:                 *   Before - en_US_Boston, en_US, en, en_US, en, fr_FR, fr,
0970:                 *            zh_TW, zn, zh_Hant, zh, zh, fr_CA, fr
0971:                 *   After  - en_US_Boston, en_US, en, fr_FR, zh_TW, zh_Hant,
0972:                 *            zh, fr_CA, fr
0973:                 */
0974:                index = 0;
0975:                while (index < result.size() - 1) {
0976:                    ULocale uloc = (ULocale) result.get(index);
0977:                    boolean bRemoved = false;
0978:                    for (int i = index + 1; i < result.size(); i++) {
0979:                        if (uloc.equals((ULocale) result.get(i))) {
0980:                            // Remove ealier one
0981:                            result.remove(index);
0982:                            bRemoved = true;
0983:                            break;
0984:                        }
0985:                    }
0986:                    if (!bRemoved) {
0987:                        index++;
0988:                    }
0989:                }
0990:                return result;
0991:            }
0992:
0993:            /**
0994:             * This function can be overridden by subclasses to use different heuristics.
0995:             * <b>It MUST return a 'safe' value,
0996:             * one whose modification will not affect this object.</b>
0997:             * 
0998:             * @param dateStyle
0999:             * @param timeStyle
1000:             * @draft ICU 3.6
1001:             * @provisional This API might change or be removed in a future release.
1002:             */
1003:            protected DateFormat guessDateFormat(int dateStyle, int timeStyle) {
1004:                DateFormat result;
1005:                ULocale dfLocale = getAvailableLocale(TYPE_DATEFORMAT);
1006:                if (dfLocale == null) {
1007:                    dfLocale = ULocale.ROOT;
1008:                }
1009:                if (timeStyle == DF_NONE) {
1010:                    result = DateFormat.getDateInstance(getCalendar(),
1011:                            dateStyle, dfLocale);
1012:                } else if (dateStyle == DF_NONE) {
1013:                    result = DateFormat.getTimeInstance(getCalendar(),
1014:                            timeStyle, dfLocale);
1015:                } else {
1016:                    result = DateFormat.getDateTimeInstance(getCalendar(),
1017:                            dateStyle, timeStyle, dfLocale);
1018:                }
1019:                return result;
1020:            }
1021:
1022:            /**
1023:             * This function can be overridden by subclasses to use different heuristics.
1024:             * <b>It MUST return a 'safe' value,
1025:             * one whose modification will not affect this object.</b>
1026:             * 
1027:             * @param style
1028:             * @draft ICU 3.6
1029:             * @provisional This API might change or be removed in a future release.
1030:             */
1031:            protected NumberFormat guessNumberFormat(int style) {
1032:                NumberFormat result;
1033:                ULocale nfLocale = getAvailableLocale(TYPE_NUMBERFORMAT);
1034:                if (nfLocale == null) {
1035:                    nfLocale = ULocale.ROOT;
1036:                }
1037:                switch (style) {
1038:                case NF_NUMBER:
1039:                    result = NumberFormat.getInstance(nfLocale);
1040:                    break;
1041:                case NF_SCIENTIFIC:
1042:                    result = NumberFormat.getScientificInstance(nfLocale);
1043:                    break;
1044:                case NF_INTEGER:
1045:                    result = NumberFormat.getIntegerInstance(nfLocale);
1046:                    break;
1047:                case NF_PERCENT:
1048:                    result = NumberFormat.getPercentInstance(nfLocale);
1049:                    break;
1050:                case NF_CURRENCY:
1051:                    result = NumberFormat.getCurrencyInstance(nfLocale);
1052:                    result.setCurrency(getCurrency());
1053:                    break;
1054:                default:
1055:                    throw new IllegalArgumentException(
1056:                            "Unknown number format style");
1057:                }
1058:                return result;
1059:            }
1060:
1061:            /**
1062:             * This function can be overridden by subclasses to use different heuristics.
1063:             * 
1064:             * @draft ICU 3.6
1065:             * @provisional This API might change or be removed in a future release.
1066:             */
1067:            protected String guessTerritory() {
1068:                String result;
1069:                // pass through locales to see if there is a territory.
1070:                for (Iterator it = getLocales().iterator(); it.hasNext();) {
1071:                    ULocale locale = (ULocale) it.next();
1072:                    result = locale.getCountry();
1073:                    if (result.length() != 0) {
1074:                        return result;
1075:                    }
1076:                }
1077:                // if not, guess from the first language tag, or maybe from
1078:                // intersection of languages, eg nl + fr => BE
1079:                // TODO: fix using real data
1080:                // for now, just use fixed values
1081:                ULocale firstLocale = getLocale(0);
1082:                String language = firstLocale.getLanguage();
1083:                String script = firstLocale.getScript();
1084:                result = null;
1085:                if (script.length() != 0) {
1086:                    result = (String) language_territory_hack_map.get(language
1087:                            + "_" + script);
1088:                }
1089:                if (result == null) {
1090:                    result = (String) language_territory_hack_map.get(language);
1091:                }
1092:                if (result == null) {
1093:                    result = "US"; // need *some* default
1094:                }
1095:                return result;
1096:            }
1097:
1098:            /**
1099:             * This function can be overridden by subclasses to use different heuristics
1100:             * 
1101:             * @draft ICU 3.6
1102:             * @provisional This API might change or be removed in a future release.
1103:             */
1104:            protected Currency guessCurrency() {
1105:                return Currency
1106:                        .getInstance(new ULocale("und-" + getTerritory()));
1107:            }
1108:
1109:            /**
1110:             * This function can be overridden by subclasses to use different heuristics
1111:             * <b>It MUST return a 'safe' value,
1112:             * one whose modification will not affect this object.</b>
1113:             * 
1114:             * @draft ICU 3.6
1115:             * @provisional This API might change or be removed in a future release.
1116:             */
1117:            protected List guessLocales() {
1118:                if (implicitLocales == null) {
1119:                    List result = new ArrayList(1);
1120:                    result.add(ULocale.getDefault());
1121:                    implicitLocales = processLocales(result);
1122:                }
1123:                return implicitLocales;
1124:            }
1125:
1126:            /**
1127:             * This function can be overridden by subclasses to use different heuristics.
1128:             * <b>It MUST return a 'safe' value,
1129:             * one whose modification will not affect this object.</b>
1130:             * 
1131:             * @draft ICU 3.6
1132:             * @provisional This API might change or be removed in a future release.
1133:             */
1134:            protected Collator guessCollator() {
1135:                ULocale collLocale = getAvailableLocale(TYPE_COLLATOR);
1136:                if (collLocale == null) {
1137:                    collLocale = ULocale.ROOT;
1138:                }
1139:                return Collator.getInstance(collLocale);
1140:            }
1141:
1142:            /**
1143:             * This function can be overridden by subclasses to use different heuristics.
1144:             * <b>It MUST return a 'safe' value,
1145:             * one whose modification will not affect this object.</b>
1146:             * 
1147:             * @param type
1148:             * @draft ICU 3.6
1149:             * @provisional This API might change or be removed in a future release.
1150:             */
1151:            protected BreakIterator guessBreakIterator(int type) {
1152:                BreakIterator bitr = null;
1153:                ULocale brkLocale = getAvailableLocale(TYPE_BREAKITERATOR);
1154:                if (brkLocale == null) {
1155:                    brkLocale = ULocale.ROOT;
1156:                }
1157:                switch (type) {
1158:                case BI_CHARACTER:
1159:                    bitr = BreakIterator.getCharacterInstance(brkLocale);
1160:                    break;
1161:                case BI_TITLE:
1162:                    bitr = BreakIterator.getTitleInstance(brkLocale);
1163:                    break;
1164:                case BI_WORD:
1165:                    bitr = BreakIterator.getWordInstance(brkLocale);
1166:                    break;
1167:                case BI_LINE:
1168:                    bitr = BreakIterator.getLineInstance(brkLocale);
1169:                    break;
1170:                case BI_SENTENCE:
1171:                    bitr = BreakIterator.getSentenceInstance(brkLocale);
1172:                    break;
1173:                default:
1174:                    throw new IllegalArgumentException(
1175:                            "Unknown break iterator type");
1176:                }
1177:                return bitr;
1178:            }
1179:
1180:            /**
1181:             * This function can be overridden by subclasses to use different heuristics.
1182:             * <b>It MUST return a 'safe' value,
1183:             * one whose modification will not affect this object.</b>
1184:             * 
1185:             * @draft ICU 3.6
1186:             * @provisional This API might change or be removed in a future release.
1187:             */
1188:            protected TimeZone guessTimeZone() {
1189:                // TODO fix using real data
1190:                // for single-zone countries, pick that zone
1191:                // for others, pick the most populous zone
1192:                // for now, just use fixed value
1193:                // NOTE: in a few cases can do better by looking at language. 
1194:                // Eg haw+US should go to Pacific/Honolulu
1195:                // fr+CA should go to America/Montreal
1196:                String timezoneString = (String) territory_tzid_hack_map
1197:                        .get(getTerritory());
1198:                if (timezoneString == null) {
1199:                    String[] attempt = ZoneMeta.getAvailableIDs(getTerritory());
1200:                    if (attempt.length == 0) {
1201:                        timezoneString = "Etc/GMT"; // gotta do something
1202:                    } else {
1203:                        int i;
1204:                        // this all needs to be fixed to use real data. But for now, do slightly better by skipping cruft
1205:                        for (i = 0; i < attempt.length; ++i) {
1206:                            if (attempt[i].indexOf("/") >= 0)
1207:                                break;
1208:                        }
1209:                        if (i > attempt.length)
1210:                            i = 0;
1211:                        timezoneString = attempt[i];
1212:                    }
1213:                }
1214:                return TimeZone.getTimeZone(timezoneString);
1215:            }
1216:
1217:            /**
1218:             * This function can be overridden by subclasses to use different heuristics.
1219:             * <b>It MUST return a 'safe' value,
1220:             * one whose modification will not affect this object.</b>
1221:             * 
1222:             * @draft ICU 3.6
1223:             * @provisional This API might change or be removed in a future release.
1224:             */
1225:            protected Calendar guessCalendar() {
1226:                ULocale calLocale = getAvailableLocale(TYPE_CALENDAR);
1227:                if (calLocale == null) {
1228:                    calLocale = ULocale.US;
1229:                }
1230:                return Calendar.getInstance(getTimeZone(), calLocale);
1231:            }
1232:
1233:            // PRIVATES
1234:
1235:            private List locales;
1236:            private String territory;
1237:            private Currency currency;
1238:            private TimeZone timezone;
1239:            private Calendar calendar;
1240:            private Collator collator;
1241:            private BreakIterator[] breakIterators;
1242:            private DateFormat[][] dateFormats;
1243:            private NumberFormat[] numberFormats;
1244:            private List implicitLocales;
1245:
1246:            {
1247:                reset();
1248:            }
1249:
1250:            private ULocale getAvailableLocale(int type) {
1251:                List locs = getLocales();
1252:                ULocale result = null;
1253:                for (int i = 0; i < locs.size(); i++) {
1254:                    ULocale l = (ULocale) locs.get(i);
1255:                    if (isAvailableLocale(l, type)) {
1256:                        result = l;
1257:                        break;
1258:                    }
1259:                }
1260:                return result;
1261:            }
1262:
1263:            private boolean isAvailableLocale(ULocale loc, int type) {
1264:                BitSet bits = (BitSet) available_locales.get(loc);
1265:                if (bits != null && bits.get(type)) {
1266:                    return true;
1267:                }
1268:                return false;
1269:            }
1270:
1271:            /*
1272:             * Available locales for service types
1273:             */
1274:            private static final HashMap available_locales = new HashMap();
1275:            private static final int TYPE_GENERIC = 0, TYPE_CALENDAR = 1,
1276:                    TYPE_DATEFORMAT = 2, TYPE_NUMBERFORMAT = 3,
1277:                    TYPE_COLLATOR = 4, TYPE_BREAKITERATOR = 5,
1278:                    TYPE_LIMIT = TYPE_BREAKITERATOR + 1;
1279:
1280:            static {
1281:                BitSet bits;
1282:                ULocale[] allLocales = ULocale.getAvailableLocales();
1283:                for (int i = 0; i < allLocales.length; i++) {
1284:                    bits = new BitSet(TYPE_LIMIT);
1285:                    available_locales.put(allLocales[i], bits);
1286:                    bits.set(TYPE_GENERIC);
1287:                }
1288:
1289:                ULocale[] calLocales = Calendar.getAvailableULocales();
1290:                for (int i = 0; i < calLocales.length; i++) {
1291:                    bits = (BitSet) available_locales.get(calLocales[i]);
1292:                    if (bits == null) {
1293:                        bits = new BitSet(TYPE_LIMIT);
1294:                        available_locales.put(allLocales[i], bits);
1295:                    }
1296:                    bits.set(TYPE_CALENDAR);
1297:                }
1298:
1299:                ULocale[] dateLocales = DateFormat.getAvailableULocales();
1300:                for (int i = 0; i < dateLocales.length; i++) {
1301:                    bits = (BitSet) available_locales.get(dateLocales[i]);
1302:                    if (bits == null) {
1303:                        bits = new BitSet(TYPE_LIMIT);
1304:                        available_locales.put(allLocales[i], bits);
1305:                    }
1306:                    bits.set(TYPE_DATEFORMAT);
1307:                }
1308:
1309:                ULocale[] numLocales = NumberFormat.getAvailableULocales();
1310:                for (int i = 0; i < numLocales.length; i++) {
1311:                    bits = (BitSet) available_locales.get(numLocales[i]);
1312:                    if (bits == null) {
1313:                        bits = new BitSet(TYPE_LIMIT);
1314:                        available_locales.put(allLocales[i], bits);
1315:                    }
1316:                    bits.set(TYPE_NUMBERFORMAT);
1317:                }
1318:
1319:                ULocale[] collLocales = Collator.getAvailableULocales();
1320:                for (int i = 0; i < collLocales.length; i++) {
1321:                    bits = (BitSet) available_locales.get(collLocales[i]);
1322:                    if (bits == null) {
1323:                        bits = new BitSet(TYPE_LIMIT);
1324:                        available_locales.put(allLocales[i], bits);
1325:                    }
1326:                    bits.set(TYPE_COLLATOR);
1327:                }
1328:
1329:                ULocale[] brkLocales = BreakIterator.getAvailableULocales();
1330:                for (int i = 0; i < brkLocales.length; i++) {
1331:                    bits = (BitSet) available_locales.get(brkLocales[i]);
1332:                    bits.set(TYPE_BREAKITERATOR);
1333:                }
1334:            }
1335:
1336:            /** WARNING: All of this data is temporary, until we start importing from CLDR!!!
1337:             * 
1338:             */
1339:            private static final Map language_territory_hack_map = new HashMap();
1340:            private static final String[][] language_territory_hack = {
1341:                    { "af", "ZA" }, { "am", "ET" }, { "ar", "SA" },
1342:                    { "as", "IN" }, { "ay", "PE" }, { "az", "AZ" },
1343:                    { "bal", "PK" }, { "be", "BY" }, { "bg", "BG" },
1344:                    { "bn", "IN" }, { "bs", "BA" }, { "ca", "ES" },
1345:                    { "ch", "MP" }, { "cpe", "SL" }, { "cs", "CZ" },
1346:                    { "cy", "GB" }, { "da", "DK" }, { "de", "DE" },
1347:                    { "dv", "MV" }, { "dz", "BT" }, { "el", "GR" },
1348:                    { "en", "US" }, { "es", "ES" }, { "et", "EE" },
1349:                    { "eu", "ES" }, { "fa", "IR" }, { "fi", "FI" },
1350:                    { "fil", "PH" }, { "fj", "FJ" }, { "fo", "FO" },
1351:                    { "fr", "FR" }, { "ga", "IE" }, { "gd", "GB" },
1352:                    { "gl", "ES" }, { "gn", "PY" }, { "gu", "IN" },
1353:                    { "gv", "GB" }, { "ha", "NG" }, { "he", "IL" },
1354:                    { "hi", "IN" }, { "ho", "PG" }, { "hr", "HR" },
1355:                    { "ht", "HT" }, { "hu", "HU" }, { "hy", "AM" },
1356:                    { "id", "ID" }, { "is", "IS" }, { "it", "IT" },
1357:                    { "ja", "JP" }, { "ka", "GE" }, { "kk", "KZ" },
1358:                    { "kl", "GL" }, { "km", "KH" }, { "kn", "IN" },
1359:                    { "ko", "KR" }, { "kok", "IN" }, { "ks", "IN" },
1360:                    { "ku", "TR" }, { "ky", "KG" }, { "la", "VA" },
1361:                    { "lb", "LU" }, { "ln", "CG" }, { "lo", "LA" },
1362:                    { "lt", "LT" }, { "lv", "LV" }, { "mai", "IN" },
1363:                    { "men", "GN" }, { "mg", "MG" }, { "mh", "MH" },
1364:                    { "mk", "MK" }, { "ml", "IN" }, { "mn", "MN" },
1365:                    { "mni", "IN" }, { "mo", "MD" }, { "mr", "IN" },
1366:                    { "ms", "MY" }, { "mt", "MT" }, { "my", "MM" },
1367:                    { "na", "NR" }, { "nb", "NO" }, { "nd", "ZA" },
1368:                    { "ne", "NP" }, { "niu", "NU" }, { "nl", "NL" },
1369:                    { "nn", "NO" }, { "no", "NO" }, { "nr", "ZA" },
1370:                    { "nso", "ZA" }, { "ny", "MW" }, { "om", "KE" },
1371:                    { "or", "IN" }, { "pa", "IN" }, { "pau", "PW" },
1372:                    { "pl", "PL" }, { "ps", "PK" }, { "pt", "BR" },
1373:                    { "qu", "PE" }, { "rn", "BI" }, { "ro", "RO" },
1374:                    { "ru", "RU" }, { "rw", "RW" }, { "sd", "IN" },
1375:                    { "sg", "CF" }, { "si", "LK" }, { "sk", "SK" },
1376:                    { "sl", "SI" }, { "sm", "WS" }, { "so", "DJ" },
1377:                    { "sq", "CS" }, { "sr", "CS" }, { "ss", "ZA" },
1378:                    { "st", "ZA" }, { "sv", "SE" }, { "sw", "KE" },
1379:                    { "ta", "IN" }, { "te", "IN" }, { "tem", "SL" },
1380:                    { "tet", "TL" }, { "th", "TH" }, { "ti", "ET" },
1381:                    { "tg", "TJ" }, { "tk", "TM" }, { "tkl", "TK" },
1382:                    { "tvl", "TV" }, { "tl", "PH" }, { "tn", "ZA" },
1383:                    { "to", "TO" }, { "tpi", "PG" }, { "tr", "TR" },
1384:                    { "ts", "ZA" }, { "uk", "UA" }, { "ur", "IN" },
1385:                    { "uz", "UZ" }, { "ve", "ZA" }, { "vi", "VN" },
1386:                    { "wo", "SN" }, { "xh", "ZA" }, { "zh", "CN" },
1387:                    { "zh_Hant", "TW" }, { "zu", "ZA" }, { "aa", "ET" },
1388:                    { "byn", "ER" }, { "eo", "DE" }, { "gez", "ET" },
1389:                    { "haw", "US" }, { "iu", "CA" }, { "kw", "GB" },
1390:                    { "sa", "IN" }, { "sh", "HR" }, { "sid", "ET" },
1391:                    { "syr", "SY" }, { "tig", "ER" }, { "tt", "RU" },
1392:                    { "wal", "ET" }, };
1393:            static {
1394:                for (int i = 0; i < language_territory_hack.length; ++i) {
1395:                    language_territory_hack_map.put(
1396:                            language_territory_hack[i][0],
1397:                            language_territory_hack[i][1]);
1398:                }
1399:            }
1400:
1401:            static final Map territory_tzid_hack_map = new HashMap();
1402:            static final String[][] territory_tzid_hack = {
1403:                    { "AQ", "Antarctica/McMurdo" },
1404:                    { "AR", "America/Buenos_Aires" },
1405:                    { "AU", "Australia/Sydney" },
1406:                    { "BR", "America/Sao_Paulo" }, { "CA", "America/Toronto" },
1407:                    { "CD", "Africa/Kinshasa" }, { "CL", "America/Santiago" },
1408:                    { "CN", "Asia/Shanghai" }, { "EC", "America/Guayaquil" },
1409:                    { "ES", "Europe/Madrid" }, { "GB", "Europe/London" },
1410:                    { "GL", "America/Godthab" }, { "ID", "Asia/Jakarta" },
1411:                    { "ML", "Africa/Bamako" }, { "MX", "America/Mexico_City" },
1412:                    { "MY", "Asia/Kuala_Lumpur" },
1413:                    { "NZ", "Pacific/Auckland" }, { "PT", "Europe/Lisbon" },
1414:                    { "RU", "Europe/Moscow" }, { "UA", "Europe/Kiev" },
1415:                    { "US", "America/New_York" }, { "UZ", "Asia/Tashkent" },
1416:                    { "PF", "Pacific/Tahiti" }, { "FM", "Pacific/Kosrae" },
1417:                    { "KI", "Pacific/Tarawa" }, { "KZ", "Asia/Almaty" },
1418:                    { "MH", "Pacific/Majuro" }, { "MN", "Asia/Ulaanbaatar" },
1419:                    { "SJ", "Arctic/Longyearbyen" },
1420:                    { "UM", "Pacific/Midway" }, };
1421:            static {
1422:                for (int i = 0; i < territory_tzid_hack.length; ++i) {
1423:                    territory_tzid_hack_map.put(territory_tzid_hack[i][0],
1424:                            territory_tzid_hack[i][1]);
1425:                }
1426:            }
1427:
1428:            // Freezable implmentation
1429:
1430:            private boolean frozen;
1431:
1432:            /**
1433:             * @draft ICU 3.6
1434:             * @provisional This API might change or be removed in a future release.
1435:             */
1436:            public boolean isFrozen() {
1437:                return frozen;
1438:            }
1439:
1440:            /**
1441:             * @draft ICU 3.6
1442:             * @provisional This API might change or be removed in a future release.
1443:             */
1444:            public Object freeze() {
1445:                frozen = true;
1446:                return this ;
1447:            }
1448:
1449:            /**
1450:             * @draft ICU 3.6
1451:             * @provisional This API might change or be removed in a future release.
1452:             */
1453:            public Object cloneAsThawed() {
1454:                try {
1455:                    GlobalizationPreferences result = (GlobalizationPreferences) clone();
1456:                    result.frozen = false;
1457:                    return result;
1458:                } catch (CloneNotSupportedException e) {
1459:                    // will always work
1460:                    return null;
1461:                }
1462:            }
1463:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.