< prev index next >

src/java.base/share/classes/java/util/Locale.java

Print this page
rev 47733 : 8176841: Additional Unicode Language-Tag Extensions
8189134: New system properties for the default Locale extensions
Reviewed-by:


  31  * is copyrighted and owned by Taligent, Inc., a wholly-owned
  32  * subsidiary of IBM. These materials are provided under terms
  33  * of a License Agreement between Taligent and Sun. This technology
  34  * is protected by multiple US and International patents.
  35  *
  36  * This notice and attribution to Taligent may not be removed.
  37  * Taligent is a registered trademark of Taligent, Inc.
  38  *
  39  */
  40 
  41 package java.util;
  42 
  43 import java.io.IOException;
  44 import java.io.ObjectInputStream;
  45 import java.io.ObjectOutputStream;
  46 import java.io.ObjectStreamField;
  47 import java.io.Serializable;
  48 import java.text.MessageFormat;
  49 import java.util.concurrent.ConcurrentHashMap;
  50 import java.util.spi.LocaleNameProvider;

  51 
  52 import sun.security.action.GetPropertyAction;
  53 import sun.util.locale.BaseLocale;
  54 import sun.util.locale.InternalLocaleBuilder;
  55 import sun.util.locale.LanguageTag;
  56 import sun.util.locale.LocaleExtensions;
  57 import sun.util.locale.LocaleMatcher;
  58 import sun.util.locale.LocaleObjectCache;
  59 import sun.util.locale.LocaleSyntaxException;
  60 import sun.util.locale.LocaleUtils;
  61 import sun.util.locale.ParseStatus;
  62 import sun.util.locale.provider.LocaleProviderAdapter;
  63 import sun.util.locale.provider.LocaleResources;
  64 import sun.util.locale.provider.LocaleServiceProviderPool;

  65 
  66 /**
  67  * A <code>Locale</code> object represents a specific geographical, political,
  68  * or cultural region. An operation that requires a <code>Locale</code> to perform
  69  * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
  70  * to tailor information for the user. For example, displaying a number
  71  * is a locale-sensitive operation&mdash; the number should be formatted
  72  * according to the customs and conventions of the user's native country,
  73  * region, or culture.
  74  *
  75  * <p> The {@code Locale} class implements IETF BCP 47 which is composed of
  76  * <a href="http://tools.ietf.org/html/rfc4647">RFC 4647 "Matching of Language
  77  * Tags"</a> and <a href="http://tools.ietf.org/html/rfc5646">RFC 5646 "Tags
  78  * for Identifying Languages"</a> with support for the LDML (UTS#35, "Unicode
  79  * Locale Data Markup Language") BCP 47-compatible extensions for locale data
  80  * exchange.
  81  *
  82  * <p> A <code>Locale</code> object logically consists of the fields
  83  * described below.
  84  *


 652          * Map to hold country codes for each ISO3166 part.
 653          */
 654         private static Map<IsoCountryCode, Set<String>> iso3166CodesMap = new ConcurrentHashMap<>();
 655 
 656         /**
 657          * This method is called from Locale class to retrieve country code set
 658          * for getISOCountries(type)
 659          */
 660         static Set<String> retrieveISOCountryCodes(IsoCountryCode type) {
 661             return iso3166CodesMap.computeIfAbsent(type, IsoCountryCode::createCountryCodeSet);
 662         }
 663     }
 664 
 665     /**
 666      * Display types for retrieving localized names from the name providers.
 667      */
 668     private static final int DISPLAY_LANGUAGE = 0;
 669     private static final int DISPLAY_COUNTRY  = 1;
 670     private static final int DISPLAY_VARIANT  = 2;
 671     private static final int DISPLAY_SCRIPT   = 3;


 672 
 673     /**
 674      * Private constructor used by getInstance method
 675      */
 676     private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
 677         this.baseLocale = baseLocale;
 678         this.localeExtensions = extensions;
 679     }
 680 
 681     /**
 682      * Construct a locale from language, country and variant.
 683      * This constructor normalizes the language value to lowercase and
 684      * the country value to uppercase.
 685      * <p>
 686      * <b>Note:</b>
 687      * <ul>
 688      * <li>ISO 639 is not a stable standard; some of the language codes it defines
 689      * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 690      * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 691      * API on Locale will return only the OLD codes.


 925         language = props.getProperty("user.language", "en");
 926         // for compatibility, check for old user.region property
 927         region = props.getProperty("user.region");
 928         if (region != null) {
 929             // region can be of form country, country_variant, or _variant
 930             int i = region.indexOf('_');
 931             if (i >= 0) {
 932                 country = region.substring(0, i);
 933                 variant = region.substring(i + 1);
 934             } else {
 935                 country = region;
 936                 variant = "";
 937             }
 938             script = "";
 939         } else {
 940             script = props.getProperty("user.script", "");
 941             country = props.getProperty("user.country", "");
 942             variant = props.getProperty("user.variant", "");
 943         }
 944 
 945         return getInstance(language, script, country, variant, null);


 946     }
 947 
 948     private static Locale initDefault(Locale.Category category) {
 949         Properties props = GetPropertyAction.privilegedGetProperties();

 950         return getInstance(
 951             props.getProperty(category.languageKey,
 952                     defaultLocale.getLanguage()),
 953             props.getProperty(category.scriptKey,
 954                     defaultLocale.getScript()),
 955             props.getProperty(category.countryKey,
 956                     defaultLocale.getCountry()),
 957             props.getProperty(category.variantKey,
 958                     defaultLocale.getVariant()),
 959             null);















 960     }
 961 
 962     /**
 963      * Sets the default locale for this instance of the Java Virtual Machine.
 964      * This does not affect the host locale.
 965      * <p>
 966      * If there is a security manager, its <code>checkPermission</code>
 967      * method is called with a <code>PropertyPermission("user.language", "write")</code>
 968      * permission before the default locale is changed.
 969      * <p>
 970      * The Java Virtual Machine sets the default locale during startup
 971      * based on the host environment. It is used by many locale-sensitive
 972      * methods if no locale is explicitly specified.
 973      * <p>
 974      * Since changing the default locale may affect many different areas
 975      * of functionality, this method should only be used if the caller
 976      * is prepared to reinitialize locale-sensitive code running
 977      * within the same Java Virtual Machine.
 978      * <p>
 979      * By setting the default locale with this method, all of the default


1754     }
1755 
1756     /**
1757      * Returns a name for the locale's language that is appropriate for display to the
1758      * user.
1759      * If possible, the name returned will be localized according to inLocale.
1760      * For example, if the locale is fr_FR and inLocale
1761      * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
1762      * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
1763      * If the name returned cannot be localized according to inLocale,
1764      * (say, we don't have a Japanese name for Croatian),
1765      * this function falls back on the English name, and finally
1766      * on the ISO code as a last-resort value.  If the locale doesn't specify a language,
1767      * this function returns the empty string.
1768      *
1769      * @param inLocale The locale for which to retrieve the display language.
1770      * @return The name of the display language appropriate to the given locale.
1771      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1772      */
1773     public String getDisplayLanguage(Locale inLocale) {
1774         return getDisplayString(baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
1775     }
1776 
1777     /**
1778      * Returns a name for the locale's script that is appropriate for display to
1779      * the user. If possible, the name will be localized for the default
1780      * {@link Locale.Category#DISPLAY DISPLAY} locale.  Returns
1781      * the empty string if this locale doesn't specify a script code.
1782      *
1783      * @return the display name of the script code for the current default
1784      *     {@link Locale.Category#DISPLAY DISPLAY} locale
1785      * @since 1.7
1786      */
1787     public String getDisplayScript() {
1788         return getDisplayScript(getDefault(Category.DISPLAY));
1789     }
1790 
1791     /**
1792      * Returns a name for the locale's script that is appropriate
1793      * for display to the user. If possible, the name will be
1794      * localized for the given locale. Returns the empty string if
1795      * this locale doesn't specify a script code.
1796      *
1797      * @param inLocale The locale for which to retrieve the display script.
1798      * @return the display name of the script code for the current default
1799      * {@link Locale.Category#DISPLAY DISPLAY} locale
1800      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1801      * @since 1.7
1802      */
1803     public String getDisplayScript(Locale inLocale) {
1804         return getDisplayString(baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
1805     }
1806 
1807     /**
1808      * Returns a name for the locale's country that is appropriate for display to the
1809      * user.
1810      * If possible, the name returned will be localized for the default
1811      * {@link Locale.Category#DISPLAY DISPLAY} locale.
1812      * For example, if the locale is fr_FR and the default
1813      * {@link Locale.Category#DISPLAY DISPLAY} locale
1814      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1815      * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
1816      * getDisplayCountry() will return "Etats-Unis".
1817      * If the name returned cannot be localized for the default
1818      * {@link Locale.Category#DISPLAY DISPLAY} locale,
1819      * (say, we don't have a Japanese name for Croatia),
1820      * this function falls back on the English name, and uses the ISO code as a last-resort
1821      * value.  If the locale doesn't specify a country, this function returns the empty string.
1822      *
1823      * @return The name of the country appropriate to the locale.
1824      */


1827     }
1828 
1829     /**
1830      * Returns a name for the locale's country that is appropriate for display to the
1831      * user.
1832      * If possible, the name returned will be localized according to inLocale.
1833      * For example, if the locale is fr_FR and inLocale
1834      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1835      * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
1836      * If the name returned cannot be localized according to inLocale.
1837      * (say, we don't have a Japanese name for Croatia),
1838      * this function falls back on the English name, and finally
1839      * on the ISO code as a last-resort value.  If the locale doesn't specify a country,
1840      * this function returns the empty string.
1841      *
1842      * @param inLocale The locale for which to retrieve the display country.
1843      * @return The name of the country appropriate to the given locale.
1844      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1845      */
1846     public String getDisplayCountry(Locale inLocale) {
1847         return getDisplayString(baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
1848     }
1849 
1850     private String getDisplayString(String code, Locale inLocale, int type) {
1851         if (code.length() == 0) {
1852             return "";
1853         }
1854 
1855         if (inLocale == null) {
1856             throw new NullPointerException();
1857         }
1858 
1859         LocaleServiceProviderPool pool =
1860             LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
1861         String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
1862         String result = pool.getLocalizedObject(
1863                                 LocaleNameGetter.INSTANCE,
1864                                 inLocale, key, type, code);
1865             if (result != null) {
1866                 return result;
1867             }
1868 
1869         return code;
1870     }
1871 
1872     /**
1873      * Returns a name for the locale's variant code that is appropriate for display to the
1874      * user.  If possible, the name will be localized for the default
1875      * {@link Locale.Category#DISPLAY DISPLAY} locale.  If the locale
1876      * doesn't specify a variant code, this function returns the empty string.
1877      *
1878      * @return The name of the display variant code appropriate to the locale.
1879      */
1880     public final String getDisplayVariant() {
1881         return getDisplayVariant(getDefault(Category.DISPLAY));
1882     }
1883 
1884     /**
1885      * Returns a name for the locale's variant code that is appropriate for display to the
1886      * user.  If possible, the name will be localized for inLocale.  If the locale
1887      * doesn't specify a variant code, this function returns the empty string.
1888      *
1889      * @param inLocale The locale for which to retrieve the display variant code.
1890      * @return The name of the display variant code appropriate to the given locale.
1891      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1892      */
1893     public String getDisplayVariant(Locale inLocale) {
1894         if (baseLocale.getVariant().length() == 0)
1895             return "";
1896 
1897         LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);


1898 
1899         String names[] = getDisplayVariantArray(inLocale);
1900 
1901         // Get the localized patterns for formatting a list, and use
1902         // them to format the list.
1903         return formatList(names,
1904                           lr.getLocaleName("ListPattern"),
1905                           lr.getLocaleName("ListCompositionPattern"));
1906     }
1907 
1908     /**
1909      * Returns a name for the locale that is appropriate for display to the
1910      * user. This will be the values returned by getDisplayLanguage(),
1911      * getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled
1912      * into a single string. The non-empty values are used in order,
1913      * with the second and subsequent names in parentheses.  For example:

1914      * <blockquote>
1915      * language (script, country, variant)<br>
1916      * language (country)<br>
1917      * language (variant)<br>
1918      * script (country)<br>
1919      * country<br>
1920      * </blockquote>
1921      * depending on which fields are specified in the locale.  If the
1922      * language, script, country, and variant fields are all empty,
1923      * this function returns the empty string.
1924      *
1925      * @return The name of the locale appropriate to display.
1926      */
1927     public final String getDisplayName() {
1928         return getDisplayName(getDefault(Category.DISPLAY));
1929     }
1930 
1931     /**
1932      * Returns a name for the locale that is appropriate for display
1933      * to the user.  This will be the values returned by
1934      * getDisplayLanguage(), getDisplayScript(),getDisplayCountry(),
1935      * and getDisplayVariant() assembled into a single string.
1936      * The non-empty values are used in order,
1937      * with the second and subsequent names in parentheses.  For example:

1938      * <blockquote>
1939      * language (script, country, variant)<br>
1940      * language (country)<br>
1941      * language (variant)<br>
1942      * script (country)<br>
1943      * country<br>
1944      * </blockquote>
1945      * depending on which fields are specified in the locale.  If the
1946      * language, script, country, and variant fields are all empty,
1947      * this function returns the empty string.
1948      *
1949      * @param inLocale The locale for which to retrieve the display name.
1950      * @return The name of the locale appropriate to display.
1951      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1952      */
1953     public String getDisplayName(Locale inLocale) {
1954         LocaleResources lr =  LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);


1955 
1956         String languageName = getDisplayLanguage(inLocale);
1957         String scriptName = getDisplayScript(inLocale);
1958         String countryName = getDisplayCountry(inLocale);
1959         String[] variantNames = getDisplayVariantArray(inLocale);
1960 
1961         // Get the localized patterns for formatting a display name.
1962         String displayNamePattern = lr.getLocaleName("DisplayNamePattern");
1963         String listPattern = lr.getLocaleName("ListPattern");
1964         String listCompositionPattern = lr.getLocaleName("ListCompositionPattern");
1965 
1966         // The display name consists of a main name, followed by qualifiers.
1967         // Typically, the format is "MainName (Qualifier, Qualifier)" but this
1968         // depends on what pattern is stored in the display locale.
1969         String   mainName       = null;
1970         String[] qualifierNames = null;
1971 
1972         // The main name is the language, or if there is no language, the script,
1973         // then if no script, the country. If there is no language/script/country
1974         // (an anomalous situation) then the display name is simply the variant's
1975         // display name.
1976         if (languageName.length() == 0 && scriptName.length() == 0 && countryName.length() == 0) {
1977             if (variantNames.length == 0) {
1978                 return "";
1979             } else {
1980                 return formatList(variantNames, listPattern, listCompositionPattern);
1981             }
1982         }
1983         ArrayList<String> names = new ArrayList<>(4);
1984         if (languageName.length() != 0) {
1985             names.add(languageName);
1986         }
1987         if (scriptName.length() != 0) {
1988             names.add(scriptName);
1989         }
1990         if (countryName.length() != 0) {
1991             names.add(countryName);
1992         }
1993         if (variantNames.length != 0) {
1994             names.addAll(Arrays.asList(variantNames));
1995         }
1996 










1997         // The first one in the main name
1998         mainName = names.get(0);
1999 
2000         // Others are qualifiers
2001         int numNames = names.size();
2002         qualifierNames = (numNames > 1) ?
2003                 names.subList(1, numNames).toArray(new String[numNames - 1]) : new String[0];
2004 
2005         // Create an array whose first element is the number of remaining
2006         // elements.  This serves as a selector into a ChoiceFormat pattern from
2007         // the resource.  The second and third elements are the main name and
2008         // the qualifier; if there are no qualifiers, the third element is
2009         // unused by the format pattern.
2010         Object[] displayNames = {
2011             qualifierNames.length != 0 ? 2 : 1,
2012             mainName,
2013             // We could also just call formatList() and have it handle the empty
2014             // list case, but this is more efficient, and we want it to be
2015             // efficient since all the language-only locales will not have any
2016             // qualifiers.
2017             qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null
2018         };
2019 
2020         if (displayNamePattern != null) {
2021             return new MessageFormat(displayNamePattern).format(displayNames);
2022         }
2023         else {
2024             // If we cannot get the message format pattern, then we use a simple
2025             // hard-coded pattern.  This should not occur in practice unless the
2026             // installation is missing some core files (FormatData etc.).
2027             StringBuilder result = new StringBuilder();
2028             result.append((String)displayNames[1]);
2029             if (displayNames.length > 2) {
2030                 result.append(" (");
2031                 result.append((String)displayNames[2]);
2032                 result.append(')');
2033             }
2034             return result.toString();
2035         }
2036     }
2037 


