jdk/src/share/classes/java/util/Locale.java
changeset 9224 75c0420badef
parent 8780 c88e159a3e5c
child 9232 9e29d6359705
equal deleted inserted replaced
9223:d331b7996fc3 9224:75c0420badef
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    49 import java.text.MessageFormat;
    49 import java.text.MessageFormat;
    50 import java.util.spi.LocaleNameProvider;
    50 import java.util.spi.LocaleNameProvider;
    51 
    51 
    52 import sun.security.action.GetPropertyAction;
    52 import sun.security.action.GetPropertyAction;
    53 import sun.util.LocaleServiceProviderPool;
    53 import sun.util.LocaleServiceProviderPool;
    54 import sun.util.locale.AsciiUtil;
       
    55 import sun.util.locale.BaseLocale;
    54 import sun.util.locale.BaseLocale;
    56 import sun.util.locale.InternalLocaleBuilder;
    55 import sun.util.locale.InternalLocaleBuilder;
    57 import sun.util.locale.LanguageTag;
    56 import sun.util.locale.LanguageTag;
    58 import sun.util.locale.LocaleExtensions;
    57 import sun.util.locale.LocaleExtensions;
    59 import sun.util.locale.LocaleObjectCache;
    58 import sun.util.locale.LocaleObjectCache;
    60 import sun.util.locale.LocaleSyntaxException;
    59 import sun.util.locale.LocaleSyntaxException;
       
    60 import sun.util.locale.LocaleUtils;
    61 import sun.util.locale.ParseStatus;
    61 import sun.util.locale.ParseStatus;
    62 import sun.util.locale.UnicodeLocaleExtension;
    62 import sun.util.locale.UnicodeLocaleExtension;
    63 import sun.util.resources.LocaleData;
    63 import sun.util.resources.LocaleData;
    64 import sun.util.resources.OpenListResourceBundle;
    64 import sun.util.resources.OpenListResourceBundle;
    65 
    65 
   410 
   410 
   411     static private final  Cache LOCALECACHE = new Cache();
   411     static private final  Cache LOCALECACHE = new Cache();
   412 
   412 
   413     /** Useful constant for language.
   413     /** Useful constant for language.
   414      */
   414      */
   415     static public final Locale ENGLISH = getInstance("en", "", "");
   415     static public final Locale ENGLISH = createConstant("en", "");
   416 
   416 
   417     /** Useful constant for language.
   417     /** Useful constant for language.
   418      */
   418      */
   419     static public final Locale FRENCH = getInstance("fr", "", "");
   419     static public final Locale FRENCH = createConstant("fr", "");
   420 
   420 
   421     /** Useful constant for language.
   421     /** Useful constant for language.
   422      */
   422      */
   423     static public final Locale GERMAN = getInstance("de", "", "");
   423     static public final Locale GERMAN = createConstant("de", "");
   424 
   424 
   425     /** Useful constant for language.
   425     /** Useful constant for language.
   426      */
   426      */
   427     static public final Locale ITALIAN = getInstance("it", "", "");
   427     static public final Locale ITALIAN = createConstant("it", "");
   428 
   428 
   429     /** Useful constant for language.
   429     /** Useful constant for language.
   430      */
   430      */
   431     static public final Locale JAPANESE = getInstance("ja", "", "");
   431     static public final Locale JAPANESE = createConstant("ja", "");
   432 
   432 
   433     /** Useful constant for language.
   433     /** Useful constant for language.
   434      */
   434      */
   435     static public final Locale KOREAN = getInstance("ko", "", "");
   435     static public final Locale KOREAN = createConstant("ko", "");
   436 
   436 
   437     /** Useful constant for language.
   437     /** Useful constant for language.
   438      */
   438      */
   439     static public final Locale CHINESE = getInstance("zh", "", "");
   439     static public final Locale CHINESE = createConstant("zh", "");
   440 
   440 
   441     /** Useful constant for language.
   441     /** Useful constant for language.
   442      */
   442      */
   443     static public final Locale SIMPLIFIED_CHINESE = getInstance("zh", "CN", "");
   443     static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
   444 
   444 
   445     /** Useful constant for language.
   445     /** Useful constant for language.
   446      */
   446      */
   447     static public final Locale TRADITIONAL_CHINESE = getInstance("zh", "TW", "");
   447     static public final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
   448 
   448 
   449     /** Useful constant for country.
   449     /** Useful constant for country.
   450      */
   450      */
   451     static public final Locale FRANCE = getInstance("fr", "FR", "");
   451     static public final Locale FRANCE = createConstant("fr", "FR");
   452 
   452 
   453     /** Useful constant for country.
   453     /** Useful constant for country.
   454      */
   454      */
   455     static public final Locale GERMANY = getInstance("de", "DE", "");
   455     static public final Locale GERMANY = createConstant("de", "DE");
   456 
   456 
   457     /** Useful constant for country.
   457     /** Useful constant for country.
   458      */
   458      */
   459     static public final Locale ITALY = getInstance("it", "IT", "");
   459     static public final Locale ITALY = createConstant("it", "IT");
   460 
   460 
   461     /** Useful constant for country.
   461     /** Useful constant for country.
   462      */
   462      */
   463     static public final Locale JAPAN = getInstance("ja", "JP", "");
   463     static public final Locale JAPAN = createConstant("ja", "JP");
   464 
   464 
   465     /** Useful constant for country.
   465     /** Useful constant for country.
   466      */
   466      */
   467     static public final Locale KOREA = getInstance("ko", "KR", "");
   467     static public final Locale KOREA = createConstant("ko", "KR");
   468 
   468 
   469     /** Useful constant for country.
   469     /** Useful constant for country.
   470      */
   470      */
   471     static public final Locale CHINA = SIMPLIFIED_CHINESE;
   471     static public final Locale CHINA = SIMPLIFIED_CHINESE;
   472 
   472 
   478      */
   478      */
   479     static public final Locale TAIWAN = TRADITIONAL_CHINESE;
   479     static public final Locale TAIWAN = TRADITIONAL_CHINESE;
   480 
   480 
   481     /** Useful constant for country.
   481     /** Useful constant for country.
   482      */
   482      */
   483     static public final Locale UK = getInstance("en", "GB", "");
   483     static public final Locale UK = createConstant("en", "GB");
   484 
   484 
   485     /** Useful constant for country.
   485     /** Useful constant for country.
   486      */
   486      */
   487     static public final Locale US = getInstance("en", "US", "");
   487     static public final Locale US = createConstant("en", "US");
   488 
   488 
   489     /** Useful constant for country.
   489     /** Useful constant for country.
   490      */
   490      */
   491     static public final Locale CANADA = getInstance("en", "CA", "");
   491     static public final Locale CANADA = createConstant("en", "CA");
   492 
   492 
   493     /** Useful constant for country.
   493     /** Useful constant for country.
   494      */
   494      */
   495     static public final Locale CANADA_FRENCH = getInstance("fr", "CA", "");
   495     static public final Locale CANADA_FRENCH = createConstant("fr", "CA");
   496 
   496 
   497     /**
   497     /**
   498      * Useful constant for the root locale.  The root locale is the locale whose
   498      * Useful constant for the root locale.  The root locale is the locale whose
   499      * language, country, and variant are empty ("") strings.  This is regarded
   499      * language, country, and variant are empty ("") strings.  This is regarded
   500      * as the base locale of all locales, and is used as the language/country
   500      * as the base locale of all locales, and is used as the language/country
   501      * neutral locale for the locale sensitive operations.
   501      * neutral locale for the locale sensitive operations.
   502      *
   502      *
   503      * @since 1.6
   503      * @since 1.6
   504      */
   504      */
   505     static public final Locale ROOT = getInstance("", "", "");
   505     static public final Locale ROOT = createConstant("", "");
   506 
   506 
   507     /**
   507     /**
   508      * The key for the private use extension ('x').
   508      * The key for the private use extension ('x').
   509      *
   509      *
   510      * @see #getExtension(char)
   510      * @see #getExtension(char)
   530      * Display types for retrieving localized names from the name providers.
   530      * Display types for retrieving localized names from the name providers.
   531      */
   531      */
   532     private static final int DISPLAY_LANGUAGE = 0;
   532     private static final int DISPLAY_LANGUAGE = 0;
   533     private static final int DISPLAY_COUNTRY  = 1;
   533     private static final int DISPLAY_COUNTRY  = 1;
   534     private static final int DISPLAY_VARIANT  = 2;
   534     private static final int DISPLAY_VARIANT  = 2;
   535     private static final int DISPLAY_SCRIPT = 3;
   535     private static final int DISPLAY_SCRIPT   = 3;
   536 
   536 
   537     /**
   537     /**
   538      * Private constructor used by getInstance method
   538      * Private constructor used by getInstance method
   539      */
   539      */
   540     private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
   540     private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
   541         _baseLocale = baseLocale;
   541         this.baseLocale = baseLocale;
   542         _extensions = extensions;
   542         this.localeExtensions = extensions;
   543     }
   543     }
   544 
   544 
   545     /**
   545     /**
   546      * Construct a locale from language, country and variant.
   546      * Construct a locale from language, country and variant.
   547      * This constructor normalizes the language value to lowercase and
   547      * This constructor normalizes the language value to lowercase and
   570      */
   570      */
   571     public Locale(String language, String country, String variant) {
   571     public Locale(String language, String country, String variant) {
   572         if (language== null || country == null || variant == null) {
   572         if (language== null || country == null || variant == null) {
   573             throw new NullPointerException();
   573             throw new NullPointerException();
   574         }
   574         }
   575         _baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
   575         baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
   576         _extensions = getCompatibilityExtensions(language, "", country, variant);
   576         localeExtensions = getCompatibilityExtensions(language, "", country, variant);
   577     }
   577     }
   578 
   578 
   579     /**
   579     /**
   580      * Construct a locale from language and country.
   580      * Construct a locale from language and country.
   581      * This constructor normalizes the language value to lowercase and
   581      * This constructor normalizes the language value to lowercase and
   625     public Locale(String language) {
   625     public Locale(String language) {
   626         this(language, "", "");
   626         this(language, "", "");
   627     }
   627     }
   628 
   628 
   629     /**
   629     /**
       
   630      * This method must be called only for creating the Locale.*
       
   631      * constants due to making shortcuts.
       
   632      */
       
   633     private static Locale createConstant(String lang, String country) {
       
   634         BaseLocale base = BaseLocale.createInstance(lang, country);
       
   635         return getInstance(base, null);
       
   636     }
       
   637 
       
   638     /**
   630      * Returns a <code>Locale</code> constructed from the given
   639      * Returns a <code>Locale</code> constructed from the given
   631      * <code>language</code>, <code>country</code> and
   640      * <code>language</code>, <code>country</code> and
   632      * <code>variant</code>. If the same <code>Locale</code> instance
   641      * <code>variant</code>. If the same <code>Locale</code> instance
   633      * is available in the cache, then that instance is
   642      * is available in the cache, then that instance is
   634      * returned. Otherwise, a new <code>Locale</code> instance is
   643      * returned. Otherwise, a new <code>Locale</code> instance is
   639      * @param variant vendor and browser specific code. See class description.
   648      * @param variant vendor and browser specific code. See class description.
   640      * @return the <code>Locale</code> instance requested
   649      * @return the <code>Locale</code> instance requested
   641      * @exception NullPointerException if any argument is null.
   650      * @exception NullPointerException if any argument is null.
   642      */
   651      */
   643     static Locale getInstance(String language, String country, String variant) {
   652     static Locale getInstance(String language, String country, String variant) {
   644         return getInstance(language, "", country, variant, LocaleExtensions.EMPTY_EXTENSIONS);
   653         return getInstance(language, "", country, variant, null);
   645     }
   654     }
   646 
   655 
   647     static Locale getInstance(String language, String script, String country,
   656     static Locale getInstance(String language, String script, String country,
   648                                       String variant, LocaleExtensions extensions) {
   657                                       String variant, LocaleExtensions extensions) {
   649         if (language== null || script == null || country == null || variant == null) {
   658         if (language== null || script == null || country == null || variant == null) {
   650             throw new NullPointerException();
   659             throw new NullPointerException();
   651         }
   660         }
   652 
   661 
   653         if (extensions == null) {
   662         if (extensions == null) {
   654             extensions = LocaleExtensions.EMPTY_EXTENSIONS;
       
   655         }
       
   656 
       
   657         if (extensions.equals(LocaleExtensions.EMPTY_EXTENSIONS)) {
       
   658             extensions = getCompatibilityExtensions(language, script, country, variant);
   663             extensions = getCompatibilityExtensions(language, script, country, variant);
   659         }
   664         }
   660 
   665 
   661         BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
   666         BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
   662         return getInstance(baseloc, extensions);
   667         return getInstance(baseloc, extensions);
   666         LocaleKey key = new LocaleKey(baseloc, extensions);
   671         LocaleKey key = new LocaleKey(baseloc, extensions);
   667         return LOCALECACHE.get(key);
   672         return LOCALECACHE.get(key);
   668     }
   673     }
   669 
   674 
   670     private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
   675     private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
   671         public Cache() {
   676         private Cache() {
   672         }
   677         }
       
   678 
       
   679         @Override
   673         protected Locale createObject(LocaleKey key) {
   680         protected Locale createObject(LocaleKey key) {
   674             return new Locale(key._base, key._exts);
   681             return new Locale(key.base, key.exts);
   675         }
   682         }
   676     }
   683     }
   677 
   684 
   678     private static class LocaleKey {
   685     private static final class LocaleKey {
   679         private BaseLocale _base;
   686         private final BaseLocale base;
   680         private LocaleExtensions _exts;
   687         private final LocaleExtensions exts;
       
   688         private final int hash;
   681 
   689 
   682         private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) {
   690         private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) {
   683             _base = baseLocale;
   691             base = baseLocale;
   684             _exts = extensions;
   692             exts = extensions;
   685         }
   693 
   686 
   694             // Calculate the hash value here because it's always used.
       
   695             int h = base.hashCode();
       
   696             if (exts != null) {
       
   697                 h ^= exts.hashCode();
       
   698             }
       
   699             hash = h;
       
   700         }
       
   701 
       
   702         @Override
   687         public boolean equals(Object obj) {
   703         public boolean equals(Object obj) {
   688             if (this == obj) {
   704             if (this == obj) {
   689                 return true;
   705                 return true;
   690             }
   706             }
   691             if (!(obj instanceof LocaleKey)) {
   707             if (!(obj instanceof LocaleKey)) {
   692                 return false;
   708                 return false;
   693             }
   709             }
   694             LocaleKey other = (LocaleKey)obj;
   710             LocaleKey other = (LocaleKey)obj;
   695             return _base.equals(other._base) && _exts.equals(other._exts);
   711             if (hash != other.hash || !base.equals(other.base)) {
   696         }
   712                 return false;
   697 
   713             }
       
   714             if (exts == null) {
       
   715                 return other.exts == null;
       
   716             }
       
   717             return exts.equals(other.exts);
       
   718         }
       
   719 
       
   720         @Override
   698         public int hashCode() {
   721         public int hashCode() {
   699             return _base.hashCode() ^ _exts.hashCode();
   722             return hash;
   700         }
   723         }
   701     }
   724     }
   702 
   725 
   703     /**
   726     /**
   704      * Gets the current value of the default locale for this instance
   727      * Gets the current value of the default locale for this instance
   979      * </pre>
  1002      * </pre>
   980      * @return The language code, or the empty string if none is defined.
  1003      * @return The language code, or the empty string if none is defined.
   981      * @see #getDisplayLanguage
  1004      * @see #getDisplayLanguage
   982      */
  1005      */
   983     public String getLanguage() {
  1006     public String getLanguage() {
   984         return _baseLocale.getLanguage();
  1007         return baseLocale.getLanguage();
   985     }
  1008     }
   986 
  1009 
   987     /**
  1010     /**
   988      * Returns the script for this locale, which should
  1011      * Returns the script for this locale, which should
   989      * either be the empty string or an ISO 15924 4-letter script
  1012      * either be the empty string or an ISO 15924 4-letter script
   993      * @return The script code, or the empty string if none is defined.
  1016      * @return The script code, or the empty string if none is defined.
   994      * @see #getDisplayScript
  1017      * @see #getDisplayScript
   995      * @since 1.7
  1018      * @since 1.7
   996      */
  1019      */
   997     public String getScript() {
  1020     public String getScript() {
   998         return _baseLocale.getScript();
  1021         return baseLocale.getScript();
   999     }
  1022     }
  1000 
  1023 
  1001     /**
  1024     /**
  1002      * Returns the country/region code for this locale, which should
  1025      * Returns the country/region code for this locale, which should
  1003      * either be the empty string, an uppercase ISO 3166 2-letter code,
  1026      * either be the empty string, an uppercase ISO 3166 2-letter code,
  1005      *
  1028      *
  1006      * @return The country/region code, or the empty string if none is defined.
  1029      * @return The country/region code, or the empty string if none is defined.
  1007      * @see #getDisplayCountry
  1030      * @see #getDisplayCountry
  1008      */
  1031      */
  1009     public String getCountry() {
  1032     public String getCountry() {
  1010         return _baseLocale.getRegion();
  1033         return baseLocale.getRegion();
  1011     }
  1034     }
  1012 
  1035 
  1013     /**
  1036     /**
  1014      * Returns the variant code for this locale.
  1037      * Returns the variant code for this locale.
  1015      *
  1038      *
  1016      * @return The variant code, or the empty string if none is defined.
  1039      * @return The variant code, or the empty string if none is defined.
  1017      * @see #getDisplayVariant
  1040      * @see #getDisplayVariant
  1018      */
  1041      */
  1019     public String getVariant() {
  1042     public String getVariant() {
  1020         return _baseLocale.getVariant();
  1043         return baseLocale.getVariant();
  1021     }
  1044     }
  1022 
  1045 
  1023     /**
  1046     /**
  1024      * Returns the extension (or private use) value associated with
  1047      * Returns the extension (or private use) value associated with
  1025      * the specified key, or null if there is no extension
  1048      * the specified key, or null if there is no extension
  1037      */
  1060      */
  1038     public String getExtension(char key) {
  1061     public String getExtension(char key) {
  1039         if (!LocaleExtensions.isValidKey(key)) {
  1062         if (!LocaleExtensions.isValidKey(key)) {
  1040             throw new IllegalArgumentException("Ill-formed extension key: " + key);
  1063             throw new IllegalArgumentException("Ill-formed extension key: " + key);
  1041         }
  1064         }
  1042         return _extensions.getExtensionValue(key);
  1065         return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key);
  1043     }
  1066     }
  1044 
  1067 
  1045     /**
  1068     /**
  1046      * Returns the set of extension keys associated with this locale, or the
  1069      * Returns the set of extension keys associated with this locale, or the
  1047      * empty set if it has no extensions. The returned set is unmodifiable.
  1070      * empty set if it has no extensions. The returned set is unmodifiable.
  1050      * @return The set of extension keys, or the empty set if this locale has
  1073      * @return The set of extension keys, or the empty set if this locale has
  1051      * no extensions.
  1074      * no extensions.
  1052      * @since 1.7
  1075      * @since 1.7
  1053      */
  1076      */
  1054     public Set<Character> getExtensionKeys() {
  1077     public Set<Character> getExtensionKeys() {
  1055         return _extensions.getKeys();
  1078         if (localeExtensions == null) {
       
  1079             return Collections.emptySet();
       
  1080         }
       
  1081         return localeExtensions.getKeys();
  1056     }
  1082     }
  1057 
  1083 
  1058     /**
  1084     /**
  1059      * Returns the set of unicode locale attributes associated with
  1085      * Returns the set of unicode locale attributes associated with
  1060      * this locale, or the empty set if it has no attributes. The
  1086      * this locale, or the empty set if it has no attributes. The
  1062      *
  1088      *
  1063      * @return The set of attributes.
  1089      * @return The set of attributes.
  1064      * @since 1.7
  1090      * @since 1.7
  1065      */
  1091      */
  1066     public Set<String> getUnicodeLocaleAttributes() {
  1092     public Set<String> getUnicodeLocaleAttributes() {
  1067         return _extensions.getUnicodeLocaleAttributes();
  1093         if (localeExtensions == null) {
       
  1094             return Collections.emptySet();
       
  1095         }
       
  1096         return localeExtensions.getUnicodeLocaleAttributes();
  1068     }
  1097     }
  1069 
  1098 
  1070     /**
  1099     /**
  1071      * Returns the Unicode locale type associated with the specified Unicode locale key
  1100      * Returns the Unicode locale type associated with the specified Unicode locale key
  1072      * for this locale. Returns the empty string for keys that are defined with no type.
  1101      * for this locale. Returns the empty string for keys that are defined with no type.
  1083      */
  1112      */
  1084     public String getUnicodeLocaleType(String key) {
  1113     public String getUnicodeLocaleType(String key) {
  1085         if (!UnicodeLocaleExtension.isKey(key)) {
  1114         if (!UnicodeLocaleExtension.isKey(key)) {
  1086             throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
  1115             throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
  1087         }
  1116         }
  1088         return _extensions.getUnicodeLocaleType(key);
  1117         return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key);
  1089     }
  1118     }
  1090 
  1119 
  1091     /**
  1120     /**
  1092      * Returns the set of Unicode locale keys defined by this locale, or the empty set if
  1121      * Returns the set of Unicode locale keys defined by this locale, or the empty set if
  1093      * this locale has none.  The returned set is immutable.  Keys are all lower case.
  1122      * this locale has none.  The returned set is immutable.  Keys are all lower case.
  1095      * @return The set of Unicode locale keys, or the empty set if this locale has
  1124      * @return The set of Unicode locale keys, or the empty set if this locale has
  1096      * no Unicode locale keywords.
  1125      * no Unicode locale keywords.
  1097      * @since 1.7
  1126      * @since 1.7
  1098      */
  1127      */
  1099     public Set<String> getUnicodeLocaleKeys() {
  1128     public Set<String> getUnicodeLocaleKeys() {
  1100         return _extensions.getUnicodeLocaleKeys();
  1129         if (localeExtensions == null) {
       
  1130             return Collections.emptySet();
       
  1131         }
       
  1132         return localeExtensions.getUnicodeLocaleKeys();
  1101     }
  1133     }
  1102 
  1134 
  1103     /**
  1135     /**
  1104      * Package locale method returning the Locale's BaseLocale,
  1136      * Package locale method returning the Locale's BaseLocale,
  1105      * used by ResourceBundle
  1137      * used by ResourceBundle
  1106      * @return base locale of this Locale
  1138      * @return base locale of this Locale
  1107      */
  1139      */
  1108     BaseLocale getBaseLocale() {
  1140     BaseLocale getBaseLocale() {
  1109         return _baseLocale;
  1141         return baseLocale;
  1110     }
  1142     }
  1111 
  1143 
  1112     /**
  1144     /**
  1113      * Package local method returning the Locale's LocaleExtensions,
  1145      * Package private method returning the Locale's LocaleExtensions,
  1114      * used by ResourceBundle
  1146      * used by ResourceBundle.
  1115      * @return locale exnteions of this Locale
  1147      * @return locale exnteions of this Locale,
       
  1148      *         or {@code null} if no extensions are defined
  1116      */
  1149      */
  1117      LocaleExtensions getLocaleExtensions() {
  1150      LocaleExtensions getLocaleExtensions() {
  1118          return _extensions;
  1151          return localeExtensions;
  1119      }
  1152      }
  1120 
  1153 
  1121     /**
  1154     /**
  1122      * Returns a string representation of this <code>Locale</code>
  1155      * Returns a string representation of this <code>Locale</code>
  1123      * object, consisting of language, country, variant, script,
  1156      * object, consisting of language, country, variant, script,
  1158      *
  1191      *
  1159      * @return A string representation of the Locale, for debugging.
  1192      * @return A string representation of the Locale, for debugging.
  1160      * @see #getDisplayName
  1193      * @see #getDisplayName
  1161      * @see #toLanguageTag
  1194      * @see #toLanguageTag
  1162      */
  1195      */
       
  1196     @Override
  1163     public final String toString() {
  1197     public final String toString() {
  1164         boolean l = (_baseLocale.getLanguage().length() != 0);
  1198         boolean l = (baseLocale.getLanguage().length() != 0);
  1165         boolean s = (_baseLocale.getScript().length() != 0);
  1199         boolean s = (baseLocale.getScript().length() != 0);
  1166         boolean r = (_baseLocale.getRegion().length() != 0);
  1200         boolean r = (baseLocale.getRegion().length() != 0);
  1167         boolean v = (_baseLocale.getVariant().length() != 0);
  1201         boolean v = (baseLocale.getVariant().length() != 0);
  1168         boolean e = (_extensions.getID().length() != 0);
  1202         boolean e = (localeExtensions != null && localeExtensions.getID().length() != 0);
  1169 
  1203 
  1170         StringBuilder result = new StringBuilder(_baseLocale.getLanguage());
  1204         StringBuilder result = new StringBuilder(baseLocale.getLanguage());
  1171         if (r || (l && (v || s || e))) {
  1205         if (r || (l && (v || s || e))) {
  1172             result.append('_')
  1206             result.append('_')
  1173                 .append(_baseLocale.getRegion()); // This may just append '_'
  1207                 .append(baseLocale.getRegion()); // This may just append '_'
  1174         }
  1208         }
  1175         if (v && (l || r)) {
  1209         if (v && (l || r)) {
  1176             result.append('_')
  1210             result.append('_')
  1177                 .append(_baseLocale.getVariant());
  1211                 .append(baseLocale.getVariant());
  1178         }
  1212         }
  1179 
  1213 
  1180         if (s && (l || r)) {
  1214         if (s && (l || r)) {
  1181             result.append("_#")
  1215             result.append("_#")
  1182                 .append(_baseLocale.getScript());
  1216                 .append(baseLocale.getScript());
  1183         }
  1217         }
  1184 
  1218 
  1185         if (e && (l || r)) {
  1219         if (e && (l || r)) {
  1186             result.append('_');
  1220             result.append('_');
  1187             if (!s) {
  1221             if (!s) {
  1188                 result.append('#');
  1222                 result.append('#');
  1189             }
  1223             }
  1190             result.append(_extensions.getID());
  1224             result.append(localeExtensions.getID());
  1191         }
  1225         }
  1192 
  1226 
  1193         return result.toString();
  1227         return result.toString();
  1194     }
  1228     }
  1195 
  1229 
  1259      * @return a BCP47 language tag representing the locale
  1293      * @return a BCP47 language tag representing the locale
  1260      * @see #forLanguageTag(String)
  1294      * @see #forLanguageTag(String)
  1261      * @since 1.7
  1295      * @since 1.7
  1262      */
  1296      */
  1263     public String toLanguageTag() {
  1297     public String toLanguageTag() {
  1264         LanguageTag tag = LanguageTag.parseLocale(_baseLocale, _extensions);
  1298         LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
  1265         StringBuilder buf = new StringBuilder();
  1299         StringBuilder buf = new StringBuilder();
  1266 
  1300 
  1267         String subtag = tag.getLanguage();
  1301         String subtag = tag.getLanguage();
  1268         if (subtag.length() > 0) {
  1302         if (subtag.length() > 0) {
  1269             buf.append(LanguageTag.canonicalizeLanguage(subtag));
  1303             buf.append(LanguageTag.canonicalizeLanguage(subtag));
  1431         LanguageTag tag = LanguageTag.parse(languageTag, null);
  1465         LanguageTag tag = LanguageTag.parse(languageTag, null);
  1432         InternalLocaleBuilder bldr = new InternalLocaleBuilder();
  1466         InternalLocaleBuilder bldr = new InternalLocaleBuilder();
  1433         bldr.setLanguageTag(tag);
  1467         bldr.setLanguageTag(tag);
  1434         BaseLocale base = bldr.getBaseLocale();
  1468         BaseLocale base = bldr.getBaseLocale();
  1435         LocaleExtensions exts = bldr.getLocaleExtensions();
  1469         LocaleExtensions exts = bldr.getLocaleExtensions();
  1436         if (exts.isEmpty() && base.getVariant().length() > 0) {
  1470         if (exts == null && base.getVariant().length() > 0) {
  1437             exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(), base.getRegion(), base.getVariant());
  1471             exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(),
       
  1472                                               base.getRegion(), base.getVariant());
  1438         }
  1473         }
  1439         return getInstance(base, exts);
  1474         return getInstance(base, exts);
  1440     }
  1475     }
  1441 
  1476 
  1442     /**
  1477     /**
  1452      * @return A three-letter abbreviation of this locale's language.
  1487      * @return A three-letter abbreviation of this locale's language.
  1453      * @exception MissingResourceException Throws MissingResourceException if
  1488      * @exception MissingResourceException Throws MissingResourceException if
  1454      * three-letter language abbreviation is not available for this locale.
  1489      * three-letter language abbreviation is not available for this locale.
  1455      */
  1490      */
  1456     public String getISO3Language() throws MissingResourceException {
  1491     public String getISO3Language() throws MissingResourceException {
  1457         String lang = _baseLocale.getLanguage();
  1492         String lang = baseLocale.getLanguage();
  1458         if (lang.length() == 3) {
  1493         if (lang.length() == 3) {
  1459             return lang;
  1494             return lang;
  1460         }
  1495         }
  1461 
  1496 
  1462         String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
  1497         String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
  1479      * @return A three-letter abbreviation of this locale's country.
  1514      * @return A three-letter abbreviation of this locale's country.
  1480      * @exception MissingResourceException Throws MissingResourceException if the
  1515      * @exception MissingResourceException Throws MissingResourceException if the
  1481      * three-letter country abbreviation is not available for this locale.
  1516      * three-letter country abbreviation is not available for this locale.
  1482      */
  1517      */
  1483     public String getISO3Country() throws MissingResourceException {
  1518     public String getISO3Country() throws MissingResourceException {
  1484         String country3 = getISO3Code(_baseLocale.getRegion(), LocaleISOData.isoCountryTable);
  1519         String country3 = getISO3Code(baseLocale.getRegion(), LocaleISOData.isoCountryTable);
  1485         if (country3 == null) {
  1520         if (country3 == null) {
  1486             throw new MissingResourceException("Couldn't find 3-letter country code for "
  1521             throw new MissingResourceException("Couldn't find 3-letter country code for "
  1487                     + _baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
  1522                     + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
  1488         }
  1523         }
  1489         return country3;
  1524         return country3;
  1490     }
  1525     }
  1491 
  1526 
  1492     private static final String getISO3Code(String iso2Code, String table) {
  1527     private static final String getISO3Code(String iso2Code, String table) {
  1540      * this function returns the empty string.
  1575      * this function returns the empty string.
  1541      *
  1576      *
  1542      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1577      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1543      */
  1578      */
  1544     public String getDisplayLanguage(Locale inLocale) {
  1579     public String getDisplayLanguage(Locale inLocale) {
  1545         return getDisplayString(_baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
  1580         return getDisplayString(baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
  1546     }
  1581     }
  1547 
  1582 
  1548     /**
  1583     /**
  1549      * Returns a name for the the locale's script that is appropriate for display to
  1584      * Returns a name for the the locale's script that is appropriate for display to
  1550      * the user. If possible, the name will be localized for the default locale.  Returns
  1585      * the user. If possible, the name will be localized for the default locale.  Returns
  1566      * @return the display name of the script code for the current default locale
  1601      * @return the display name of the script code for the current default locale
  1567      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
  1602      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
  1568      * @since 1.7
  1603      * @since 1.7
  1569      */
  1604      */
  1570     public String getDisplayScript(Locale inLocale) {
  1605     public String getDisplayScript(Locale inLocale) {
  1571         return getDisplayString(_baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
  1606         return getDisplayString(baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
  1572     }
  1607     }
  1573 
  1608 
  1574     /**
  1609     /**
  1575      * Returns a name for the locale's country that is appropriate for display to the
  1610      * Returns a name for the locale's country that is appropriate for display to the
  1576      * user.
  1611      * user.
  1601      * this function returns the empty string.
  1636      * this function returns the empty string.
  1602      *
  1637      *
  1603      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1638      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1604      */
  1639      */
  1605     public String getDisplayCountry(Locale inLocale) {
  1640     public String getDisplayCountry(Locale inLocale) {
  1606         return getDisplayString(_baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
  1641         return getDisplayString(baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
  1607     }
  1642     }
  1608 
  1643 
  1609     private String getDisplayString(String code, Locale inLocale, int type) {
  1644     private String getDisplayString(String code, Locale inLocale, int type) {
  1610         if (code.length() == 0) {
  1645         if (code.length() == 0) {
  1611             return "";
  1646             return "";
  1660      * doesn't specify a variant code, this function returns the empty string.
  1695      * doesn't specify a variant code, this function returns the empty string.
  1661      *
  1696      *
  1662      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1697      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1663      */
  1698      */
  1664     public String getDisplayVariant(Locale inLocale) {
  1699     public String getDisplayVariant(Locale inLocale) {
  1665         if (_baseLocale.getVariant().length() == 0)
  1700         if (baseLocale.getVariant().length() == 0)
  1666             return "";
  1701             return "";
  1667 
  1702 
  1668         OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1703         OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1669 
  1704 
  1670         String names[] = getDisplayVariantArray(bundle, inLocale);
  1705         String names[] = getDisplayVariantArray(bundle, inLocale);
  1756                 return "";
  1791                 return "";
  1757             } else {
  1792             } else {
  1758                 return formatList(variantNames, listPattern, listCompositionPattern);
  1793                 return formatList(variantNames, listPattern, listCompositionPattern);
  1759             }
  1794             }
  1760         }
  1795         }
  1761         ArrayList<String> names = new ArrayList<String>(4);
  1796         ArrayList<String> names = new ArrayList<>(4);
  1762         if (languageName.length() != 0) {
  1797         if (languageName.length() != 0) {
  1763             names.add(languageName);
  1798             names.add(languageName);
  1764         }
  1799         }
  1765         if (scriptName.length() != 0) {
  1800         if (scriptName.length() != 0) {
  1766             names.add(scriptName);
  1801             names.add(scriptName);
  1831     /**
  1866     /**
  1832      * Override hashCode.
  1867      * Override hashCode.
  1833      * Since Locales are often used in hashtables, caches the value
  1868      * Since Locales are often used in hashtables, caches the value
  1834      * for speed.
  1869      * for speed.
  1835      */
  1870      */
       
  1871     @Override
  1836     public int hashCode() {
  1872     public int hashCode() {
  1837         int hc = hashCodeValue;
  1873         int hc = hashCodeValue;
  1838         if (hc == 0) {
  1874         if (hc == 0) {
  1839             hc = _baseLocale.hashCode() ^ _extensions.hashCode();
  1875             hc = baseLocale.hashCode();
       
  1876             if (localeExtensions != null) {
       
  1877                 hc ^= localeExtensions.hashCode();
       
  1878             }
  1840             hashCodeValue = hc;
  1879             hashCodeValue = hc;
  1841         }
  1880         }
  1842         return hc;
  1881         return hc;
  1843     }
  1882     }
  1844 
  1883 
  1849      * deemed equal to another Locale with identical language, script, country,
  1888      * deemed equal to another Locale with identical language, script, country,
  1850      * variant and extensions, and unequal to all other objects.
  1889      * variant and extensions, and unequal to all other objects.
  1851      *
  1890      *
  1852      * @return true if this Locale is equal to the specified object.
  1891      * @return true if this Locale is equal to the specified object.
  1853      */
  1892      */
  1854 
  1893     @Override
  1855     public boolean equals(Object obj) {
  1894     public boolean equals(Object obj) {
  1856         if (this == obj)                      // quick check
  1895         if (this == obj)                      // quick check
  1857             return true;
  1896             return true;
  1858         if (!(obj instanceof Locale))
  1897         if (!(obj instanceof Locale))
  1859             return false;
  1898             return false;
  1860         BaseLocale otherBase = ((Locale)obj)._baseLocale;
  1899         BaseLocale otherBase = ((Locale)obj).baseLocale;
  1861         LocaleExtensions otherExt = ((Locale)obj)._extensions;
  1900         if (!baseLocale.equals(otherBase)) {
  1862         return _baseLocale.equals(otherBase) && _extensions.equals(otherExt);
  1901             return false;
       
  1902         }
       
  1903         if (localeExtensions == null) {
       
  1904             return ((Locale)obj).localeExtensions == null;
       
  1905         }
       
  1906         return localeExtensions.equals(((Locale)obj).localeExtensions);
  1863     }
  1907     }
  1864 
  1908 
  1865     // ================= privates =====================================
  1909     // ================= privates =====================================
  1866 
  1910 
  1867     private transient BaseLocale _baseLocale;
  1911     private transient BaseLocale baseLocale;
  1868     private transient LocaleExtensions _extensions;
  1912     private transient LocaleExtensions localeExtensions;
  1869 
  1913 
  1870     /**
  1914     /**
  1871      * Calculated hashcode
  1915      * Calculated hashcode
  1872      */
  1916      */
  1873     private transient volatile int hashCodeValue = 0;
  1917     private transient volatile int hashCodeValue = 0;
  1881      * @param bundle the ResourceBundle to use to get the display names
  1925      * @param bundle the ResourceBundle to use to get the display names
  1882      * @return an array of display names, possible of zero length.
  1926      * @return an array of display names, possible of zero length.
  1883      */
  1927      */
  1884     private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
  1928     private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
  1885         // Split the variant name into tokens separated by '_'.
  1929         // Split the variant name into tokens separated by '_'.
  1886         StringTokenizer tokenizer = new StringTokenizer(_baseLocale.getVariant(), "_");
  1930         StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
  1887         String[] names = new String[tokenizer.countTokens()];
  1931         String[] names = new String[tokenizer.countTokens()];
  1888 
  1932 
  1889         // For each variant token, lookup the display name.  If
  1933         // For each variant token, lookup the display name.  If
  1890         // not found, use the variant name itself.
  1934         // not found, use the variant name itself.
  1891         for (int i=0; i<names.length; ++i) {
  1935         for (int i=0; i<names.length; ++i) {
  1994      * @throws IOException
  2038      * @throws IOException
  1995      * @since 1.7
  2039      * @since 1.7
  1996      */
  2040      */
  1997     private void writeObject(ObjectOutputStream out) throws IOException {
  2041     private void writeObject(ObjectOutputStream out) throws IOException {
  1998         ObjectOutputStream.PutField fields = out.putFields();
  2042         ObjectOutputStream.PutField fields = out.putFields();
  1999         fields.put("language", _baseLocale.getLanguage());
  2043         fields.put("language", baseLocale.getLanguage());
  2000         fields.put("script", _baseLocale.getScript());
  2044         fields.put("script", baseLocale.getScript());
  2001         fields.put("country", _baseLocale.getRegion());
  2045         fields.put("country", baseLocale.getRegion());
  2002         fields.put("variant", _baseLocale.getVariant());
  2046         fields.put("variant", baseLocale.getVariant());
  2003         fields.put("extensions", _extensions.getID());
  2047         fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID());
  2004         fields.put("hashcode", -1); // place holder just for backward support
  2048         fields.put("hashcode", -1); // place holder just for backward support
  2005         out.writeFields();
  2049         out.writeFields();
  2006     }
  2050     }
  2007 
  2051 
  2008     /**
  2052     /**
  2018         String language = (String)fields.get("language", "");
  2062         String language = (String)fields.get("language", "");
  2019         String script = (String)fields.get("script", "");
  2063         String script = (String)fields.get("script", "");
  2020         String country = (String)fields.get("country", "");
  2064         String country = (String)fields.get("country", "");
  2021         String variant = (String)fields.get("variant", "");
  2065         String variant = (String)fields.get("variant", "");
  2022         String extStr = (String)fields.get("extensions", "");
  2066         String extStr = (String)fields.get("extensions", "");
  2023         _baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
  2067         baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
  2024         try {
  2068         if (extStr.length() > 0) {
  2025             InternalLocaleBuilder bldr = new InternalLocaleBuilder();
  2069             try {
  2026             bldr.setExtensions(extStr);
  2070                 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
  2027             _extensions = bldr.getLocaleExtensions();
  2071                 bldr.setExtensions(extStr);
  2028         } catch (LocaleSyntaxException e) {
  2072                 localeExtensions = bldr.getLocaleExtensions();
  2029             throw new IllformedLocaleException(e.getMessage());
  2073             } catch (LocaleSyntaxException e) {
       
  2074                 throw new IllformedLocaleException(e.getMessage());
       
  2075             }
       
  2076         } else {
       
  2077             localeExtensions = null;
  2030         }
  2078         }
  2031     }
  2079     }
  2032 
  2080 
  2033     /**
  2081     /**
  2034      * Returns a cached <code>Locale</code> instance equivalent to
  2082      * Returns a cached <code>Locale</code> instance equivalent to
  2043      * @return an instance of <code>Locale</code> equivalent to
  2091      * @return an instance of <code>Locale</code> equivalent to
  2044      * the deserialized <code>Locale</code>.
  2092      * the deserialized <code>Locale</code>.
  2045      * @throws java.io.ObjectStreamException
  2093      * @throws java.io.ObjectStreamException
  2046      */
  2094      */
  2047     private Object readResolve() throws java.io.ObjectStreamException {
  2095     private Object readResolve() throws java.io.ObjectStreamException {
  2048         return getInstance(_baseLocale.getLanguage(), _baseLocale.getScript(),
  2096         return getInstance(baseLocale.getLanguage(), baseLocale.getScript(),
  2049                 _baseLocale.getRegion(), _baseLocale.getVariant(), _extensions);
  2097                 baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
  2050     }
  2098     }
  2051 
  2099 
  2052     private static volatile String[] isoLanguages = null;
  2100     private static volatile String[] isoLanguages = null;
  2053 
  2101 
  2054     private static volatile String[] isoCountries = null;
  2102     private static volatile String[] isoCountries = null;
  2055 
  2103 
  2056     private static String convertOldISOCodes(String language) {
  2104     private static String convertOldISOCodes(String language) {
  2057         // we accept both the old and the new ISO codes for the languages whose ISO
  2105         // we accept both the old and the new ISO codes for the languages whose ISO
  2058         // codes have changed, but we always store the OLD code, for backward compatibility
  2106         // codes have changed, but we always store the OLD code, for backward compatibility
  2059         language = AsciiUtil.toLowerString(language).intern();
  2107         language = LocaleUtils.toLowerString(language).intern();
  2060         if (language == "he") {
  2108         if (language == "he") {
  2061             return "iw";
  2109             return "iw";
  2062         } else if (language == "yi") {
  2110         } else if (language == "yi") {
  2063             return "ji";
  2111             return "ji";
  2064         } else if (language == "id") {
  2112         } else if (language == "id") {
  2066         } else {
  2114         } else {
  2067             return language;
  2115             return language;
  2068         }
  2116         }
  2069     }
  2117     }
  2070 
  2118 
  2071     private static LocaleExtensions getCompatibilityExtensions(String language, String script, String country, String variant) {
  2119     private static LocaleExtensions getCompatibilityExtensions(String language,
  2072         LocaleExtensions extensions = LocaleExtensions.EMPTY_EXTENSIONS;
  2120                                                                String script,
       
  2121                                                                String country,
       
  2122                                                                String variant) {
       
  2123         LocaleExtensions extensions = null;
  2073         // Special cases for backward compatibility support
  2124         // Special cases for backward compatibility support
  2074         if (AsciiUtil.caseIgnoreMatch(language, "ja")
  2125         if (LocaleUtils.caseIgnoreMatch(language, "ja")
  2075                 && script.length() == 0
  2126                 && script.length() == 0
  2076                 && AsciiUtil.caseIgnoreMatch(country, "JP")
  2127                 && LocaleUtils.caseIgnoreMatch(country, "jp")
  2077                 && AsciiUtil.caseIgnoreMatch(variant, "JP")) {
  2128                 && "JP".equals(variant)) {
  2078             // ja_JP_JP -> u-ca-japanese (calendar = japanese)
  2129             // ja_JP_JP -> u-ca-japanese (calendar = japanese)
  2079             extensions = LocaleExtensions.CALENDAR_JAPANESE;
  2130             extensions = LocaleExtensions.CALENDAR_JAPANESE;
  2080         } else if (AsciiUtil.caseIgnoreMatch(language, "th")
  2131         } else if (LocaleUtils.caseIgnoreMatch(language, "th")
  2081                 && script.length() == 0
  2132                 && script.length() == 0
  2082                 && AsciiUtil.caseIgnoreMatch(country, "TH")
  2133                 && LocaleUtils.caseIgnoreMatch(country, "th")
  2083                 && AsciiUtil.caseIgnoreMatch(variant, "TH")) {
  2134                 && "TH".equals(variant)) {
  2084             // th_TH_TH -> u-nu-thai (numbersystem = thai)
  2135             // th_TH_TH -> u-nu-thai (numbersystem = thai)
  2085             extensions = LocaleExtensions.NUMBER_THAI;
  2136             extensions = LocaleExtensions.NUMBER_THAI;
  2086         }
  2137         }
  2087         return extensions;
  2138         return extensions;
  2088     }
  2139     }
  2194      *
  2245      *
  2195      * @see Locale#forLanguageTag
  2246      * @see Locale#forLanguageTag
  2196      * @since 1.7
  2247      * @since 1.7
  2197      */
  2248      */
  2198     public static final class Builder {
  2249     public static final class Builder {
  2199         private InternalLocaleBuilder _locbld;
  2250         private final InternalLocaleBuilder localeBuilder;
  2200 
  2251 
  2201         /**
  2252         /**
  2202          * Constructs an empty Builder. The default value of all
  2253          * Constructs an empty Builder. The default value of all
  2203          * fields, extensions, and private use information is the
  2254          * fields, extensions, and private use information is the
  2204          * empty string.
  2255          * empty string.
  2205          */
  2256          */
  2206         public Builder() {
  2257         public Builder() {
  2207             _locbld = new InternalLocaleBuilder();
  2258             localeBuilder = new InternalLocaleBuilder();
  2208         }
  2259         }
  2209 
  2260 
  2210         /**
  2261         /**
  2211          * Resets the <code>Builder</code> to match the provided
  2262          * Resets the <code>Builder</code> to match the provided
  2212          * <code>locale</code>.  Existing state is discarded.
  2263          * <code>locale</code>.  Existing state is discarded.
  2227          * any ill-formed fields.
  2278          * any ill-formed fields.
  2228          * @throws NullPointerException if <code>locale</code> is null.
  2279          * @throws NullPointerException if <code>locale</code> is null.
  2229          */
  2280          */
  2230         public Builder setLocale(Locale locale) {
  2281         public Builder setLocale(Locale locale) {
  2231             try {
  2282             try {
  2232                 _locbld.setLocale(locale._baseLocale, locale._extensions);
  2283                 localeBuilder.setLocale(locale.baseLocale, locale.localeExtensions);
  2233             } catch (LocaleSyntaxException e) {
  2284             } catch (LocaleSyntaxException e) {
  2234                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2285                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2235             }
  2286             }
  2236             return this;
  2287             return this;
  2237         }
  2288         }
  2257             ParseStatus sts = new ParseStatus();
  2308             ParseStatus sts = new ParseStatus();
  2258             LanguageTag tag = LanguageTag.parse(languageTag, sts);
  2309             LanguageTag tag = LanguageTag.parse(languageTag, sts);
  2259             if (sts.isError()) {
  2310             if (sts.isError()) {
  2260                 throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
  2311                 throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
  2261             }
  2312             }
  2262             _locbld.setLanguageTag(tag);
  2313             localeBuilder.setLanguageTag(tag);
  2263 
       
  2264             return this;
  2314             return this;
  2265         }
  2315         }
  2266 
  2316 
  2267         /**
  2317         /**
  2268          * Sets the language.  If <code>language</code> is the empty string or
  2318          * Sets the language.  If <code>language</code> is the empty string or
  2277          * @return This builder.
  2327          * @return This builder.
  2278          * @throws IllformedLocaleException if <code>language</code> is ill-formed
  2328          * @throws IllformedLocaleException if <code>language</code> is ill-formed
  2279          */
  2329          */
  2280         public Builder setLanguage(String language) {
  2330         public Builder setLanguage(String language) {
  2281             try {
  2331             try {
  2282                 _locbld.setLanguage(language);
  2332                 localeBuilder.setLanguage(language);
  2283             } catch (LocaleSyntaxException e) {
  2333             } catch (LocaleSyntaxException e) {
  2284                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2334                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2285             }
  2335             }
  2286             return this;
  2336             return this;
  2287         }
  2337         }
  2298          * @return This builder.
  2348          * @return This builder.
  2299          * @throws IllformedLocaleException if <code>script</code> is ill-formed
  2349          * @throws IllformedLocaleException if <code>script</code> is ill-formed
  2300          */
  2350          */
  2301         public Builder setScript(String script) {
  2351         public Builder setScript(String script) {
  2302             try {
  2352             try {
  2303                 _locbld.setScript(script);
  2353                 localeBuilder.setScript(script);
  2304             } catch (LocaleSyntaxException e) {
  2354             } catch (LocaleSyntaxException e) {
  2305                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2355                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2306             }
  2356             }
  2307             return this;
  2357             return this;
  2308         }
  2358         }
  2323          * @return This builder.
  2373          * @return This builder.
  2324          * @throws IllformedLocaleException if <code>region</code> is ill-formed
  2374          * @throws IllformedLocaleException if <code>region</code> is ill-formed
  2325          */
  2375          */
  2326         public Builder setRegion(String region) {
  2376         public Builder setRegion(String region) {
  2327             try {
  2377             try {
  2328                 _locbld.setRegion(region);
  2378                 localeBuilder.setRegion(region);
  2329             } catch (LocaleSyntaxException e) {
  2379             } catch (LocaleSyntaxException e) {
  2330                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2380                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2331             }
  2381             }
  2332             return this;
  2382             return this;
  2333         }
  2383         }
  2350          * @return This builder.
  2400          * @return This builder.
  2351          * @throws IllformedLocaleException if <code>variant</code> is ill-formed
  2401          * @throws IllformedLocaleException if <code>variant</code> is ill-formed
  2352          */
  2402          */
  2353         public Builder setVariant(String variant) {
  2403         public Builder setVariant(String variant) {
  2354             try {
  2404             try {
  2355                 _locbld.setVariant(variant);
  2405                 localeBuilder.setVariant(variant);
  2356             } catch (LocaleSyntaxException e) {
  2406             } catch (LocaleSyntaxException e) {
  2357                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2407                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2358             }
  2408             }
  2359             return this;
  2409             return this;
  2360         }
  2410         }
  2382          * or <code>value</code> is ill-formed
  2432          * or <code>value</code> is ill-formed
  2383          * @see #setUnicodeLocaleKeyword(String, String)
  2433          * @see #setUnicodeLocaleKeyword(String, String)
  2384          */
  2434          */
  2385         public Builder setExtension(char key, String value) {
  2435         public Builder setExtension(char key, String value) {
  2386             try {
  2436             try {
  2387                 _locbld.setExtension(key, value);
  2437                 localeBuilder.setExtension(key, value);
  2388             } catch (LocaleSyntaxException e) {
  2438             } catch (LocaleSyntaxException e) {
  2389                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2439                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2390             }
  2440             }
  2391             return this;
  2441             return this;
  2392         }
  2442         }
  2412          * @throws NullPointerException if <code>key</code> is null
  2462          * @throws NullPointerException if <code>key</code> is null
  2413          * @see #setExtension(char, String)
  2463          * @see #setExtension(char, String)
  2414          */
  2464          */
  2415         public Builder setUnicodeLocaleKeyword(String key, String type) {
  2465         public Builder setUnicodeLocaleKeyword(String key, String type) {
  2416             try {
  2466             try {
  2417                 _locbld.setUnicodeLocaleKeyword(key, type);
  2467                 localeBuilder.setUnicodeLocaleKeyword(key, type);
  2418             } catch (LocaleSyntaxException e) {
  2468             } catch (LocaleSyntaxException e) {
  2419                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2469                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2420             }
  2470             }
  2421             return this;
  2471             return this;
  2422         }
  2472         }
  2433          * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
  2483          * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
  2434          * @see #setExtension(char, String)
  2484          * @see #setExtension(char, String)
  2435          */
  2485          */
  2436         public Builder addUnicodeLocaleAttribute(String attribute) {
  2486         public Builder addUnicodeLocaleAttribute(String attribute) {
  2437             try {
  2487             try {
  2438                 _locbld.addUnicodeLocaleAttribute(attribute);
  2488                 localeBuilder.addUnicodeLocaleAttribute(attribute);
  2439             } catch (LocaleSyntaxException e) {
  2489             } catch (LocaleSyntaxException e) {
  2440                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2490                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2441             }
  2491             }
  2442             return this;
  2492             return this;
  2443         }
  2493         }
  2456          * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
  2506          * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
  2457          * @see #setExtension(char, String)
  2507          * @see #setExtension(char, String)
  2458          */
  2508          */
  2459         public Builder removeUnicodeLocaleAttribute(String attribute) {
  2509         public Builder removeUnicodeLocaleAttribute(String attribute) {
  2460             try {
  2510             try {
  2461                 _locbld.removeUnicodeLocaleAttribute(attribute);
  2511                 localeBuilder.removeUnicodeLocaleAttribute(attribute);
  2462             } catch (LocaleSyntaxException e) {
  2512             } catch (LocaleSyntaxException e) {
  2463                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2513                 throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  2464             }
  2514             }
  2465             return this;
  2515             return this;
  2466         }
  2516         }
  2469          * Resets the builder to its initial, empty state.
  2519          * Resets the builder to its initial, empty state.
  2470          *
  2520          *
  2471          * @return This builder.
  2521          * @return This builder.
  2472          */
  2522          */
  2473         public Builder clear() {
  2523         public Builder clear() {
  2474             _locbld.clear();
  2524             localeBuilder.clear();
  2475             return this;
  2525             return this;
  2476         }
  2526         }
  2477 
  2527 
  2478         /**
  2528         /**
  2479          * Resets the extensions to their initial, empty state.
  2529          * Resets the extensions to their initial, empty state.
  2481          *
  2531          *
  2482          * @return This builder.
  2532          * @return This builder.
  2483          * @see #setExtension(char, String)
  2533          * @see #setExtension(char, String)
  2484          */
  2534          */
  2485         public Builder clearExtensions() {
  2535         public Builder clearExtensions() {
  2486             _locbld.clearExtensions();
  2536             localeBuilder.clearExtensions();
  2487             return this;
  2537             return this;
  2488         }
  2538         }
  2489 
  2539 
  2490         /**
  2540         /**
  2491          * Returns an instance of <code>Locale</code> created from the fields set
  2541          * Returns an instance of <code>Locale</code> created from the fields set
  2496          * {@link #setLanguageTag}.)
  2546          * {@link #setLanguageTag}.)
  2497          *
  2547          *
  2498          * @return A Locale.
  2548          * @return A Locale.
  2499          */
  2549          */
  2500         public Locale build() {
  2550         public Locale build() {
  2501             BaseLocale baseloc = _locbld.getBaseLocale();
  2551             BaseLocale baseloc = localeBuilder.getBaseLocale();
  2502             LocaleExtensions extensions = _locbld.getLocaleExtensions();
  2552             LocaleExtensions extensions = localeBuilder.getLocaleExtensions();
  2503             if (extensions.isEmpty() && baseloc.getVariant().length() > 0) {
  2553             if (extensions == null && baseloc.getVariant().length() > 0) {
  2504                 extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(),
  2554                 extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(),
  2505                         baseloc.getRegion(), baseloc.getVariant());
  2555                         baseloc.getRegion(), baseloc.getVariant());
  2506             }
  2556             }
  2507             return Locale.getInstance(baseloc, extensions);
  2557             return Locale.getInstance(baseloc, extensions);
  2508         }
  2558         }