2104 
2105     private static volatile Locale defaultLocale = initDefault();
2106     private static volatile Locale defaultDisplayLocale;
2107     private static volatile Locale defaultFormatLocale;
2108 
2109     private transient volatile String languageTag;
2110 
2111     /**
2112      * Return an array of the display names of the variant.
2113      * @param bundle the ResourceBundle to use to get the display names
2114      * @return an array of display names, possible of zero length.
2115      */
2116     private String[] getDisplayVariantArray(Locale inLocale) {
2117         // Split the variant name into tokens separated by '_'.
2118         StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
2119         String[] names = new String[tokenizer.countTokens()];
2120 
2121         // For each variant token, lookup the display name.  If
2122         // not found, use the variant name itself.
2123         for (int i=0; i<names.length; ++i) {
2124             names[i] = getDisplayString(tokenizer.nextToken(),
2125                                 inLocale, DISPLAY_VARIANT);
2126         }
2127 
2128         return names;
2129     }
2130 
































2131     /**
2132      * Format a list using given pattern strings.
2133      * If either of the patterns is null, then a the list is
2134      * formatted by concatenation with the delimiter ','.
2135      * @param stringList the list of strings to be formatted.
2136      * @param listPattern should create a MessageFormat taking 0-3 arguments
2137      * and formatting them into a list.
2138      * @param listCompositionPattern should take 2 arguments
2139      * and is used by composeList.
2140      * @return a string representing the list.
2141      */
2142     private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
2143         // If we have no list patterns, compose the list in a simple,
2144         // non-localized way.
2145         if (listPattern == null || listCompositionPattern == null) {
2146             StringJoiner sj = new StringJoiner(",");
2147             for (int i = 0; i < stringList.length; ++i) {
2148                 sj.add(stringList[i]);
2149             }
2150             return sj.toString();
2151         }
2152 
2153         // Compose the list down to three elements if necessary
2154         if (stringList.length > 3) {
2155             MessageFormat format = new MessageFormat(listCompositionPattern);
2156             stringList = composeList(format, stringList);






2157         }
2158 
2159         // Rebuild the argument list with the list length as the first element
2160         Object[] args = new Object[stringList.length + 1];
2161         System.arraycopy(stringList, 0, args, 1, stringList.length);
2162         args[0] = stringList.length;
2163 
2164         // Format it using the pattern in the resource
2165         MessageFormat format = new MessageFormat(listPattern);
2166         return format.format(args);
2167     }
2168 
2169     /**
2170      * Given a list of strings, return a list shortened to three elements.
2171      * Shorten it by applying the given format to the first two elements
2172      * recursively.
2173      * @param format a format which takes two arguments
2174      * @param list a list of strings
2175      * @return if the list is three elements or shorter, the same list;
2176      * otherwise, a new list of three elements.
2177      */
2178     private static String[] composeList(MessageFormat format, String[] list) {
2179         if (list.length <= 3) return list;
2180 
2181         // Use the given format to compose the first two elements into one
2182         String[] listItems = { list[0], list[1] };
2183         String newItem = format.format(listItems);
2184 
2185         // Form a new list one element shorter
2186         String[] newList = new String[list.length-1];
2187         System.arraycopy(list, 2, newList, 1, newList.length-1);
2188         newList[0] = newItem;
2189 
2190         // Recurse
2191         return composeList(format, newList);
2192     }
2193 
2194     // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
2195     // avoid its class loading.
2196     private static boolean isUnicodeExtensionKey(String s) {
2197         // 2alphanum
2198         return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
2199     }
2200 
2201     /**
2202      * @serialField language    String
2203      *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
2204      * @serialField country     String
2205      *      country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
2206      * @serialField variant     String
2207      *      variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>)
2208      * @serialField hashcode    int
2209      *      deprecated, for forward compatibility only
2210      * @serialField script      String
2211      *      script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>)


2328                 && "TH".equals(variant)) {
2329             // th_TH_TH -> u-nu-thai (numbersystem = thai)
2330             extensions = LocaleExtensions.NUMBER_THAI;
2331         }
2332         return extensions;
2333     }
2334 
2335     /**
2336      * Obtains a localized locale names from a LocaleNameProvider
2337      * implementation.
2338      */
2339     private static class LocaleNameGetter
2340         implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
2341         private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
2342 
2343         @Override
2344         public String getObject(LocaleNameProvider localeNameProvider,
2345                                 Locale locale,
2346                                 String key,
2347                                 Object... params) {
2348             assert params.length == 2;
2349             int type = (Integer)params[0];
2350             String code = (String)params[1];

2351 
2352             switch(type) {
2353             case DISPLAY_LANGUAGE:
2354                 return localeNameProvider.getDisplayLanguage(code, locale);
2355             case DISPLAY_COUNTRY:
2356                 return localeNameProvider.getDisplayCountry(code, locale);
2357             case DISPLAY_VARIANT:
2358                 return localeNameProvider.getDisplayVariant(code, locale);
2359             case DISPLAY_SCRIPT:
2360                 return localeNameProvider.getDisplayScript(code, locale);




2361             default:
2362                 assert false; // shouldn't happen
2363             }
2364 
2365             return null;
2366         }
2367     }
2368 
2369     /**
2370      * Enum for locale categories.  These locale categories are used to get/set
2371      * the default locale for the specific functionality represented by the
2372      * category.
2373      *
2374      * @see #getDefault(Locale.Category)
2375      * @see #setDefault(Locale.Category, Locale)
2376      * @since 1.7
2377      */
2378     public enum Category {
2379 
2380         /**
2381          * Category used to represent the default locale for
2382          * displaying user interfaces.
2383          */
2384         DISPLAY("user.language.display",
2385                 "user.script.display",
2386                 "user.country.display",
2387                 "user.variant.display"),

2388 
2389         /**
2390          * Category used to represent the default locale for
2391          * formatting dates, numbers, and/or currencies.
2392          */
2393         FORMAT("user.language.format",
2394                "user.script.format",
2395                "user.country.format",
2396                "user.variant.format");

2397 
2398         Category(String languageKey, String scriptKey, String countryKey, String variantKey) {

2399             this.languageKey = languageKey;
2400             this.scriptKey = scriptKey;
2401             this.countryKey = countryKey;
2402             this.variantKey = variantKey;

2403         }
2404 
2405         final String languageKey;
2406         final String scriptKey;
2407         final String countryKey;
2408         final String variantKey;

2409     }
2410 
2411     /**
2412      * <code>Builder</code> is used to build instances of <code>Locale</code>
2413      * from values configured by the setters.  Unlike the <code>Locale</code>
2414      * constructors, the <code>Builder</code> checks if a value configured by a
2415      * setter satisfies the syntax requirements defined by the <code>Locale</code>
2416      * class.  A <code>Locale</code> object created by a <code>Builder</code> is
2417      * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
2418      * without losing information.
2419      *
2420      * <p><b>Note:</b> The <code>Locale</code> class does not provide any
2421      * syntactic restrictions on variant, while BCP 47 requires each variant
2422      * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
2423      * alphanumerics.  The method <code>setVariant</code> throws
2424      * <code>IllformedLocaleException</code> for a variant that does not satisfy
2425      * this restriction. If it is necessary to support such a variant, use a
2426      * Locale constructor.  However, keep in mind that a <code>Locale</code>
2427      * object created this way might lose the variant information when
2428      * transformed to a BCP 47 language tag.




  31  * is copyrighted and owned by Taligent, Inc., a wholly-owned
  32  * subsidiary of IBM. These materials are provided under terms
  33  * of a License Agreement between Taligent and Sun. This technology
  34  * is protected by multiple US and International patents.
  35  *
  36  * This notice and attribution to Taligent may not be removed.
  37  * Taligent is a registered trademark of Taligent, Inc.
  38  *
  39  */
  40 
  41 package java.util;
  42 
  43 import java.io.IOException;
  44 import java.io.ObjectInputStream;
  45 import java.io.ObjectOutputStream;
  46 import java.io.ObjectStreamField;
  47 import java.io.Serializable;
  48 import java.text.MessageFormat;
  49 import java.util.concurrent.ConcurrentHashMap;
  50 import java.util.spi.LocaleNameProvider;
  51 import java.util.stream.Collectors;
  52 
  53 import sun.security.action.GetPropertyAction;
  54 import sun.util.locale.BaseLocale;
  55 import sun.util.locale.InternalLocaleBuilder;
  56 import sun.util.locale.LanguageTag;
  57 import sun.util.locale.LocaleExtensions;
  58 import sun.util.locale.LocaleMatcher;
  59 import sun.util.locale.LocaleObjectCache;
  60 import sun.util.locale.LocaleSyntaxException;
  61 import sun.util.locale.LocaleUtils;
  62 import sun.util.locale.ParseStatus;
  63 import sun.util.locale.provider.LocaleProviderAdapter;
  64 import sun.util.locale.provider.LocaleResources;
  65 import sun.util.locale.provider.LocaleServiceProviderPool;
  66 import sun.util.locale.provider.TimeZoneNameUtility;
  67 
  68 /**
  69  * A <code>Locale</code> object represents a specific geographical, political,
  70  * or cultural region. An operation that requires a <code>Locale</code> to perform
  71  * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
  72  * to tailor information for the user. For example, displaying a number
  73  * is a locale-sensitive operation&mdash; the number should be formatted
  74  * according to the customs and conventions of the user's native country,
  75  * region, or culture.
  76  *
  77  * <p> The {@code Locale} class implements IETF BCP 47 which is composed of
  78  * <a href="http://tools.ietf.org/html/rfc4647">RFC 4647 "Matching of Language
  79  * Tags"</a> and <a href="http://tools.ietf.org/html/rfc5646">RFC 5646 "Tags
  80  * for Identifying Languages"</a> with support for the LDML (UTS#35, "Unicode
  81  * Locale Data Markup Language") BCP 47-compatible extensions for locale data
  82  * exchange.
  83  *
  84  * <p> A <code>Locale</code> object logically consists of the fields
  85  * described below.
  86  *


 654          * Map to hold country codes for each ISO3166 part.
 655          */
 656         private static Map<IsoCountryCode, Set<String>> iso3166CodesMap = new ConcurrentHashMap<>();
 657 
 658         /**
 659          * This method is called from Locale class to retrieve country code set
 660          * for getISOCountries(type)
 661          */
 662         static Set<String> retrieveISOCountryCodes(IsoCountryCode type) {
 663             return iso3166CodesMap.computeIfAbsent(type, IsoCountryCode::createCountryCodeSet);
 664         }
 665     }
 666 
 667     /**
 668      * Display types for retrieving localized names from the name providers.
 669      */
 670     private static final int DISPLAY_LANGUAGE  = 0;
 671     private static final int DISPLAY_COUNTRY   = 1;
 672     private static final int DISPLAY_VARIANT   = 2;
 673     private static final int DISPLAY_SCRIPT    = 3;
 674     private static final int DISPLAY_UEXT_KEY  = 4;
 675     private static final int DISPLAY_UEXT_TYPE = 5;
 676 
 677     /**
 678      * Private constructor used by getInstance method
 679      */
 680     private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
 681         this.baseLocale = baseLocale;
 682         this.localeExtensions = extensions;
 683     }
 684 
 685     /**
 686      * Construct a locale from language, country and variant.
 687      * This constructor normalizes the language value to lowercase and
 688      * the country value to uppercase.
 689      * <p>
 690      * <b>Note:</b>
 691      * <ul>
 692      * <li>ISO 639 is not a stable standard; some of the language codes it defines
 693      * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 694      * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 695      * API on Locale will return only the OLD codes.


 929         language = props.getProperty("user.language", "en");
 930         // for compatibility, check for old user.region property
 931         region = props.getProperty("user.region");
 932         if (region != null) {
 933             // region can be of form country, country_variant, or _variant
 934             int i = region.indexOf('_');
 935             if (i >= 0) {
 936                 country = region.substring(0, i);
 937                 variant = region.substring(i + 1);
 938             } else {
 939                 country = region;
 940                 variant = "";
 941             }
 942             script = "";
 943         } else {
 944             script = props.getProperty("user.script", "");
 945             country = props.getProperty("user.country", "");
 946             variant = props.getProperty("user.variant", "");
 947         }
 948 
 949         return getInstance(language, script, country, variant,
 950                 getDefaultExtensions(props.getProperty("user.extensions", ""))
 951                     .orElse(null));
 952     }
 953 
 954     private static Locale initDefault(Locale.Category category) {
 955         Properties props = GetPropertyAction.privilegedGetProperties();
 956 
 957         return getInstance(
 958             props.getProperty(category.languageKey,
 959                     defaultLocale.getLanguage()),
 960             props.getProperty(category.scriptKey,
 961                     defaultLocale.getScript()),
 962             props.getProperty(category.countryKey,
 963                     defaultLocale.getCountry()),
 964             props.getProperty(category.variantKey,
 965                     defaultLocale.getVariant()),
 966             getDefaultExtensions(props.getProperty(category.extensionsKey, ""))
 967                 .orElse(defaultLocale.getLocaleExtensions()));
 968     }
 969 
 970     private static Optional<LocaleExtensions> getDefaultExtensions(String extensionsProp) {
 971         LocaleExtensions exts = null;
 972 
 973         try {
 974             exts = new InternalLocaleBuilder()
 975                 .setExtensions(extensionsProp)
 976                 .getLocaleExtensions();
 977         } catch (LocaleSyntaxException e) {
 978             // just ignore this incorrect property
 979         }
 980 
 981         return Optional.ofNullable(exts);
 982     }
 983 
 984     /**
 985      * Sets the default locale for this instance of the Java Virtual Machine.
 986      * This does not affect the host locale.
 987      * <p>
 988      * If there is a security manager, its <code>checkPermission</code>
 989      * method is called with a <code>PropertyPermission("user.language", "write")</code>
 990      * permission before the default locale is changed.
 991      * <p>
 992      * The Java Virtual Machine sets the default locale during startup
 993      * based on the host environment. It is used by many locale-sensitive
 994      * methods if no locale is explicitly specified.
 995      * <p>
 996      * Since changing the default locale may affect many different areas
 997      * of functionality, this method should only be used if the caller
 998      * is prepared to reinitialize locale-sensitive code running
 999      * within the same Java Virtual Machine.
1000      * <p>
1001      * By setting the default locale with this method, all of the default


1776     }
1777 
1778     /**
1779      * Returns a name for the locale's language that is appropriate for display to the
1780      * user.
1781      * If possible, the name returned will be localized according to inLocale.
1782      * For example, if the locale is fr_FR and inLocale
1783      * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
1784      * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
1785      * If the name returned cannot be localized according to inLocale,
1786      * (say, we don't have a Japanese name for Croatian),
1787      * this function falls back on the English name, and finally
1788      * on the ISO code as a last-resort value.  If the locale doesn't specify a language,
1789      * this function returns the empty string.
1790      *
1791      * @param inLocale The locale for which to retrieve the display language.
1792      * @return The name of the display language appropriate to the given locale.
1793      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1794      */
1795     public String getDisplayLanguage(Locale inLocale) {
1796         return getDisplayString(baseLocale.getLanguage(), null, inLocale, DISPLAY_LANGUAGE);
1797     }
1798 
1799     /**
1800      * Returns a name for the locale's script that is appropriate for display to
1801      * the user. If possible, the name will be localized for the default
1802      * {@link Locale.Category#DISPLAY DISPLAY} locale.  Returns
1803      * the empty string if this locale doesn't specify a script code.
1804      *
1805      * @return the display name of the script code for the current default
1806      *     {@link Locale.Category#DISPLAY DISPLAY} locale
1807      * @since 1.7
1808      */
1809     public String getDisplayScript() {
1810         return getDisplayScript(getDefault(Category.DISPLAY));
1811     }
1812 
1813     /**
1814      * Returns a name for the locale's script that is appropriate
1815      * for display to the user. If possible, the name will be
1816      * localized for the given locale. Returns the empty string if
1817      * this locale doesn't specify a script code.
1818      *
1819      * @param inLocale The locale for which to retrieve the display script.
1820      * @return the display name of the script code for the current default
1821      * {@link Locale.Category#DISPLAY DISPLAY} locale
1822      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1823      * @since 1.7
1824      */
1825     public String getDisplayScript(Locale inLocale) {
1826         return getDisplayString(baseLocale.getScript(), null, inLocale, DISPLAY_SCRIPT);
1827     }
1828 
1829     /**
1830      * Returns a name for the locale's country that is appropriate for display to the
1831      * user.
1832      * If possible, the name returned will be localized for the default
1833      * {@link Locale.Category#DISPLAY DISPLAY} locale.
1834      * For example, if the locale is fr_FR and the default
1835      * {@link Locale.Category#DISPLAY DISPLAY} locale
1836      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1837      * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
1838      * getDisplayCountry() will return "Etats-Unis".
1839      * If the name returned cannot be localized for the default
1840      * {@link Locale.Category#DISPLAY DISPLAY} locale,
1841      * (say, we don't have a Japanese name for Croatia),
1842      * this function falls back on the English name, and uses the ISO code as a last-resort
1843      * value.  If the locale doesn't specify a country, this function returns the empty string.
1844      *
1845      * @return The name of the country appropriate to the locale.
1846      */


1849     }
1850 
1851     /**
1852      * Returns a name for the locale's country that is appropriate for display to the
1853      * user.
1854      * If possible, the name returned will be localized according to inLocale.
1855      * For example, if the locale is fr_FR and inLocale
1856      * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1857      * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
1858      * If the name returned cannot be localized according to inLocale.
1859      * (say, we don't have a Japanese name for Croatia),
1860      * this function falls back on the English name, and finally
1861      * on the ISO code as a last-resort value.  If the locale doesn't specify a country,
1862      * this function returns the empty string.
1863      *
1864      * @param inLocale The locale for which to retrieve the display country.
1865      * @return The name of the country appropriate to the given locale.
1866      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1867      */
1868     public String getDisplayCountry(Locale inLocale) {
1869         return getDisplayString(baseLocale.getRegion(), null, inLocale, DISPLAY_COUNTRY);
1870     }
1871 
1872     private String getDisplayString(String code, String cat, Locale inLocale, int type) {
1873         Objects.requireNonNull(inLocale);
1874         Objects.requireNonNull(code);

1875 
1876         if (code.isEmpty()) {
1877             return "";
1878         }
1879 
1880         LocaleServiceProviderPool pool =
1881             LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
1882         String rbKey = (type == DISPLAY_VARIANT ? "%%"+code : code);
1883         String result = pool.getLocalizedObject(
1884                                 LocaleNameGetter.INSTANCE,
1885                                 inLocale, rbKey, type, code, cat);
1886         return result != null ? result : code;




1887     }
1888 
1889     /**
1890      * Returns a name for the locale's variant code that is appropriate for display to the
1891      * user.  If possible, the name will be localized for the default
1892      * {@link Locale.Category#DISPLAY DISPLAY} locale.  If the locale
1893      * doesn't specify a variant code, this function returns the empty string.
1894      *
1895      * @return The name of the display variant code appropriate to the locale.
1896      */
1897     public final String getDisplayVariant() {
1898         return getDisplayVariant(getDefault(Category.DISPLAY));
1899     }
1900 
1901     /**
1902      * Returns a name for the locale's variant code that is appropriate for display to the
1903      * user.  If possible, the name will be localized for inLocale.  If the locale
1904      * doesn't specify a variant code, this function returns the empty string.
1905      *
1906      * @param inLocale The locale for which to retrieve the display variant code.
1907      * @return The name of the display variant code appropriate to the given locale.
1908      * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1909      */
1910     public String getDisplayVariant(Locale inLocale) {
1911         if (baseLocale.getVariant().length() == 0)
1912             return "";
1913 
1914         LocaleResources lr = LocaleProviderAdapter
1915             .getResourceBundleBased()
1916             .getLocaleResources(inLocale);
1917 
1918         String names[] = getDisplayVariantArray(inLocale);
1919 
1920         // Get the localized patterns for formatting a list, and use
1921         // them to format the list.
1922         return formatList(names,

1923                           lr.getLocaleName("ListCompositionPattern"));
1924     }
1925 
1926     /**
1927      * Returns a name for the locale that is appropriate for display to the
1928      * user. This will be the values returned by getDisplayLanguage(),
1929      * getDisplayScript(), getDisplayCountry(), getDisplayVariant() and
1930      * optional <a href="./Locale.html#def_locale_extension">Unicode extensions</a>
1931      * assembled into a single string. The non-empty values are used in order, with
1932      * the second and subsequent names in parentheses.  For example:
1933      * <blockquote>
1934      * language (script, country, variant(, extension)*)<br>
1935      * language (country(, extension)*)<br>
1936      * language (variant(, extension)*)<br>
1937      * script (country(, extension)*)<br>
1938      * country (extension)*<br>
1939      * </blockquote>
1940      * depending on which fields are specified in the locale.  If the
1941      * language, script, country, and variant fields are all empty,
1942      * this function returns the empty string.
1943      *
1944      * @return The name of the locale appropriate to display.
1945      */
1946     public final String getDisplayName() {
1947         return getDisplayName(getDefault(Category.DISPLAY));
1948     }
1949 
1950     /**
1951      * Returns a name for the locale that is appropriate for display
1952      * to the user.  This will be the values returned by
1953      * getDisplayLanguage(), getDisplayScript(),getDisplayCountry()
1954      * getDisplayVariant(), and optional <a href="./Locale.html#def_locale_extension">
1955      * Unicode extensions</a> assembled into a single string. The non-empty
1956      * values are used in order, with the second and subsequent names in
1957      * parentheses.  For example:
1958      * <blockquote>
1959      * language (script, country, variant(, extension)*)<br>
1960      * language (country(, extension)*)<br>
1961      * language (variant(, extension)*)<br>
1962      * script (country(, extension)*)<br>
1963      * country (extension)*<br>
1964      * </blockquote>
1965      * depending on which fields are specified in the locale.  If the
1966      * language, script, country, and variant fields are all empty,
1967      * this function returns the empty string.
1968      *
1969      * @param inLocale The locale for which to retrieve the display name.
1970      * @return The name of the locale appropriate to display.
1971      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1972      */
1973     public String getDisplayName(Locale inLocale) {
1974         LocaleResources lr =  LocaleProviderAdapter
1975             .getResourceBundleBased()
1976             .getLocaleResources(inLocale);
1977 
1978         String languageName = getDisplayLanguage(inLocale);
1979         String scriptName = getDisplayScript(inLocale);
1980         String countryName = getDisplayCountry(inLocale);
1981         String[] variantNames = getDisplayVariantArray(inLocale);
1982 
1983         // Get the localized patterns for formatting a display name.
1984         String displayNamePattern = lr.getLocaleName("DisplayNamePattern");

1985         String listCompositionPattern = lr.getLocaleName("ListCompositionPattern");
1986 
1987         // The display name consists of a main name, followed by qualifiers.
1988         // Typically, the format is "MainName (Qualifier, Qualifier)" but this
1989         // depends on what pattern is stored in the display locale.
1990         String   mainName       = null;
1991         String[] qualifierNames = null;
1992 
1993         // The main name is the language, or if there is no language, the script,
1994         // then if no script, the country. If there is no language/script/country
1995         // (an anomalous situation) then the display name is simply the variant's
1996         // display name.
1997         if (languageName.length() == 0 && scriptName.length() == 0 && countryName.length() == 0) {
1998             if (variantNames.length == 0) {
1999                 return "";
2000             } else {
2001                 return formatList(variantNames, listCompositionPattern);
2002             }
2003         }
2004         ArrayList<String> names = new ArrayList<>(4);
2005         if (languageName.length() != 0) {
2006             names.add(languageName);
2007         }
2008         if (scriptName.length() != 0) {
2009             names.add(scriptName);
2010         }
2011         if (countryName.length() != 0) {
2012             names.add(countryName);
2013         }
2014         if (variantNames.length != 0) {
2015             names.addAll(Arrays.asList(variantNames));
2016         }
2017 
2018         // add Unicode extensions
2019         if (localeExtensions != null) {
2020             localeExtensions.getUnicodeLocaleAttributes().stream()
2021                 .map(key -> getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY))
2022                 .forEach(names::add);
2023             localeExtensions.getUnicodeLocaleKeys().stream()
2024                 .map(key -> getDisplayKeyTypeExtensionString(key, lr, inLocale))
2025                 .forEach(names::add);
2026         }
2027 
2028         // The first one in the main name
2029         mainName = names.get(0);
2030 
2031         // Others are qualifiers
2032         int numNames = names.size();
2033         qualifierNames = (numNames > 1) ?
2034                 names.subList(1, numNames).toArray(new String[numNames - 1]) : new String[0];
2035 
2036         // Create an array whose first element is the number of remaining
2037         // elements.  This serves as a selector into a ChoiceFormat pattern from
2038         // the resource.  The second and third elements are the main name and
2039         // the qualifier; if there are no qualifiers, the third element is
2040         // unused by the format pattern.
2041         Object[] displayNames = {
2042             qualifierNames.length != 0 ? 2 : 1,
2043             mainName,
2044             // We could also just call formatList() and have it handle the empty
2045             // list case, but this is more efficient, and we want it to be
2046             // efficient since all the language-only locales will not have any
2047             // qualifiers.
2048             qualifierNames.length != 0 ? formatList(qualifierNames, listCompositionPattern) : null
2049         };
2050 
2051         if (displayNamePattern != null) {
2052             return new MessageFormat(displayNamePattern).format(displayNames);
2053         }
2054         else {
2055             // If we cannot get the message format pattern, then we use a simple
2056             // hard-coded pattern.  This should not occur in practice unless the
2057             // installation is missing some core files (FormatData etc.).
2058             StringBuilder result = new StringBuilder();
2059             result.append((String)displayNames[1]);
2060             if (displayNames.length > 2) {
2061                 result.append(" (");
2062                 result.append((String)displayNames[2]);
2063                 result.append(')');
2064             }
2065             return result.toString();
2066         }
2067     }
2068 


2135 
2136     private static volatile Locale defaultLocale = initDefault();
2137     private static volatile Locale defaultDisplayLocale;
2138     private static volatile Locale defaultFormatLocale;
2139 
2140     private transient volatile String languageTag;
2141 
2142     /**
2143      * Return an array of the display names of the variant.
2144      * @param bundle the ResourceBundle to use to get the display names
2145      * @return an array of display names, possible of zero length.
2146      */
2147     private String[] getDisplayVariantArray(Locale inLocale) {
2148         // Split the variant name into tokens separated by '_'.
2149         StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
2150         String[] names = new String[tokenizer.countTokens()];
2151 
2152         // For each variant token, lookup the display name.  If
2153         // not found, use the variant name itself.
2154         for (int i=0; i<names.length; ++i) {
2155             names[i] = getDisplayString(tokenizer.nextToken(), null,
2156                                 inLocale, DISPLAY_VARIANT);
2157         }
2158 
2159         return names;
2160     }
2161 
2162     private String getDisplayKeyTypeExtensionString(String key, LocaleResources lr, Locale inLocale) {
2163         String type = localeExtensions.getUnicodeLocaleType(key);
2164         String ret = getDisplayString(type, key, inLocale, DISPLAY_UEXT_TYPE);
2165 
2166         if (ret == null || ret.equals(type)) {
2167             // no localization for this type. try combining key/type separately
2168             String displayType = type;
2169             switch (key) {
2170             case "cu":
2171                 displayType = lr.getCurrencyName(type.toLowerCase(Locale.ROOT));
2172                 break;
2173             case "rg":
2174                 if (type != null &&
2175                     // UN M.49 code should not be allowed here
2176                     type.matches("^[a-zA-Z]{2}[zZ]{4}$")) {
2177                         displayType = lr.getLocaleName(type.substring(0, 2).toUpperCase(Locale.ROOT));
2178                 }
2179                 break;
2180             case "tz":
2181                 displayType = TimeZoneNameUtility.retrieveGenericDisplayName(
2182                     TimeZoneNameUtility.convertLDMLShortID(type).orElse(type),
2183                     TimeZone.LONG, inLocale);
2184                 break;
2185             }
2186             ret = MessageFormat.format(lr.getLocaleName("ListKeyTypePattern"),
2187                 getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY),
2188                 Optional.ofNullable(displayType).orElse(type));
2189         }
2190 
2191         return ret;
2192     }
2193 
2194     /**
2195      * Format a list using given pattern strings.
2196      * If either of the patterns is null, then a the list is
2197      * formatted by concatenation with the delimiter ','.
2198      * @param stringList the list of strings to be formatted.

2199      * and formatting them into a list.
2200      * @param pattern should take 2 arguments for reduction

2201      * @return a string representing the list.
2202      */
2203     private static String formatList(String[] stringList, String pattern) {
2204         // If we have no list patterns, compose the list in a simple,
2205         // non-localized way.
2206         if (pattern == null) {
2207             return Arrays.stream(stringList).collect(Collectors.joining(","));




2208         }
2209 
2210         switch (stringList.length) {
2211             case 0:
2212                 return "";
2213             case 1:
2214                 return stringList[0];
2215             default:
2216                 return Arrays.stream(stringList).reduce("",
2217                     (s1, s2) -> {
2218                         if (s1.equals("")) {
2219                             return s2;
2220                         }
2221                         if (s2.equals("")) {
2222                             return s1;
2223                         }
2224                         return MessageFormat.format(pattern, s1, s2);
2225                     });




2226         }
























2227     }
2228 
2229     // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
2230     // avoid its class loading.
2231     private static boolean isUnicodeExtensionKey(String s) {
2232         // 2alphanum
2233         return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
2234     }
2235 
2236     /**
2237      * @serialField language    String
2238      *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
2239      * @serialField country     String
2240      *      country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
2241      * @serialField variant     String
2242      *      variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>)
2243      * @serialField hashcode    int
2244      *      deprecated, for forward compatibility only
2245      * @serialField script      String
2246      *      script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>)


2363                 && "TH".equals(variant)) {
2364             // th_TH_TH -> u-nu-thai (numbersystem = thai)
2365             extensions = LocaleExtensions.NUMBER_THAI;
2366         }
2367         return extensions;
2368     }
2369 
2370     /**
2371      * Obtains a localized locale names from a LocaleNameProvider
2372      * implementation.
2373      */
2374     private static class LocaleNameGetter
2375         implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
2376         private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
2377 
2378         @Override
2379         public String getObject(LocaleNameProvider localeNameProvider,
2380                                 Locale locale,
2381                                 String key,
2382                                 Object... params) {
2383             assert params.length == 3;
2384             int type = (Integer)params[0];
2385             String code = (String)params[1];
2386             String cat = (String)params[2];
2387 
2388             switch(type) {
2389             case DISPLAY_LANGUAGE:
2390                 return localeNameProvider.getDisplayLanguage(code, locale);
2391             case DISPLAY_COUNTRY:
2392                 return localeNameProvider.getDisplayCountry(code, locale);
2393             case DISPLAY_VARIANT:
2394                 return localeNameProvider.getDisplayVariant(code, locale);
2395             case DISPLAY_SCRIPT:
2396                 return localeNameProvider.getDisplayScript(code, locale);
2397             case DISPLAY_UEXT_KEY:
2398                 return localeNameProvider.getDisplayUnicodeExtensionKey(code, locale);
2399             case DISPLAY_UEXT_TYPE:
2400                 return localeNameProvider.getDisplayUnicodeExtensionType(code, cat, locale);
2401             default:
2402                 assert false; // shouldn't happen
2403             }
2404 
2405             return null;
2406         }
2407     }
2408 
2409     /**
2410      * Enum for locale categories.  These locale categories are used to get/set
2411      * the default locale for the specific functionality represented by the
2412      * category.
2413      *
2414      * @see #getDefault(Locale.Category)
2415      * @see #setDefault(Locale.Category, Locale)
2416      * @since 1.7
2417      */
2418     public enum Category {
2419 
2420         /**
2421          * Category used to represent the default locale for
2422          * displaying user interfaces.
2423          */
2424         DISPLAY("user.language.display",
2425                 "user.script.display",
2426                 "user.country.display",
2427                 "user.variant.display",
2428                 "user.extensions.display"),
2429 
2430         /**
2431          * Category used to represent the default locale for
2432          * formatting dates, numbers, and/or currencies.
2433          */
2434         FORMAT("user.language.format",
2435                "user.script.format",
2436                "user.country.format",
2437                "user.variant.format",
2438                "user.extensions.format");
2439 
2440         Category(String languageKey, String scriptKey, String countryKey,
2441                 String variantKey, String extensionsKey) {
2442             this.languageKey = languageKey;
2443             this.scriptKey = scriptKey;
2444             this.countryKey = countryKey;
2445             this.variantKey = variantKey;
2446             this.extensionsKey = extensionsKey;
2447         }
2448 
2449         final String languageKey;
2450         final String scriptKey;
2451         final String countryKey;
2452         final String variantKey;
2453         final String extensionsKey;
2454     }
2455 
2456     /**
2457      * <code>Builder</code> is used to build instances of <code>Locale</code>
2458      * from values configured by the setters.  Unlike the <code>Locale</code>
2459      * constructors, the <code>Builder</code> checks if a value configured by a
2460      * setter satisfies the syntax requirements defined by the <code>Locale</code>
2461      * class.  A <code>Locale</code> object created by a <code>Builder</code> is
2462      * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
2463      * without losing information.
2464      *
2465      * <p><b>Note:</b> The <code>Locale</code> class does not provide any
2466      * syntactic restrictions on variant, while BCP 47 requires each variant
2467      * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
2468      * alphanumerics.  The method <code>setVariant</code> throws
2469      * <code>IllformedLocaleException</code> for a variant that does not satisfy
2470      * this restriction. If it is necessary to support such a variant, use a
2471      * Locale constructor.  However, keep in mind that a <code>Locale</code>
2472      * object created this way might lose the variant information when
2473      * transformed to a BCP 47 language tag.


< prev index next >