String.format needs Locale jdk7-b147
authorJaroslav Tulach <jtulach@netbeans.org>
Sat, 28 Sep 2013 02:18:42 +0200
branchjdk7-b147
changeset 13181af7f8903b62
parent 1314 e3db9cca817b
child 1319 be64f0e582bc
child 1334 588d5bf7a560
String.format needs Locale
rt/emul/compact/src/main/java/java/util/Locale.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/compact/src/main/java/java/util/Locale.java	Sat Sep 28 02:18:42 2013 +0200
     1.3 @@ -0,0 +1,2560 @@
     1.4 +/*
     1.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +/*
    1.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
    1.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
    1.32 + *
    1.33 + * The original version of this source code and documentation
    1.34 + * is copyrighted and owned by Taligent, Inc., a wholly-owned
    1.35 + * subsidiary of IBM. These materials are provided under terms
    1.36 + * of a License Agreement between Taligent and Sun. This technology
    1.37 + * is protected by multiple US and International patents.
    1.38 + *
    1.39 + * This notice and attribution to Taligent may not be removed.
    1.40 + * Taligent is a registered trademark of Taligent, Inc.
    1.41 + *
    1.42 + */
    1.43 +
    1.44 +package java.util;
    1.45 +
    1.46 +import java.io.IOException;
    1.47 +import java.io.ObjectInputStream;
    1.48 +import java.io.ObjectOutputStream;
    1.49 +import java.io.ObjectStreamField;
    1.50 +import java.io.Serializable;
    1.51 +import java.security.AccessController;
    1.52 +import java.text.MessageFormat;
    1.53 +import java.util.spi.LocaleNameProvider;
    1.54 +
    1.55 +import sun.security.action.GetPropertyAction;
    1.56 +import sun.util.LocaleServiceProviderPool;
    1.57 +import sun.util.locale.BaseLocale;
    1.58 +import sun.util.locale.InternalLocaleBuilder;
    1.59 +import sun.util.locale.LanguageTag;
    1.60 +import sun.util.locale.LocaleExtensions;
    1.61 +import sun.util.locale.LocaleObjectCache;
    1.62 +import sun.util.locale.LocaleSyntaxException;
    1.63 +import sun.util.locale.LocaleUtils;
    1.64 +import sun.util.locale.ParseStatus;
    1.65 +import sun.util.locale.UnicodeLocaleExtension;
    1.66 +import sun.util.resources.LocaleData;
    1.67 +import sun.util.resources.OpenListResourceBundle;
    1.68 +
    1.69 +/**
    1.70 + * A <code>Locale</code> object represents a specific geographical, political,
    1.71 + * or cultural region. An operation that requires a <code>Locale</code> to perform
    1.72 + * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
    1.73 + * to tailor information for the user. For example, displaying a number
    1.74 + * is a locale-sensitive operation&mdash; the number should be formatted
    1.75 + * according to the customs and conventions of the user's native country,
    1.76 + * region, or culture.
    1.77 + *
    1.78 + * <p> The <code>Locale</code> class implements identifiers
    1.79 + * interchangeable with BCP 47 (IETF BCP 47, "Tags for Identifying
    1.80 + * Languages"), with support for the LDML (UTS#35, "Unicode Locale
    1.81 + * Data Markup Language") BCP 47-compatible extensions for locale data
    1.82 + * exchange.
    1.83 + *
    1.84 + * <p> A <code>Locale</code> object logically consists of the fields
    1.85 + * described below.
    1.86 + *
    1.87 + * <dl>
    1.88 + *   <dt><a name="def_language"/><b>language</b></dt>
    1.89 + *
    1.90 + *   <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
    1.91 + *   language subtags up to 8 alpha letters (for future enhancements).
    1.92 + *   When a language has both an alpha-2 code and an alpha-3 code, the
    1.93 + *   alpha-2 code must be used.  You can find a full list of valid
    1.94 + *   language codes in the IANA Language Subtag Registry (search for
    1.95 + *   "Type: language").  The language field is case insensitive, but
    1.96 + *   <code>Locale</code> always canonicalizes to lower case.</dd><br>
    1.97 + *
    1.98 + *   <dd>Well-formed language values have the form
    1.99 + *   <code>[a-zA-Z]{2,8}</code>.  Note that this is not the the full
   1.100 + *   BCP47 language production, since it excludes extlang.  They are
   1.101 + *   not needed since modern three-letter language codes replace
   1.102 + *   them.</dd><br>
   1.103 + *
   1.104 + *   <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
   1.105 + *
   1.106 + *   <dt><a name="def_script"/><b>script</b></dt>
   1.107 + *
   1.108 + *   <dd>ISO 15924 alpha-4 script code.  You can find a full list of
   1.109 + *   valid script codes in the IANA Language Subtag Registry (search
   1.110 + *   for "Type: script").  The script field is case insensitive, but
   1.111 + *   <code>Locale</code> always canonicalizes to title case (the first
   1.112 + *   letter is upper case and the rest of the letters are lower
   1.113 + *   case).</dd><br>
   1.114 + *
   1.115 + *   <dd>Well-formed script values have the form
   1.116 + *   <code>[a-zA-Z]{4}</code></dd><br>
   1.117 + *
   1.118 + *   <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
   1.119 + *
   1.120 + *   <dt><a name="def_region"/><b>country (region)</b></dt>
   1.121 + *
   1.122 + *   <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
   1.123 + *   You can find a full list of valid country and region codes in the
   1.124 + *   IANA Language Subtag Registry (search for "Type: region").  The
   1.125 + *   country (region) field is case insensitive, but
   1.126 + *   <code>Locale</code> always canonicalizes to upper case.</dd><br>
   1.127 + *
   1.128 + *   <dd>Well-formed country/region values have
   1.129 + *   the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd><br>
   1.130 + *
   1.131 + *   <dd>Example: "US" (United States), "FR" (France), "029"
   1.132 + *   (Caribbean)</dd><br>
   1.133 + *
   1.134 + *   <dt><a name="def_variant"/><b>variant</b></dt>
   1.135 + *
   1.136 + *   <dd>Any arbitrary value used to indicate a variation of a
   1.137 + *   <code>Locale</code>.  Where there are two or more variant values
   1.138 + *   each indicating its own semantics, these values should be ordered
   1.139 + *   by importance, with most important first, separated by
   1.140 + *   underscore('_').  The variant field is case sensitive.</dd><br>
   1.141 + *
   1.142 + *   <dd>Note: IETF BCP 47 places syntactic restrictions on variant
   1.143 + *   subtags.  Also BCP 47 subtags are strictly used to indicate
   1.144 + *   additional variations that define a language or its dialects that
   1.145 + *   are not covered by any combinations of language, script and
   1.146 + *   region subtags.  You can find a full list of valid variant codes
   1.147 + *   in the IANA Language Subtag Registry (search for "Type: variant").
   1.148 + *
   1.149 + *   <p>However, the variant field in <code>Locale</code> has
   1.150 + *   historically been used for any kind of variation, not just
   1.151 + *   language variations.  For example, some supported variants
   1.152 + *   available in Java SE Runtime Environments indicate alternative
   1.153 + *   cultural behaviors such as calendar type or number script.  In
   1.154 + *   BCP 47 this kind of information, which does not identify the
   1.155 + *   language, is supported by extension subtags or private use
   1.156 + *   subtags.</dd><br>
   1.157 + *
   1.158 + *   <dd>Well-formed variant values have the form <code>SUBTAG
   1.159 + *   (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
   1.160 + *   [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
   1.161 + *   uses hyphen ('-') as a delimiter, this is more lenient).</dd><br>
   1.162 + *
   1.163 + *   <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
   1.164 + *
   1.165 + *   <dt><a name="def_extensions"/><b>extensions</b></dt>
   1.166 + *
   1.167 + *   <dd>A map from single character keys to string values, indicating
   1.168 + *   extensions apart from language identification.  The extensions in
   1.169 + *   <code>Locale</code> implement the semantics and syntax of BCP 47
   1.170 + *   extension subtags and private use subtags. The extensions are
   1.171 + *   case insensitive, but <code>Locale</code> canonicalizes all
   1.172 + *   extension keys and values to lower case. Note that extensions
   1.173 + *   cannot have empty values.</dd><br>
   1.174 + *
   1.175 + *   <dd>Well-formed keys are single characters from the set
   1.176 + *   <code>[0-9a-zA-Z]</code>.  Well-formed values have the form
   1.177 + *   <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
   1.178 + *   <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
   1.179 + *   <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
   1.180 + *   single-character subtags).</dd><br>
   1.181 + *
   1.182 + *   <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
   1.183 + *   key="x"/value="java-1-7"</dd>
   1.184 + * </dl>
   1.185 + *
   1.186 + * <b>Note:</b> Although BCP 47 requires field values to be registered
   1.187 + * in the IANA Language Subtag Registry, the <code>Locale</code> class
   1.188 + * does not provide any validation features.  The <code>Builder</code>
   1.189 + * only checks if an individual field satisfies the syntactic
   1.190 + * requirement (is well-formed), but does not validate the value
   1.191 + * itself.  See {@link Builder} for details.
   1.192 + *
   1.193 + * <h4><a name="def_locale_extension">Unicode locale/language extension</h4>
   1.194 + *
   1.195 + * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
   1.196 + * attributes and keywords to override or refine the default behavior
   1.197 + * associated with a locale.  A keyword is represented by a pair of
   1.198 + * key and type.  For example, "nu-thai" indicates that Thai local
   1.199 + * digits (value:"thai") should be used for formatting numbers
   1.200 + * (key:"nu").
   1.201 + *
   1.202 + * <p>The keywords are mapped to a BCP 47 extension value using the
   1.203 + * extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}).  The above
   1.204 + * example, "nu-thai", becomes the extension "u-nu-thai".code
   1.205 + *
   1.206 + * <p>Thus, when a <code>Locale</code> object contains Unicode locale
   1.207 + * attributes and keywords,
   1.208 + * <code>getExtension(UNICODE_LOCALE_EXTENSION)</code> will return a
   1.209 + * String representing this information, for example, "nu-thai".  The
   1.210 + * <code>Locale</code> class also provides {@link
   1.211 + * #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and
   1.212 + * {@link #getUnicodeLocaleType} which allow you to access Unicode
   1.213 + * locale attributes and key/type pairs directly.  When represented as
   1.214 + * a string, the Unicode Locale Extension lists attributes
   1.215 + * alphabetically, followed by key/type sequences with keys listed
   1.216 + * alphabetically (the order of subtags comprising a key's type is
   1.217 + * fixed when the type is defined)
   1.218 + *
   1.219 + * <p>A well-formed locale key has the form
   1.220 + * <code>[0-9a-zA-Z]{2}</code>.  A well-formed locale type has the
   1.221 + * form <code>"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*</code> (it
   1.222 + * can be empty, or a series of subtags 3-8 alphanums in length).  A
   1.223 + * well-formed locale attribute has the form
   1.224 + * <code>[0-9a-zA-Z]{3,8}</code> (it is a single subtag with the same
   1.225 + * form as a locale type subtag).
   1.226 + *
   1.227 + * <p>The Unicode locale extension specifies optional behavior in
   1.228 + * locale-sensitive services.  Although the LDML specification defines
   1.229 + * various keys and values, actual locale-sensitive service
   1.230 + * implementations in a Java Runtime Environment might not support any
   1.231 + * particular Unicode locale attributes or key/type pairs.
   1.232 + *
   1.233 + * <h4>Creating a Locale</h4>
   1.234 + *
   1.235 + * <p>There are several different ways to create a <code>Locale</code>
   1.236 + * object.
   1.237 + *
   1.238 + * <h5>Builder</h5>
   1.239 + *
   1.240 + * <p>Using {@link Builder} you can construct a <code>Locale</code> object
   1.241 + * that conforms to BCP 47 syntax.
   1.242 + *
   1.243 + * <h5>Constructors</h5>
   1.244 + *
   1.245 + * <p>The <code>Locale</code> class provides three constructors:
   1.246 + * <blockquote>
   1.247 + * <pre>
   1.248 + *     {@link #Locale(String language)}
   1.249 + *     {@link #Locale(String language, String country)}
   1.250 + *     {@link #Locale(String language, String country, String variant)}
   1.251 + * </pre>
   1.252 + * </blockquote>
   1.253 + * These constructors allow you to create a <code>Locale</code> object
   1.254 + * with language, country and variant, but you cannot specify
   1.255 + * script or extensions.
   1.256 + *
   1.257 + * <h5>Factory Methods</h5>
   1.258 + *
   1.259 + * <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
   1.260 + * object for a well-formed BCP 47 language tag.
   1.261 + *
   1.262 + * <h5>Locale Constants</h5>
   1.263 + *
   1.264 + * <p>The <code>Locale</code> class provides a number of convenient constants
   1.265 + * that you can use to create <code>Locale</code> objects for commonly used
   1.266 + * locales. For example, the following creates a <code>Locale</code> object
   1.267 + * for the United States:
   1.268 + * <blockquote>
   1.269 + * <pre>
   1.270 + *     Locale.US
   1.271 + * </pre>
   1.272 + * </blockquote>
   1.273 + *
   1.274 + * <h4>Use of Locale</h4>
   1.275 + *
   1.276 + * <p>Once you've created a <code>Locale</code> you can query it for information
   1.277 + * about itself. Use <code>getCountry</code> to get the country (or region)
   1.278 + * code and <code>getLanguage</code> to get the language code.
   1.279 + * You can use <code>getDisplayCountry</code> to get the
   1.280 + * name of the country suitable for displaying to the user. Similarly,
   1.281 + * you can use <code>getDisplayLanguage</code> to get the name of
   1.282 + * the language suitable for displaying to the user. Interestingly,
   1.283 + * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
   1.284 + * and have two versions: one that uses the default locale and one
   1.285 + * that uses the locale specified as an argument.
   1.286 + *
   1.287 + * <p>The Java Platform provides a number of classes that perform locale-sensitive
   1.288 + * operations. For example, the <code>NumberFormat</code> class formats
   1.289 + * numbers, currency, and percentages in a locale-sensitive manner. Classes
   1.290 + * such as <code>NumberFormat</code> have several convenience methods
   1.291 + * for creating a default object of that type. For example, the
   1.292 + * <code>NumberFormat</code> class provides these three convenience methods
   1.293 + * for creating a default <code>NumberFormat</code> object:
   1.294 + * <blockquote>
   1.295 + * <pre>
   1.296 + *     NumberFormat.getInstance()
   1.297 + *     NumberFormat.getCurrencyInstance()
   1.298 + *     NumberFormat.getPercentInstance()
   1.299 + * </pre>
   1.300 + * </blockquote>
   1.301 + * Each of these methods has two variants; one with an explicit locale
   1.302 + * and one without; the latter uses the default locale:
   1.303 + * <blockquote>
   1.304 + * <pre>
   1.305 + *     NumberFormat.getInstance(myLocale)
   1.306 + *     NumberFormat.getCurrencyInstance(myLocale)
   1.307 + *     NumberFormat.getPercentInstance(myLocale)
   1.308 + * </pre>
   1.309 + * </blockquote>
   1.310 + * A <code>Locale</code> is the mechanism for identifying the kind of object
   1.311 + * (<code>NumberFormat</code>) that you would like to get. The locale is
   1.312 + * <STRONG>just</STRONG> a mechanism for identifying objects,
   1.313 + * <STRONG>not</STRONG> a container for the objects themselves.
   1.314 + *
   1.315 + * <h4>Compatibility</h4>
   1.316 + *
   1.317 + * <p>In order to maintain compatibility with existing usage, Locale's
   1.318 + * constructors retain their behavior prior to the Java Runtime
   1.319 + * Environment version 1.7.  The same is largely true for the
   1.320 + * <code>toString</code> method. Thus Locale objects can continue to
   1.321 + * be used as they were. In particular, clients who parse the output
   1.322 + * of toString into language, country, and variant fields can continue
   1.323 + * to do so (although this is strongly discouraged), although the
   1.324 + * variant field will have additional information in it if script or
   1.325 + * extensions are present.
   1.326 + *
   1.327 + * <p>In addition, BCP 47 imposes syntax restrictions that are not
   1.328 + * imposed by Locale's constructors. This means that conversions
   1.329 + * between some Locales and BCP 47 language tags cannot be made without
   1.330 + * losing information. Thus <code>toLanguageTag</code> cannot
   1.331 + * represent the state of locales whose language, country, or variant
   1.332 + * do not conform to BCP 47.
   1.333 + *
   1.334 + * <p>Because of these issues, it is recommended that clients migrate
   1.335 + * away from constructing non-conforming locales and use the
   1.336 + * <code>forLanguageTag</code> and <code>Locale.Builder</code> APIs instead.
   1.337 + * Clients desiring a string representation of the complete locale can
   1.338 + * then always rely on <code>toLanguageTag</code> for this purpose.
   1.339 + *
   1.340 + * <h5><a name="special_cases_constructor"/>Special cases</h5>
   1.341 + *
   1.342 + * <p>For compatibility reasons, two
   1.343 + * non-conforming locales are treated as special cases.  These are
   1.344 + * <b><tt>ja_JP_JP</tt></b> and <b><tt>th_TH_TH</tt></b>. These are ill-formed
   1.345 + * in BCP 47 since the variants are too short. To ease migration to BCP 47,
   1.346 + * these are treated specially during construction.  These two cases (and only
   1.347 + * these) cause a constructor to generate an extension, all other values behave
   1.348 + * exactly as they did prior to Java 7.
   1.349 + *
   1.350 + * <p>Java has used <tt>ja_JP_JP</tt> to represent Japanese as used in
   1.351 + * Japan together with the Japanese Imperial calendar. This is now
   1.352 + * representable using a Unicode locale extension, by specifying the
   1.353 + * Unicode locale key <tt>ca</tt> (for "calendar") and type
   1.354 + * <tt>japanese</tt>. When the Locale constructor is called with the
   1.355 + * arguments "ja", "JP", "JP", the extension "u-ca-japanese" is
   1.356 + * automatically added.
   1.357 + *
   1.358 + * <p>Java has used <tt>th_TH_TH</tt> to represent Thai as used in
   1.359 + * Thailand together with Thai digits. This is also now representable using
   1.360 + * a Unicode locale extension, by specifying the Unicode locale key
   1.361 + * <tt>nu</tt> (for "number") and value <tt>thai</tt>. When the Locale
   1.362 + * constructor is called with the arguments "th", "TH", "TH", the
   1.363 + * extension "u-nu-thai" is automatically added.
   1.364 + *
   1.365 + * <h5>Serialization</h5>
   1.366 + *
   1.367 + * <p>During serialization, writeObject writes all fields to the output
   1.368 + * stream, including extensions.
   1.369 + *
   1.370 + * <p>During deserialization, readResolve adds extensions as described
   1.371 + * in <a href="#special_cases_constructor">Special Cases</a>, only
   1.372 + * for the two cases th_TH_TH and ja_JP_JP.
   1.373 + *
   1.374 + * <h5>Legacy language codes</h5>
   1.375 + *
   1.376 + * <p>Locale's constructor has always converted three language codes to
   1.377 + * their earlier, obsoleted forms: <tt>he</tt> maps to <tt>iw</tt>,
   1.378 + * <tt>yi</tt> maps to <tt>ji</tt>, and <tt>id</tt> maps to
   1.379 + * <tt>in</tt>.  This continues to be the case, in order to not break
   1.380 + * backwards compatibility.
   1.381 + *
   1.382 + * <p>The APIs added in 1.7 map between the old and new language codes,
   1.383 + * maintaining the old codes internal to Locale (so that
   1.384 + * <code>getLanguage</code> and <code>toString</code> reflect the old
   1.385 + * code), but using the new codes in the BCP 47 language tag APIs (so
   1.386 + * that <code>toLanguageTag</code> reflects the new one). This
   1.387 + * preserves the equivalence between Locales no matter which code or
   1.388 + * API is used to construct them. Java's default resource bundle
   1.389 + * lookup mechanism also implements this mapping, so that resources
   1.390 + * can be named using either convention, see {@link ResourceBundle.Control}.
   1.391 + *
   1.392 + * <h5>Three-letter language/country(region) codes</h5>
   1.393 + *
   1.394 + * <p>The Locale constructors have always specified that the language
   1.395 + * and the country param be two characters in length, although in
   1.396 + * practice they have accepted any length.  The specification has now
   1.397 + * been relaxed to allow language codes of two to eight characters and
   1.398 + * country (region) codes of two to three characters, and in
   1.399 + * particular, three-letter language codes and three-digit region
   1.400 + * codes as specified in the IANA Language Subtag Registry.  For
   1.401 + * compatibility, the implementation still does not impose a length
   1.402 + * constraint.
   1.403 + *
   1.404 + * @see Builder
   1.405 + * @see ResourceBundle
   1.406 + * @see java.text.Format
   1.407 + * @see java.text.NumberFormat
   1.408 + * @see java.text.Collator
   1.409 + * @author Mark Davis
   1.410 + * @since 1.1
   1.411 + */
   1.412 +public final class Locale implements Cloneable, Serializable {
   1.413 +
   1.414 +    static private final  Cache LOCALECACHE = new Cache();
   1.415 +
   1.416 +    /** Useful constant for language.
   1.417 +     */
   1.418 +    static public final Locale ENGLISH = createConstant("en", "");
   1.419 +
   1.420 +    /** Useful constant for language.
   1.421 +     */
   1.422 +    static public final Locale FRENCH = createConstant("fr", "");
   1.423 +
   1.424 +    /** Useful constant for language.
   1.425 +     */
   1.426 +    static public final Locale GERMAN = createConstant("de", "");
   1.427 +
   1.428 +    /** Useful constant for language.
   1.429 +     */
   1.430 +    static public final Locale ITALIAN = createConstant("it", "");
   1.431 +
   1.432 +    /** Useful constant for language.
   1.433 +     */
   1.434 +    static public final Locale JAPANESE = createConstant("ja", "");
   1.435 +
   1.436 +    /** Useful constant for language.
   1.437 +     */
   1.438 +    static public final Locale KOREAN = createConstant("ko", "");
   1.439 +
   1.440 +    /** Useful constant for language.
   1.441 +     */
   1.442 +    static public final Locale CHINESE = createConstant("zh", "");
   1.443 +
   1.444 +    /** Useful constant for language.
   1.445 +     */
   1.446 +    static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
   1.447 +
   1.448 +    /** Useful constant for language.
   1.449 +     */
   1.450 +    static public final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
   1.451 +
   1.452 +    /** Useful constant for country.
   1.453 +     */
   1.454 +    static public final Locale FRANCE = createConstant("fr", "FR");
   1.455 +
   1.456 +    /** Useful constant for country.
   1.457 +     */
   1.458 +    static public final Locale GERMANY = createConstant("de", "DE");
   1.459 +
   1.460 +    /** Useful constant for country.
   1.461 +     */
   1.462 +    static public final Locale ITALY = createConstant("it", "IT");
   1.463 +
   1.464 +    /** Useful constant for country.
   1.465 +     */
   1.466 +    static public final Locale JAPAN = createConstant("ja", "JP");
   1.467 +
   1.468 +    /** Useful constant for country.
   1.469 +     */
   1.470 +    static public final Locale KOREA = createConstant("ko", "KR");
   1.471 +
   1.472 +    /** Useful constant for country.
   1.473 +     */
   1.474 +    static public final Locale CHINA = SIMPLIFIED_CHINESE;
   1.475 +
   1.476 +    /** Useful constant for country.
   1.477 +     */
   1.478 +    static public final Locale PRC = SIMPLIFIED_CHINESE;
   1.479 +
   1.480 +    /** Useful constant for country.
   1.481 +     */
   1.482 +    static public final Locale TAIWAN = TRADITIONAL_CHINESE;
   1.483 +
   1.484 +    /** Useful constant for country.
   1.485 +     */
   1.486 +    static public final Locale UK = createConstant("en", "GB");
   1.487 +
   1.488 +    /** Useful constant for country.
   1.489 +     */
   1.490 +    static public final Locale US = createConstant("en", "US");
   1.491 +
   1.492 +    /** Useful constant for country.
   1.493 +     */
   1.494 +    static public final Locale CANADA = createConstant("en", "CA");
   1.495 +
   1.496 +    /** Useful constant for country.
   1.497 +     */
   1.498 +    static public final Locale CANADA_FRENCH = createConstant("fr", "CA");
   1.499 +
   1.500 +    /**
   1.501 +     * Useful constant for the root locale.  The root locale is the locale whose
   1.502 +     * language, country, and variant are empty ("") strings.  This is regarded
   1.503 +     * as the base locale of all locales, and is used as the language/country
   1.504 +     * neutral locale for the locale sensitive operations.
   1.505 +     *
   1.506 +     * @since 1.6
   1.507 +     */
   1.508 +    static public final Locale ROOT = createConstant("", "");
   1.509 +
   1.510 +    /**
   1.511 +     * The key for the private use extension ('x').
   1.512 +     *
   1.513 +     * @see #getExtension(char)
   1.514 +     * @see Builder#setExtension(char, String)
   1.515 +     * @since 1.7
   1.516 +     */
   1.517 +    static public final char PRIVATE_USE_EXTENSION = 'x';
   1.518 +
   1.519 +    /**
   1.520 +     * The key for Unicode locale extension ('u').
   1.521 +     *
   1.522 +     * @see #getExtension(char)
   1.523 +     * @see Builder#setExtension(char, String)
   1.524 +     * @since 1.7
   1.525 +     */
   1.526 +    static public final char UNICODE_LOCALE_EXTENSION = 'u';
   1.527 +
   1.528 +    /** serialization ID
   1.529 +     */
   1.530 +    static final long serialVersionUID = 9149081749638150636L;
   1.531 +
   1.532 +    /**
   1.533 +     * Display types for retrieving localized names from the name providers.
   1.534 +     */
   1.535 +    private static final int DISPLAY_LANGUAGE = 0;
   1.536 +    private static final int DISPLAY_COUNTRY  = 1;
   1.537 +    private static final int DISPLAY_VARIANT  = 2;
   1.538 +    private static final int DISPLAY_SCRIPT   = 3;
   1.539 +
   1.540 +    /**
   1.541 +     * Private constructor used by getInstance method
   1.542 +     */
   1.543 +    private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
   1.544 +        this.baseLocale = baseLocale;
   1.545 +        this.localeExtensions = extensions;
   1.546 +    }
   1.547 +
   1.548 +    /**
   1.549 +     * Construct a locale from language, country and variant.
   1.550 +     * This constructor normalizes the language value to lowercase and
   1.551 +     * the country value to uppercase.
   1.552 +     * <p>
   1.553 +     * <b>Note:</b>
   1.554 +     * <ul>
   1.555 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
   1.556 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
   1.557 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
   1.558 +     * API on Locale will return only the OLD codes.
   1.559 +     * <li>For backward compatibility reasons, this constructor does not make
   1.560 +     * any syntactic checks on the input.
   1.561 +     * <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
   1.562 +     * see <a href="#special_cases_constructor">Special Cases</a> for more information.
   1.563 +     * </ul>
   1.564 +     *
   1.565 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
   1.566 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
   1.567 +     * valid language values.
   1.568 +     * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
   1.569 +     * See the <code>Locale</code> class description about valid country values.
   1.570 +     * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>.
   1.571 +     * See the <code>Locale</code> class description for the details.
   1.572 +     * @exception NullPointerException thrown if any argument is null.
   1.573 +     */
   1.574 +    public Locale(String language, String country, String variant) {
   1.575 +        if (language== null || country == null || variant == null) {
   1.576 +            throw new NullPointerException();
   1.577 +        }
   1.578 +        baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
   1.579 +        localeExtensions = getCompatibilityExtensions(language, "", country, variant);
   1.580 +    }
   1.581 +
   1.582 +    /**
   1.583 +     * Construct a locale from language and country.
   1.584 +     * This constructor normalizes the language value to lowercase and
   1.585 +     * the country value to uppercase.
   1.586 +     * <p>
   1.587 +     * <b>Note:</b>
   1.588 +     * <ul>
   1.589 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
   1.590 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
   1.591 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
   1.592 +     * API on Locale will return only the OLD codes.
   1.593 +     * <li>For backward compatibility reasons, this constructor does not make
   1.594 +     * any syntactic checks on the input.
   1.595 +     * </ul>
   1.596 +     *
   1.597 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
   1.598 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
   1.599 +     * valid language values.
   1.600 +     * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
   1.601 +     * See the <code>Locale</code> class description about valid country values.
   1.602 +     * @exception NullPointerException thrown if either argument is null.
   1.603 +     */
   1.604 +    public Locale(String language, String country) {
   1.605 +        this(language, country, "");
   1.606 +    }
   1.607 +
   1.608 +    /**
   1.609 +     * Construct a locale from a language code.
   1.610 +     * This constructor normalizes the language value to lowercase.
   1.611 +     * <p>
   1.612 +     * <b>Note:</b>
   1.613 +     * <ul>
   1.614 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
   1.615 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
   1.616 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
   1.617 +     * API on Locale will return only the OLD codes.
   1.618 +     * <li>For backward compatibility reasons, this constructor does not make
   1.619 +     * any syntactic checks on the input.
   1.620 +     * </ul>
   1.621 +     *
   1.622 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
   1.623 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
   1.624 +     * valid language values.
   1.625 +     * @exception NullPointerException thrown if argument is null.
   1.626 +     * @since 1.4
   1.627 +     */
   1.628 +    public Locale(String language) {
   1.629 +        this(language, "", "");
   1.630 +    }
   1.631 +
   1.632 +    /**
   1.633 +     * This method must be called only for creating the Locale.*
   1.634 +     * constants due to making shortcuts.
   1.635 +     */
   1.636 +    private static Locale createConstant(String lang, String country) {
   1.637 +        BaseLocale base = BaseLocale.createInstance(lang, country);
   1.638 +        return getInstance(base, null);
   1.639 +    }
   1.640 +
   1.641 +    /**
   1.642 +     * Returns a <code>Locale</code> constructed from the given
   1.643 +     * <code>language</code>, <code>country</code> and
   1.644 +     * <code>variant</code>. If the same <code>Locale</code> instance
   1.645 +     * is available in the cache, then that instance is
   1.646 +     * returned. Otherwise, a new <code>Locale</code> instance is
   1.647 +     * created and cached.
   1.648 +     *
   1.649 +     * @param language lowercase 2 to 8 language code.
   1.650 +     * @param country uppercase two-letter ISO-3166 code and numric-3 UN M.49 area code.
   1.651 +     * @param variant vendor and browser specific code. See class description.
   1.652 +     * @return the <code>Locale</code> instance requested
   1.653 +     * @exception NullPointerException if any argument is null.
   1.654 +     */
   1.655 +    static Locale getInstance(String language, String country, String variant) {
   1.656 +        return getInstance(language, "", country, variant, null);
   1.657 +    }
   1.658 +
   1.659 +    static Locale getInstance(String language, String script, String country,
   1.660 +                                      String variant, LocaleExtensions extensions) {
   1.661 +        if (language== null || script == null || country == null || variant == null) {
   1.662 +            throw new NullPointerException();
   1.663 +        }
   1.664 +
   1.665 +        if (extensions == null) {
   1.666 +            extensions = getCompatibilityExtensions(language, script, country, variant);
   1.667 +        }
   1.668 +
   1.669 +        BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
   1.670 +        return getInstance(baseloc, extensions);
   1.671 +    }
   1.672 +
   1.673 +    static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
   1.674 +        LocaleKey key = new LocaleKey(baseloc, extensions);
   1.675 +        return LOCALECACHE.get(key);
   1.676 +    }
   1.677 +
   1.678 +    private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
   1.679 +        private Cache() {
   1.680 +        }
   1.681 +
   1.682 +        @Override
   1.683 +        protected Locale createObject(LocaleKey key) {
   1.684 +            return new Locale(key.base, key.exts);
   1.685 +        }
   1.686 +    }
   1.687 +
   1.688 +    private static final class LocaleKey {
   1.689 +        private final BaseLocale base;
   1.690 +        private final LocaleExtensions exts;
   1.691 +        private final int hash;
   1.692 +
   1.693 +        private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) {
   1.694 +            base = baseLocale;
   1.695 +            exts = extensions;
   1.696 +
   1.697 +            // Calculate the hash value here because it's always used.
   1.698 +            int h = base.hashCode();
   1.699 +            if (exts != null) {
   1.700 +                h ^= exts.hashCode();
   1.701 +            }
   1.702 +            hash = h;
   1.703 +        }
   1.704 +
   1.705 +        @Override
   1.706 +        public boolean equals(Object obj) {
   1.707 +            if (this == obj) {
   1.708 +                return true;
   1.709 +            }
   1.710 +            if (!(obj instanceof LocaleKey)) {
   1.711 +                return false;
   1.712 +            }
   1.713 +            LocaleKey other = (LocaleKey)obj;
   1.714 +            if (hash != other.hash || !base.equals(other.base)) {
   1.715 +                return false;
   1.716 +            }
   1.717 +            if (exts == null) {
   1.718 +                return other.exts == null;
   1.719 +            }
   1.720 +            return exts.equals(other.exts);
   1.721 +        }
   1.722 +
   1.723 +        @Override
   1.724 +        public int hashCode() {
   1.725 +            return hash;
   1.726 +        }
   1.727 +    }
   1.728 +
   1.729 +    /**
   1.730 +     * Gets the current value of the default locale for this instance
   1.731 +     * of the Java Virtual Machine.
   1.732 +     * <p>
   1.733 +     * The Java Virtual Machine sets the default locale during startup
   1.734 +     * based on the host environment. It is used by many locale-sensitive
   1.735 +     * methods if no locale is explicitly specified.
   1.736 +     * It can be changed using the
   1.737 +     * {@link #setDefault(java.util.Locale) setDefault} method.
   1.738 +     *
   1.739 +     * @return the default locale for this instance of the Java Virtual Machine
   1.740 +     */
   1.741 +    public static Locale getDefault() {
   1.742 +        // do not synchronize this method - see 4071298
   1.743 +        // it's OK if more than one default locale happens to be created
   1.744 +        if (defaultLocale == null) {
   1.745 +            initDefault();
   1.746 +        }
   1.747 +        return defaultLocale;
   1.748 +    }
   1.749 +
   1.750 +    /**
   1.751 +     * Gets the current value of the default locale for the specified Category
   1.752 +     * for this instance of the Java Virtual Machine.
   1.753 +     * <p>
   1.754 +     * The Java Virtual Machine sets the default locale during startup based
   1.755 +     * on the host environment. It is used by many locale-sensitive methods
   1.756 +     * if no locale is explicitly specified. It can be changed using the
   1.757 +     * setDefault(Locale.Category, Locale) method.
   1.758 +     *
   1.759 +     * @param category - the specified category to get the default locale
   1.760 +     * @throws NullPointerException - if category is null
   1.761 +     * @return the default locale for the specified Category for this instance
   1.762 +     *     of the Java Virtual Machine
   1.763 +     * @see #setDefault(Locale.Category, Locale)
   1.764 +     * @since 1.7
   1.765 +     */
   1.766 +    public static Locale getDefault(Locale.Category category) {
   1.767 +        // do not synchronize this method - see 4071298
   1.768 +        // it's OK if more than one default locale happens to be created
   1.769 +        switch (category) {
   1.770 +        case DISPLAY:
   1.771 +            if (defaultDisplayLocale == null) {
   1.772 +                initDefault(category);
   1.773 +            }
   1.774 +            return defaultDisplayLocale;
   1.775 +        case FORMAT:
   1.776 +            if (defaultFormatLocale == null) {
   1.777 +                initDefault(category);
   1.778 +            }
   1.779 +            return defaultFormatLocale;
   1.780 +        default:
   1.781 +            assert false: "Unknown Category";
   1.782 +        }
   1.783 +        return getDefault();
   1.784 +    }
   1.785 +
   1.786 +    private static void initDefault() {
   1.787 +        String language, region, script, country, variant;
   1.788 +        language = AccessController.doPrivileged(
   1.789 +            new GetPropertyAction("user.language", "en"));
   1.790 +        // for compatibility, check for old user.region property
   1.791 +        region = AccessController.doPrivileged(
   1.792 +            new GetPropertyAction("user.region"));
   1.793 +        if (region != null) {
   1.794 +            // region can be of form country, country_variant, or _variant
   1.795 +            int i = region.indexOf('_');
   1.796 +            if (i >= 0) {
   1.797 +                country = region.substring(0, i);
   1.798 +                variant = region.substring(i + 1);
   1.799 +            } else {
   1.800 +                country = region;
   1.801 +                variant = "";
   1.802 +            }
   1.803 +            script = "";
   1.804 +        } else {
   1.805 +            script = AccessController.doPrivileged(
   1.806 +                new GetPropertyAction("user.script", ""));
   1.807 +            country = AccessController.doPrivileged(
   1.808 +                new GetPropertyAction("user.country", ""));
   1.809 +            variant = AccessController.doPrivileged(
   1.810 +                new GetPropertyAction("user.variant", ""));
   1.811 +        }
   1.812 +        defaultLocale = getInstance(language, script, country, variant, null);
   1.813 +    }
   1.814 +
   1.815 +    private static void initDefault(Locale.Category category) {
   1.816 +        // make sure defaultLocale is initialized
   1.817 +        if (defaultLocale == null) {
   1.818 +            initDefault();
   1.819 +        }
   1.820 +
   1.821 +        Locale defaultCategoryLocale = getInstance(
   1.822 +            AccessController.doPrivileged(
   1.823 +                new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
   1.824 +            AccessController.doPrivileged(
   1.825 +                new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
   1.826 +            AccessController.doPrivileged(
   1.827 +                new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
   1.828 +            AccessController.doPrivileged(
   1.829 +                new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
   1.830 +            null);
   1.831 +
   1.832 +        switch (category) {
   1.833 +        case DISPLAY:
   1.834 +            defaultDisplayLocale = defaultCategoryLocale;
   1.835 +            break;
   1.836 +        case FORMAT:
   1.837 +            defaultFormatLocale = defaultCategoryLocale;
   1.838 +            break;
   1.839 +        }
   1.840 +    }
   1.841 +
   1.842 +    /**
   1.843 +     * Sets the default locale for this instance of the Java Virtual Machine.
   1.844 +     * This does not affect the host locale.
   1.845 +     * <p>
   1.846 +     * If there is a security manager, its <code>checkPermission</code>
   1.847 +     * method is called with a <code>PropertyPermission("user.language", "write")</code>
   1.848 +     * permission before the default locale is changed.
   1.849 +     * <p>
   1.850 +     * The Java Virtual Machine sets the default locale during startup
   1.851 +     * based on the host environment. It is used by many locale-sensitive
   1.852 +     * methods if no locale is explicitly specified.
   1.853 +     * <p>
   1.854 +     * Since changing the default locale may affect many different areas
   1.855 +     * of functionality, this method should only be used if the caller
   1.856 +     * is prepared to reinitialize locale-sensitive code running
   1.857 +     * within the same Java Virtual Machine.
   1.858 +     * <p>
   1.859 +     * By setting the default locale with this method, all of the default
   1.860 +     * locales for each Category are also set to the specified default locale.
   1.861 +     *
   1.862 +     * @throws SecurityException
   1.863 +     *        if a security manager exists and its
   1.864 +     *        <code>checkPermission</code> method doesn't allow the operation.
   1.865 +     * @throws NullPointerException if <code>newLocale</code> is null
   1.866 +     * @param newLocale the new default locale
   1.867 +     * @see SecurityManager#checkPermission
   1.868 +     * @see java.util.PropertyPermission
   1.869 +     */
   1.870 +    public static synchronized void setDefault(Locale newLocale) {
   1.871 +        setDefault(Category.DISPLAY, newLocale);
   1.872 +        setDefault(Category.FORMAT, newLocale);
   1.873 +        defaultLocale = newLocale;
   1.874 +    }
   1.875 +
   1.876 +    /**
   1.877 +     * Sets the default locale for the specified Category for this instance
   1.878 +     * of the Java Virtual Machine. This does not affect the host locale.
   1.879 +     * <p>
   1.880 +     * If there is a security manager, its checkPermission method is called
   1.881 +     * with a PropertyPermission("user.language", "write") permission before
   1.882 +     * the default locale is changed.
   1.883 +     * <p>
   1.884 +     * The Java Virtual Machine sets the default locale during startup based
   1.885 +     * on the host environment. It is used by many locale-sensitive methods
   1.886 +     * if no locale is explicitly specified.
   1.887 +     * <p>
   1.888 +     * Since changing the default locale may affect many different areas of
   1.889 +     * functionality, this method should only be used if the caller is
   1.890 +     * prepared to reinitialize locale-sensitive code running within the
   1.891 +     * same Java Virtual Machine.
   1.892 +     * <p>
   1.893 +     *
   1.894 +     * @param category - the specified category to set the default locale
   1.895 +     * @param newLocale - the new default locale
   1.896 +     * @throws SecurityException - if a security manager exists and its
   1.897 +     *     checkPermission method doesn't allow the operation.
   1.898 +     * @throws NullPointerException - if category and/or newLocale is null
   1.899 +     * @see SecurityManager#checkPermission(java.security.Permission)
   1.900 +     * @see PropertyPermission
   1.901 +     * @see #getDefault(Locale.Category)
   1.902 +     * @since 1.7
   1.903 +     */
   1.904 +    public static synchronized void setDefault(Locale.Category category,
   1.905 +        Locale newLocale) {
   1.906 +        if (category == null)
   1.907 +            throw new NullPointerException("Category cannot be NULL");
   1.908 +        if (newLocale == null)
   1.909 +            throw new NullPointerException("Can't set default locale to NULL");
   1.910 +
   1.911 +        SecurityManager sm = System.getSecurityManager();
   1.912 +        if (sm != null) sm.checkPermission(new PropertyPermission
   1.913 +                        ("user.language", "write"));
   1.914 +        switch (category) {
   1.915 +        case DISPLAY:
   1.916 +            defaultDisplayLocale = newLocale;
   1.917 +            break;
   1.918 +        case FORMAT:
   1.919 +            defaultFormatLocale = newLocale;
   1.920 +            break;
   1.921 +        default:
   1.922 +            assert false: "Unknown Category";
   1.923 +        }
   1.924 +    }
   1.925 +
   1.926 +    /**
   1.927 +     * Returns an array of all installed locales.
   1.928 +     * The returned array represents the union of locales supported
   1.929 +     * by the Java runtime environment and by installed
   1.930 +     * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
   1.931 +     * implementations.  It must contain at least a <code>Locale</code>
   1.932 +     * instance equal to {@link java.util.Locale#US Locale.US}.
   1.933 +     *
   1.934 +     * @return An array of installed locales.
   1.935 +     */
   1.936 +    public static Locale[] getAvailableLocales() {
   1.937 +        return LocaleServiceProviderPool.getAllAvailableLocales();
   1.938 +    }
   1.939 +
   1.940 +    /**
   1.941 +     * Returns a list of all 2-letter country codes defined in ISO 3166.
   1.942 +     * Can be used to create Locales.
   1.943 +     * <p>
   1.944 +     * <b>Note:</b> The <code>Locale</code> class also supports other codes for
   1.945 +     * country (region), such as 3-letter numeric UN M.49 area codes.
   1.946 +     * Therefore, the list returned by this method does not contain ALL valid
   1.947 +     * codes that can be used to create Locales.
   1.948 +     */
   1.949 +    public static String[] getISOCountries() {
   1.950 +        if (isoCountries == null) {
   1.951 +            isoCountries = getISO2Table(LocaleISOData.isoCountryTable);
   1.952 +        }
   1.953 +        String[] result = new String[isoCountries.length];
   1.954 +        System.arraycopy(isoCountries, 0, result, 0, isoCountries.length);
   1.955 +        return result;
   1.956 +    }
   1.957 +
   1.958 +    /**
   1.959 +     * Returns a list of all 2-letter language codes defined in ISO 639.
   1.960 +     * Can be used to create Locales.
   1.961 +     * <p>
   1.962 +     * <b>Note:</b>
   1.963 +     * <ul>
   1.964 +     * <li>ISO 639 is not a stable standard&mdash; some languages' codes have changed.
   1.965 +     * The list this function returns includes both the new and the old codes for the
   1.966 +     * languages whose codes have changed.
   1.967 +     * <li>The <code>Locale</code> class also supports language codes up to
   1.968 +     * 8 characters in length.  Therefore, the list returned by this method does
   1.969 +     * not contain ALL valid codes that can be used to create Locales.
   1.970 +     * </ul>
   1.971 +     */
   1.972 +    public static String[] getISOLanguages() {
   1.973 +        if (isoLanguages == null) {
   1.974 +            isoLanguages = getISO2Table(LocaleISOData.isoLanguageTable);
   1.975 +        }
   1.976 +        String[] result = new String[isoLanguages.length];
   1.977 +        System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
   1.978 +        return result;
   1.979 +    }
   1.980 +
   1.981 +    private static final String[] getISO2Table(String table) {
   1.982 +        int len = table.length() / 5;
   1.983 +        String[] isoTable = new String[len];
   1.984 +        for (int i = 0, j = 0; i < len; i++, j += 5) {
   1.985 +            isoTable[i] = table.substring(j, j + 2);
   1.986 +        }
   1.987 +        return isoTable;
   1.988 +    }
   1.989 +
   1.990 +    /**
   1.991 +     * Returns the language code of this Locale.
   1.992 +     *
   1.993 +     * <p><b>Note:</b> ISO 639 is not a stable standard&mdash; some languages' codes have changed.
   1.994 +     * Locale's constructor recognizes both the new and the old codes for the languages
   1.995 +     * whose codes have changed, but this function always returns the old code.  If you
   1.996 +     * want to check for a specific language whose code has changed, don't do
   1.997 +     * <pre>
   1.998 +     * if (locale.getLanguage().equals("he")) // BAD!
   1.999 +     *    ...
  1.1000 +     * </pre>
  1.1001 +     * Instead, do
  1.1002 +     * <pre>
  1.1003 +     * if (locale.getLanguage().equals(new Locale("he").getLanguage()))
  1.1004 +     *    ...
  1.1005 +     * </pre>
  1.1006 +     * @return The language code, or the empty string if none is defined.
  1.1007 +     * @see #getDisplayLanguage
  1.1008 +     */
  1.1009 +    public String getLanguage() {
  1.1010 +        return baseLocale.getLanguage();
  1.1011 +    }
  1.1012 +
  1.1013 +    /**
  1.1014 +     * Returns the script for this locale, which should
  1.1015 +     * either be the empty string or an ISO 15924 4-letter script
  1.1016 +     * code. The first letter is uppercase and the rest are
  1.1017 +     * lowercase, for example, 'Latn', 'Cyrl'.
  1.1018 +     *
  1.1019 +     * @return The script code, or the empty string if none is defined.
  1.1020 +     * @see #getDisplayScript
  1.1021 +     * @since 1.7
  1.1022 +     */
  1.1023 +    public String getScript() {
  1.1024 +        return baseLocale.getScript();
  1.1025 +    }
  1.1026 +
  1.1027 +    /**
  1.1028 +     * Returns the country/region code for this locale, which should
  1.1029 +     * either be the empty string, an uppercase ISO 3166 2-letter code,
  1.1030 +     * or a UN M.49 3-digit code.
  1.1031 +     *
  1.1032 +     * @return The country/region code, or the empty string if none is defined.
  1.1033 +     * @see #getDisplayCountry
  1.1034 +     */
  1.1035 +    public String getCountry() {
  1.1036 +        return baseLocale.getRegion();
  1.1037 +    }
  1.1038 +
  1.1039 +    /**
  1.1040 +     * Returns the variant code for this locale.
  1.1041 +     *
  1.1042 +     * @return The variant code, or the empty string if none is defined.
  1.1043 +     * @see #getDisplayVariant
  1.1044 +     */
  1.1045 +    public String getVariant() {
  1.1046 +        return baseLocale.getVariant();
  1.1047 +    }
  1.1048 +
  1.1049 +    /**
  1.1050 +     * Returns the extension (or private use) value associated with
  1.1051 +     * the specified key, or null if there is no extension
  1.1052 +     * associated with the key. To be well-formed, the key must be one
  1.1053 +     * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
  1.1054 +     * for example 'z' and 'Z' represent the same extension.
  1.1055 +     *
  1.1056 +     * @param key the extension key
  1.1057 +     * @return The extension, or null if this locale defines no
  1.1058 +     * extension for the specified key.
  1.1059 +     * @throws IllegalArgumentException if key is not well-formed
  1.1060 +     * @see #PRIVATE_USE_EXTENSION
  1.1061 +     * @see #UNICODE_LOCALE_EXTENSION
  1.1062 +     * @since 1.7
  1.1063 +     */
  1.1064 +    public String getExtension(char key) {
  1.1065 +        if (!LocaleExtensions.isValidKey(key)) {
  1.1066 +            throw new IllegalArgumentException("Ill-formed extension key: " + key);
  1.1067 +        }
  1.1068 +        return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key);
  1.1069 +    }
  1.1070 +
  1.1071 +    /**
  1.1072 +     * Returns the set of extension keys associated with this locale, or the
  1.1073 +     * empty set if it has no extensions. The returned set is unmodifiable.
  1.1074 +     * The keys will all be lower-case.
  1.1075 +     *
  1.1076 +     * @return The set of extension keys, or the empty set if this locale has
  1.1077 +     * no extensions.
  1.1078 +     * @since 1.7
  1.1079 +     */
  1.1080 +    public Set<Character> getExtensionKeys() {
  1.1081 +        if (localeExtensions == null) {
  1.1082 +            return Collections.emptySet();
  1.1083 +        }
  1.1084 +        return localeExtensions.getKeys();
  1.1085 +    }
  1.1086 +
  1.1087 +    /**
  1.1088 +     * Returns the set of unicode locale attributes associated with
  1.1089 +     * this locale, or the empty set if it has no attributes. The
  1.1090 +     * returned set is unmodifiable.
  1.1091 +     *
  1.1092 +     * @return The set of attributes.
  1.1093 +     * @since 1.7
  1.1094 +     */
  1.1095 +    public Set<String> getUnicodeLocaleAttributes() {
  1.1096 +        if (localeExtensions == null) {
  1.1097 +            return Collections.emptySet();
  1.1098 +        }
  1.1099 +        return localeExtensions.getUnicodeLocaleAttributes();
  1.1100 +    }
  1.1101 +
  1.1102 +    /**
  1.1103 +     * Returns the Unicode locale type associated with the specified Unicode locale key
  1.1104 +     * for this locale. Returns the empty string for keys that are defined with no type.
  1.1105 +     * Returns null if the key is not defined. Keys are case-insensitive. The key must
  1.1106 +     * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is
  1.1107 +     * thrown.
  1.1108 +     *
  1.1109 +     * @param key the Unicode locale key
  1.1110 +     * @return The Unicode locale type associated with the key, or null if the
  1.1111 +     * locale does not define the key.
  1.1112 +     * @throws IllegalArgumentException if the key is not well-formed
  1.1113 +     * @throws NullPointerException if <code>key</code> is null
  1.1114 +     * @since 1.7
  1.1115 +     */
  1.1116 +    public String getUnicodeLocaleType(String key) {
  1.1117 +        if (!UnicodeLocaleExtension.isKey(key)) {
  1.1118 +            throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
  1.1119 +        }
  1.1120 +        return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key);
  1.1121 +    }
  1.1122 +
  1.1123 +    /**
  1.1124 +     * Returns the set of Unicode locale keys defined by this locale, or the empty set if
  1.1125 +     * this locale has none.  The returned set is immutable.  Keys are all lower case.
  1.1126 +     *
  1.1127 +     * @return The set of Unicode locale keys, or the empty set if this locale has
  1.1128 +     * no Unicode locale keywords.
  1.1129 +     * @since 1.7
  1.1130 +     */
  1.1131 +    public Set<String> getUnicodeLocaleKeys() {
  1.1132 +        if (localeExtensions == null) {
  1.1133 +            return Collections.emptySet();
  1.1134 +        }
  1.1135 +        return localeExtensions.getUnicodeLocaleKeys();
  1.1136 +    }
  1.1137 +
  1.1138 +    /**
  1.1139 +     * Package locale method returning the Locale's BaseLocale,
  1.1140 +     * used by ResourceBundle
  1.1141 +     * @return base locale of this Locale
  1.1142 +     */
  1.1143 +    BaseLocale getBaseLocale() {
  1.1144 +        return baseLocale;
  1.1145 +    }
  1.1146 +
  1.1147 +    /**
  1.1148 +     * Package private method returning the Locale's LocaleExtensions,
  1.1149 +     * used by ResourceBundle.
  1.1150 +     * @return locale exnteions of this Locale,
  1.1151 +     *         or {@code null} if no extensions are defined
  1.1152 +     */
  1.1153 +     LocaleExtensions getLocaleExtensions() {
  1.1154 +         return localeExtensions;
  1.1155 +     }
  1.1156 +
  1.1157 +    /**
  1.1158 +     * Returns a string representation of this <code>Locale</code>
  1.1159 +     * object, consisting of language, country, variant, script,
  1.1160 +     * and extensions as below:
  1.1161 +     * <p><blockquote>
  1.1162 +     * language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
  1.1163 +     * </blockquote>
  1.1164 +     *
  1.1165 +     * Language is always lower case, country is always upper case, script is always title
  1.1166 +     * case, and extensions are always lower case.  Extensions and private use subtags
  1.1167 +     * will be in canonical order as explained in {@link #toLanguageTag}.
  1.1168 +     *
  1.1169 +     * <p>When the locale has neither script nor extensions, the result is the same as in
  1.1170 +     * Java 6 and prior.
  1.1171 +     *
  1.1172 +     * <p>If both the language and country fields are missing, this function will return
  1.1173 +     * the empty string, even if the variant, script, or extensions field is present (you
  1.1174 +     * can't have a locale with just a variant, the variant must accompany a well-formed
  1.1175 +     * language or country code).
  1.1176 +     *
  1.1177 +     * <p>If script or extensions are present and variant is missing, no underscore is
  1.1178 +     * added before the "#".
  1.1179 +     *
  1.1180 +     * <p>This behavior is designed to support debugging and to be compatible with
  1.1181 +     * previous uses of <code>toString</code> that expected language, country, and variant
  1.1182 +     * fields only.  To represent a Locale as a String for interchange purposes, use
  1.1183 +     * {@link #toLanguageTag}.
  1.1184 +     *
  1.1185 +     * <p>Examples: <ul><tt>
  1.1186 +     * <li>en
  1.1187 +     * <li>de_DE
  1.1188 +     * <li>_GB
  1.1189 +     * <li>en_US_WIN
  1.1190 +     * <li>de__POSIX
  1.1191 +     * <li>zh_CN_#Hans
  1.1192 +     * <li>zh_TW_#Hant-x-java
  1.1193 +     * <li>th_TH_TH_#u-nu-thai</tt></ul>
  1.1194 +     *
  1.1195 +     * @return A string representation of the Locale, for debugging.
  1.1196 +     * @see #getDisplayName
  1.1197 +     * @see #toLanguageTag
  1.1198 +     */
  1.1199 +    @Override
  1.1200 +    public final String toString() {
  1.1201 +        boolean l = (baseLocale.getLanguage().length() != 0);
  1.1202 +        boolean s = (baseLocale.getScript().length() != 0);
  1.1203 +        boolean r = (baseLocale.getRegion().length() != 0);
  1.1204 +        boolean v = (baseLocale.getVariant().length() != 0);
  1.1205 +        boolean e = (localeExtensions != null && localeExtensions.getID().length() != 0);
  1.1206 +
  1.1207 +        StringBuilder result = new StringBuilder(baseLocale.getLanguage());
  1.1208 +        if (r || (l && (v || s || e))) {
  1.1209 +            result.append('_')
  1.1210 +                .append(baseLocale.getRegion()); // This may just append '_'
  1.1211 +        }
  1.1212 +        if (v && (l || r)) {
  1.1213 +            result.append('_')
  1.1214 +                .append(baseLocale.getVariant());
  1.1215 +        }
  1.1216 +
  1.1217 +        if (s && (l || r)) {
  1.1218 +            result.append("_#")
  1.1219 +                .append(baseLocale.getScript());
  1.1220 +        }
  1.1221 +
  1.1222 +        if (e && (l || r)) {
  1.1223 +            result.append('_');
  1.1224 +            if (!s) {
  1.1225 +                result.append('#');
  1.1226 +            }
  1.1227 +            result.append(localeExtensions.getID());
  1.1228 +        }
  1.1229 +
  1.1230 +        return result.toString();
  1.1231 +    }
  1.1232 +
  1.1233 +    /**
  1.1234 +     * Returns a well-formed IETF BCP 47 language tag representing
  1.1235 +     * this locale.
  1.1236 +     *
  1.1237 +     * <p>If this <code>Locale</code> has a language, country, or
  1.1238 +     * variant that does not satisfy the IETF BCP 47 language tag
  1.1239 +     * syntax requirements, this method handles these fields as
  1.1240 +     * described below:
  1.1241 +     *
  1.1242 +     * <p><b>Language:</b> If language is empty, or not <a
  1.1243 +     * href="#def_language" >well-formed</a> (for example "a" or
  1.1244 +     * "e2"), it will be emitted as "und" (Undetermined).
  1.1245 +     *
  1.1246 +     * <p><b>Country:</b> If country is not <a
  1.1247 +     * href="#def_region">well-formed</a> (for example "12" or "USA"),
  1.1248 +     * it will be omitted.
  1.1249 +     *
  1.1250 +     * <p><b>Variant:</b> If variant <b>is</b> <a
  1.1251 +     * href="#def_variant">well-formed</a>, each sub-segment
  1.1252 +     * (delimited by '-' or '_') is emitted as a subtag.  Otherwise:
  1.1253 +     * <ul>
  1.1254 +     *
  1.1255 +     * <li>if all sub-segments match <code>[0-9a-zA-Z]{1,8}</code>
  1.1256 +     * (for example "WIN" or "Oracle_JDK_Standard_Edition"), the first
  1.1257 +     * ill-formed sub-segment and all following will be appended to
  1.1258 +     * the private use subtag.  The first appended subtag will be
  1.1259 +     * "lvariant", followed by the sub-segments in order, separated by
  1.1260 +     * hyphen. For example, "x-lvariant-WIN",
  1.1261 +     * "Oracle-x-lvariant-JDK-Standard-Edition".
  1.1262 +     *
  1.1263 +     * <li>if any sub-segment does not match
  1.1264 +     * <code>[0-9a-zA-Z]{1,8}</code>, the variant will be truncated
  1.1265 +     * and the problematic sub-segment and all following sub-segments
  1.1266 +     * will be omitted.  If the remainder is non-empty, it will be
  1.1267 +     * emitted as a private use subtag as above (even if the remainder
  1.1268 +     * turns out to be well-formed).  For example,
  1.1269 +     * "Solaris_isjustthecoolestthing" is emitted as
  1.1270 +     * "x-lvariant-Solaris", not as "solaris".</li></ul>
  1.1271 +     *
  1.1272 +     * <p><b>Special Conversions:</b> Java supports some old locale
  1.1273 +     * representations, including deprecated ISO language codes,
  1.1274 +     * for compatibility. This method performs the following
  1.1275 +     * conversions:
  1.1276 +     * <ul>
  1.1277 +     *
  1.1278 +     * <li>Deprecated ISO language codes "iw", "ji", and "in" are
  1.1279 +     * converted to "he", "yi", and "id", respectively.
  1.1280 +     *
  1.1281 +     * <li>A locale with language "no", country "NO", and variant
  1.1282 +     * "NY", representing Norwegian Nynorsk (Norway), is converted
  1.1283 +     * to a language tag "nn-NO".</li></ul>
  1.1284 +     *
  1.1285 +     * <p><b>Note:</b> Although the language tag created by this
  1.1286 +     * method is well-formed (satisfies the syntax requirements
  1.1287 +     * defined by the IETF BCP 47 specification), it is not
  1.1288 +     * necessarily a valid BCP 47 language tag.  For example,
  1.1289 +     * <pre>
  1.1290 +     *   new Locale("xx", "YY").toLanguageTag();</pre>
  1.1291 +     *
  1.1292 +     * will return "xx-YY", but the language subtag "xx" and the
  1.1293 +     * region subtag "YY" are invalid because they are not registered
  1.1294 +     * in the IANA Language Subtag Registry.
  1.1295 +     *
  1.1296 +     * @return a BCP47 language tag representing the locale
  1.1297 +     * @see #forLanguageTag(String)
  1.1298 +     * @since 1.7
  1.1299 +     */
  1.1300 +    public String toLanguageTag() {
  1.1301 +        LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
  1.1302 +        StringBuilder buf = new StringBuilder();
  1.1303 +
  1.1304 +        String subtag = tag.getLanguage();
  1.1305 +        if (subtag.length() > 0) {
  1.1306 +            buf.append(LanguageTag.canonicalizeLanguage(subtag));
  1.1307 +        }
  1.1308 +
  1.1309 +        subtag = tag.getScript();
  1.1310 +        if (subtag.length() > 0) {
  1.1311 +            buf.append(LanguageTag.SEP);
  1.1312 +            buf.append(LanguageTag.canonicalizeScript(subtag));
  1.1313 +        }
  1.1314 +
  1.1315 +        subtag = tag.getRegion();
  1.1316 +        if (subtag.length() > 0) {
  1.1317 +            buf.append(LanguageTag.SEP);
  1.1318 +            buf.append(LanguageTag.canonicalizeRegion(subtag));
  1.1319 +        }
  1.1320 +
  1.1321 +        List<String>subtags = tag.getVariants();
  1.1322 +        for (String s : subtags) {
  1.1323 +            buf.append(LanguageTag.SEP);
  1.1324 +            // preserve casing
  1.1325 +            buf.append(s);
  1.1326 +        }
  1.1327 +
  1.1328 +        subtags = tag.getExtensions();
  1.1329 +        for (String s : subtags) {
  1.1330 +            buf.append(LanguageTag.SEP);
  1.1331 +            buf.append(LanguageTag.canonicalizeExtension(s));
  1.1332 +        }
  1.1333 +
  1.1334 +        subtag = tag.getPrivateuse();
  1.1335 +        if (subtag.length() > 0) {
  1.1336 +            if (buf.length() > 0) {
  1.1337 +                buf.append(LanguageTag.SEP);
  1.1338 +            }
  1.1339 +            buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
  1.1340 +            // preserve casing
  1.1341 +            buf.append(subtag);
  1.1342 +        }
  1.1343 +
  1.1344 +        return buf.toString();
  1.1345 +    }
  1.1346 +
  1.1347 +    /**
  1.1348 +     * Returns a locale for the specified IETF BCP 47 language tag string.
  1.1349 +     *
  1.1350 +     * <p>If the specified language tag contains any ill-formed subtags,
  1.1351 +     * the first such subtag and all following subtags are ignored.  Compare
  1.1352 +     * to {@link Locale.Builder#setLanguageTag} which throws an exception
  1.1353 +     * in this case.
  1.1354 +     *
  1.1355 +     * <p>The following <b>conversions</b> are performed:<ul>
  1.1356 +     *
  1.1357 +     * <li>The language code "und" is mapped to language "".
  1.1358 +     *
  1.1359 +     * <li>The language codes "he", "yi", and "id" are mapped to "iw",
  1.1360 +     * "ji", and "in" respectively. (This is the same canonicalization
  1.1361 +     * that's done in Locale's constructors.)
  1.1362 +     *
  1.1363 +     * <li>The portion of a private use subtag prefixed by "lvariant",
  1.1364 +     * if any, is removed and appended to the variant field in the
  1.1365 +     * result locale (without case normalization).  If it is then
  1.1366 +     * empty, the private use subtag is discarded:
  1.1367 +     *
  1.1368 +     * <pre>
  1.1369 +     *     Locale loc;
  1.1370 +     *     loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX");
  1.1371 +     *     loc.getVariant(); // returns "POSIX"
  1.1372 +     *     loc.getExtension('x'); // returns null
  1.1373 +     *
  1.1374 +     *     loc = Locale.forLanguageTag("de-POSIX-x-URP-lvariant-Abc-Def");
  1.1375 +     *     loc.getVariant(); // returns "POSIX_Abc_Def"
  1.1376 +     *     loc.getExtension('x'); // returns "urp"
  1.1377 +     * </pre>
  1.1378 +     *
  1.1379 +     * <li>When the languageTag argument contains an extlang subtag,
  1.1380 +     * the first such subtag is used as the language, and the primary
  1.1381 +     * language subtag and other extlang subtags are ignored:
  1.1382 +     *
  1.1383 +     * <pre>
  1.1384 +     *     Locale.forLanguageTag("ar-aao").getLanguage(); // returns "aao"
  1.1385 +     *     Locale.forLanguageTag("en-abc-def-us").toString(); // returns "abc_US"
  1.1386 +     * </pre>
  1.1387 +     *
  1.1388 +     * <li>Case is normalized except for variant tags, which are left
  1.1389 +     * unchanged.  Language is normalized to lower case, script to
  1.1390 +     * title case, country to upper case, and extensions to lower
  1.1391 +     * case.
  1.1392 +     *
  1.1393 +     * <li>If, after processing, the locale would exactly match either
  1.1394 +     * ja_JP_JP or th_TH_TH with no extensions, the appropriate
  1.1395 +     * extensions are added as though the constructor had been called:
  1.1396 +     *
  1.1397 +     * <pre>
  1.1398 +     *    Locale.forLanguageTag("ja-JP-x-lvariant-JP").toLanguageTag();
  1.1399 +     *    // returns "ja-JP-u-ca-japanese-x-lvariant-JP"
  1.1400 +     *    Locale.forLanguageTag("th-TH-x-lvariant-TH").toLanguageTag();
  1.1401 +     *    // returns "th-TH-u-nu-thai-x-lvariant-TH"
  1.1402 +     * <pre></ul>
  1.1403 +     *
  1.1404 +     * <p>This implements the 'Language-Tag' production of BCP47, and
  1.1405 +     * so supports grandfathered (regular and irregular) as well as
  1.1406 +     * private use language tags.  Stand alone private use tags are
  1.1407 +     * represented as empty language and extension 'x-whatever',
  1.1408 +     * and grandfathered tags are converted to their canonical replacements
  1.1409 +     * where they exist.
  1.1410 +     *
  1.1411 +     * <p>Grandfathered tags with canonical replacements are as follows:
  1.1412 +     *
  1.1413 +     * <table>
  1.1414 +     * <tbody align="center">
  1.1415 +     * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>modern replacement</th></tr>
  1.1416 +     * <tr><td>art-lojban</td><td>&nbsp;</td><td>jbo</td></tr>
  1.1417 +     * <tr><td>i-ami</td><td>&nbsp;</td><td>ami</td></tr>
  1.1418 +     * <tr><td>i-bnn</td><td>&nbsp;</td><td>bnn</td></tr>
  1.1419 +     * <tr><td>i-hak</td><td>&nbsp;</td><td>hak</td></tr>
  1.1420 +     * <tr><td>i-klingon</td><td>&nbsp;</td><td>tlh</td></tr>
  1.1421 +     * <tr><td>i-lux</td><td>&nbsp;</td><td>lb</td></tr>
  1.1422 +     * <tr><td>i-navajo</td><td>&nbsp;</td><td>nv</td></tr>
  1.1423 +     * <tr><td>i-pwn</td><td>&nbsp;</td><td>pwn</td></tr>
  1.1424 +     * <tr><td>i-tao</td><td>&nbsp;</td><td>tao</td></tr>
  1.1425 +     * <tr><td>i-tay</td><td>&nbsp;</td><td>tay</td></tr>
  1.1426 +     * <tr><td>i-tsu</td><td>&nbsp;</td><td>tsu</td></tr>
  1.1427 +     * <tr><td>no-bok</td><td>&nbsp;</td><td>nb</td></tr>
  1.1428 +     * <tr><td>no-nyn</td><td>&nbsp;</td><td>nn</td></tr>
  1.1429 +     * <tr><td>sgn-BE-FR</td><td>&nbsp;</td><td>sfb</td></tr>
  1.1430 +     * <tr><td>sgn-BE-NL</td><td>&nbsp;</td><td>vgt</td></tr>
  1.1431 +     * <tr><td>sgn-CH-DE</td><td>&nbsp;</td><td>sgg</td></tr>
  1.1432 +     * <tr><td>zh-guoyu</td><td>&nbsp;</td><td>cmn</td></tr>
  1.1433 +     * <tr><td>zh-hakka</td><td>&nbsp;</td><td>hak</td></tr>
  1.1434 +     * <tr><td>zh-min-nan</td><td>&nbsp;</td><td>nan</td></tr>
  1.1435 +     * <tr><td>zh-xiang</td><td>&nbsp;</td><td>hsn</td></tr>
  1.1436 +     * </tbody>
  1.1437 +     * </table>
  1.1438 +     *
  1.1439 +     * <p>Grandfathered tags with no modern replacement will be
  1.1440 +     * converted as follows:
  1.1441 +     *
  1.1442 +     * <table>
  1.1443 +     * <tbody align="center">
  1.1444 +     * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>converts to</th></tr>
  1.1445 +     * <tr><td>cel-gaulish</td><td>&nbsp;</td><td>xtg-x-cel-gaulish</td></tr>
  1.1446 +     * <tr><td>en-GB-oed</td><td>&nbsp;</td><td>en-GB-x-oed</td></tr>
  1.1447 +     * <tr><td>i-default</td><td>&nbsp;</td><td>en-x-i-default</td></tr>
  1.1448 +     * <tr><td>i-enochian</td><td>&nbsp;</td><td>und-x-i-enochian</td></tr>
  1.1449 +     * <tr><td>i-mingo</td><td>&nbsp;</td><td>see-x-i-mingo</td></tr>
  1.1450 +     * <tr><td>zh-min</td><td>&nbsp;</td><td>nan-x-zh-min</td></tr>
  1.1451 +     * </tbody>
  1.1452 +     * </table>
  1.1453 +     *
  1.1454 +     * <p>For a list of all grandfathered tags, see the
  1.1455 +     * IANA Language Subtag Registry (search for "Type: grandfathered").
  1.1456 +     *
  1.1457 +     * <p><b>Note</b>: there is no guarantee that <code>toLanguageTag</code>
  1.1458 +     * and <code>forLanguageTag</code> will round-trip.
  1.1459 +     *
  1.1460 +     * @param languageTag the language tag
  1.1461 +     * @return The locale that best represents the language tag.
  1.1462 +     * @throws NullPointerException if <code>languageTag</code> is <code>null</code>
  1.1463 +     * @see #toLanguageTag()
  1.1464 +     * @see java.util.Locale.Builder#setLanguageTag(String)
  1.1465 +     * @since 1.7
  1.1466 +     */
  1.1467 +    public static Locale forLanguageTag(String languageTag) {
  1.1468 +        LanguageTag tag = LanguageTag.parse(languageTag, null);
  1.1469 +        InternalLocaleBuilder bldr = new InternalLocaleBuilder();
  1.1470 +        bldr.setLanguageTag(tag);
  1.1471 +        BaseLocale base = bldr.getBaseLocale();
  1.1472 +        LocaleExtensions exts = bldr.getLocaleExtensions();
  1.1473 +        if (exts == null && base.getVariant().length() > 0) {
  1.1474 +            exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(),
  1.1475 +                                              base.getRegion(), base.getVariant());
  1.1476 +        }
  1.1477 +        return getInstance(base, exts);
  1.1478 +    }
  1.1479 +
  1.1480 +    /**
  1.1481 +     * Returns a three-letter abbreviation of this locale's language.
  1.1482 +     * If the language matches an ISO 639-1 two-letter code, the
  1.1483 +     * corresponding ISO 639-2/T three-letter lowercase code is
  1.1484 +     * returned.  The ISO 639-2 language codes can be found on-line,
  1.1485 +     * see "Codes for the Representation of Names of Languages Part 2:
  1.1486 +     * Alpha-3 Code".  If the locale specifies a three-letter
  1.1487 +     * language, the language is returned as is.  If the locale does
  1.1488 +     * not specify a language the empty string is returned.
  1.1489 +     *
  1.1490 +     * @return A three-letter abbreviation of this locale's language.
  1.1491 +     * @exception MissingResourceException Throws MissingResourceException if
  1.1492 +     * three-letter language abbreviation is not available for this locale.
  1.1493 +     */
  1.1494 +    public String getISO3Language() throws MissingResourceException {
  1.1495 +        String lang = baseLocale.getLanguage();
  1.1496 +        if (lang.length() == 3) {
  1.1497 +            return lang;
  1.1498 +        }
  1.1499 +
  1.1500 +        String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
  1.1501 +        if (language3 == null) {
  1.1502 +            throw new MissingResourceException("Couldn't find 3-letter language code for "
  1.1503 +                    + lang, "FormatData_" + toString(), "ShortLanguage");
  1.1504 +        }
  1.1505 +        return language3;
  1.1506 +    }
  1.1507 +
  1.1508 +    /**
  1.1509 +     * Returns a three-letter abbreviation for this locale's country.
  1.1510 +     * If the country matches an ISO 3166-1 alpha-2 code, the
  1.1511 +     * corresponding ISO 3166-1 alpha-3 uppercase code is returned.
  1.1512 +     * If the locale doesn't specify a country, this will be the empty
  1.1513 +     * string.
  1.1514 +     *
  1.1515 +     * <p>The ISO 3166-1 codes can be found on-line.
  1.1516 +     *
  1.1517 +     * @return A three-letter abbreviation of this locale's country.
  1.1518 +     * @exception MissingResourceException Throws MissingResourceException if the
  1.1519 +     * three-letter country abbreviation is not available for this locale.
  1.1520 +     */
  1.1521 +    public String getISO3Country() throws MissingResourceException {
  1.1522 +        String country3 = getISO3Code(baseLocale.getRegion(), LocaleISOData.isoCountryTable);
  1.1523 +        if (country3 == null) {
  1.1524 +            throw new MissingResourceException("Couldn't find 3-letter country code for "
  1.1525 +                    + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
  1.1526 +        }
  1.1527 +        return country3;
  1.1528 +    }
  1.1529 +
  1.1530 +    private static final String getISO3Code(String iso2Code, String table) {
  1.1531 +        int codeLength = iso2Code.length();
  1.1532 +        if (codeLength == 0) {
  1.1533 +            return "";
  1.1534 +        }
  1.1535 +
  1.1536 +        int tableLength = table.length();
  1.1537 +        int index = tableLength;
  1.1538 +        if (codeLength == 2) {
  1.1539 +            char c1 = iso2Code.charAt(0);
  1.1540 +            char c2 = iso2Code.charAt(1);
  1.1541 +            for (index = 0; index < tableLength; index += 5) {
  1.1542 +                if (table.charAt(index) == c1
  1.1543 +                    && table.charAt(index + 1) == c2) {
  1.1544 +                    break;
  1.1545 +                }
  1.1546 +            }
  1.1547 +        }
  1.1548 +        return index < tableLength ? table.substring(index + 2, index + 5) : null;
  1.1549 +    }
  1.1550 +
  1.1551 +    /**
  1.1552 +     * Returns a name for the locale's language that is appropriate for display to the
  1.1553 +     * user.
  1.1554 +     * If possible, the name returned will be localized for the default locale.
  1.1555 +     * For example, if the locale is fr_FR and the default locale
  1.1556 +     * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
  1.1557 +     * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
  1.1558 +     * If the name returned cannot be localized for the default locale,
  1.1559 +     * (say, we don't have a Japanese name for Croatian),
  1.1560 +     * this function falls back on the English name, and uses the ISO code as a last-resort
  1.1561 +     * value.  If the locale doesn't specify a language, this function returns the empty string.
  1.1562 +     */
  1.1563 +    public final String getDisplayLanguage() {
  1.1564 +        return getDisplayLanguage(getDefault(Category.DISPLAY));
  1.1565 +    }
  1.1566 +
  1.1567 +    /**
  1.1568 +     * Returns a name for the locale's language that is appropriate for display to the
  1.1569 +     * user.
  1.1570 +     * If possible, the name returned will be localized according to inLocale.
  1.1571 +     * For example, if the locale is fr_FR and inLocale
  1.1572 +     * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
  1.1573 +     * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
  1.1574 +     * If the name returned cannot be localized according to inLocale,
  1.1575 +     * (say, we don't have a Japanese name for Croatian),
  1.1576 +     * this function falls back on the English name, and finally
  1.1577 +     * on the ISO code as a last-resort value.  If the locale doesn't specify a language,
  1.1578 +     * this function returns the empty string.
  1.1579 +     *
  1.1580 +     * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1.1581 +     */
  1.1582 +    public String getDisplayLanguage(Locale inLocale) {
  1.1583 +        return getDisplayString(baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
  1.1584 +    }
  1.1585 +
  1.1586 +    /**
  1.1587 +     * Returns a name for the the locale's script that is appropriate for display to
  1.1588 +     * the user. If possible, the name will be localized for the default locale.  Returns
  1.1589 +     * the empty string if this locale doesn't specify a script code.
  1.1590 +     *
  1.1591 +     * @return the display name of the script code for the current default locale
  1.1592 +     * @since 1.7
  1.1593 +     */
  1.1594 +    public String getDisplayScript() {
  1.1595 +        return getDisplayScript(getDefault());
  1.1596 +    }
  1.1597 +
  1.1598 +    /**
  1.1599 +     * Returns a name for the locale's script that is appropriate
  1.1600 +     * for display to the user. If possible, the name will be
  1.1601 +     * localized for the given locale. Returns the empty string if
  1.1602 +     * this locale doesn't specify a script code.
  1.1603 +     *
  1.1604 +     * @return the display name of the script code for the current default locale
  1.1605 +     * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
  1.1606 +     * @since 1.7
  1.1607 +     */
  1.1608 +    public String getDisplayScript(Locale inLocale) {
  1.1609 +        return getDisplayString(baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
  1.1610 +    }
  1.1611 +
  1.1612 +    /**
  1.1613 +     * Returns a name for the locale's country that is appropriate for display to the
  1.1614 +     * user.
  1.1615 +     * If possible, the name returned will be localized for the default locale.
  1.1616 +     * For example, if the locale is fr_FR and the default locale
  1.1617 +     * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
  1.1618 +     * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis".
  1.1619 +     * If the name returned cannot be localized for the default locale,
  1.1620 +     * (say, we don't have a Japanese name for Croatia),
  1.1621 +     * this function falls back on the English name, and uses the ISO code as a last-resort
  1.1622 +     * value.  If the locale doesn't specify a country, this function returns the empty string.
  1.1623 +     */
  1.1624 +    public final String getDisplayCountry() {
  1.1625 +        return getDisplayCountry(getDefault(Category.DISPLAY));
  1.1626 +    }
  1.1627 +
  1.1628 +    /**
  1.1629 +     * Returns a name for the locale's country that is appropriate for display to the
  1.1630 +     * user.
  1.1631 +     * If possible, the name returned will be localized according to inLocale.
  1.1632 +     * For example, if the locale is fr_FR and inLocale
  1.1633 +     * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
  1.1634 +     * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
  1.1635 +     * If the name returned cannot be localized according to inLocale.
  1.1636 +     * (say, we don't have a Japanese name for Croatia),
  1.1637 +     * this function falls back on the English name, and finally
  1.1638 +     * on the ISO code as a last-resort value.  If the locale doesn't specify a country,
  1.1639 +     * this function returns the empty string.
  1.1640 +     *
  1.1641 +     * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1.1642 +     */
  1.1643 +    public String getDisplayCountry(Locale inLocale) {
  1.1644 +        return getDisplayString(baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
  1.1645 +    }
  1.1646 +
  1.1647 +    private String getDisplayString(String code, Locale inLocale, int type) {
  1.1648 +        if (code.length() == 0) {
  1.1649 +            return "";
  1.1650 +        }
  1.1651 +
  1.1652 +        if (inLocale == null) {
  1.1653 +            throw new NullPointerException();
  1.1654 +        }
  1.1655 +
  1.1656 +        try {
  1.1657 +            OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1.1658 +            String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
  1.1659 +            String result = null;
  1.1660 +
  1.1661 +            // Check whether a provider can provide an implementation that's closer
  1.1662 +            // to the requested locale than what the Java runtime itself can provide.
  1.1663 +            LocaleServiceProviderPool pool =
  1.1664 +                LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
  1.1665 +            if (pool.hasProviders()) {
  1.1666 +                result = pool.getLocalizedObject(
  1.1667 +                                    LocaleNameGetter.INSTANCE,
  1.1668 +                                    inLocale, bundle, key,
  1.1669 +                                    type, code);
  1.1670 +            }
  1.1671 +
  1.1672 +            if (result == null) {
  1.1673 +                result = bundle.getString(key);
  1.1674 +            }
  1.1675 +
  1.1676 +            if (result != null) {
  1.1677 +                return result;
  1.1678 +            }
  1.1679 +        }
  1.1680 +        catch (Exception e) {
  1.1681 +            // just fall through
  1.1682 +        }
  1.1683 +        return code;
  1.1684 +    }
  1.1685 +
  1.1686 +    /**
  1.1687 +     * Returns a name for the locale's variant code that is appropriate for display to the
  1.1688 +     * user.  If possible, the name will be localized for the default locale.  If the locale
  1.1689 +     * doesn't specify a variant code, this function returns the empty string.
  1.1690 +     */
  1.1691 +    public final String getDisplayVariant() {
  1.1692 +        return getDisplayVariant(getDefault(Category.DISPLAY));
  1.1693 +    }
  1.1694 +
  1.1695 +    /**
  1.1696 +     * Returns a name for the locale's variant code that is appropriate for display to the
  1.1697 +     * user.  If possible, the name will be localized for inLocale.  If the locale
  1.1698 +     * doesn't specify a variant code, this function returns the empty string.
  1.1699 +     *
  1.1700 +     * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  1.1701 +     */
  1.1702 +    public String getDisplayVariant(Locale inLocale) {
  1.1703 +        if (baseLocale.getVariant().length() == 0)
  1.1704 +            return "";
  1.1705 +
  1.1706 +        OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1.1707 +
  1.1708 +        String names[] = getDisplayVariantArray(bundle, inLocale);
  1.1709 +
  1.1710 +        // Get the localized patterns for formatting a list, and use
  1.1711 +        // them to format the list.
  1.1712 +        String listPattern = null;
  1.1713 +        String listCompositionPattern = null;
  1.1714 +        try {
  1.1715 +            listPattern = bundle.getString("ListPattern");
  1.1716 +            listCompositionPattern = bundle.getString("ListCompositionPattern");
  1.1717 +        } catch (MissingResourceException e) {
  1.1718 +        }
  1.1719 +        return formatList(names, listPattern, listCompositionPattern);
  1.1720 +    }
  1.1721 +
  1.1722 +    /**
  1.1723 +     * Returns a name for the locale that is appropriate for display to the
  1.1724 +     * user. This will be the values returned by getDisplayLanguage(),
  1.1725 +     * getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled
  1.1726 +     * into a single string. The the non-empty values are used in order,
  1.1727 +     * with the second and subsequent names in parentheses.  For example:
  1.1728 +     * <blockquote>
  1.1729 +     * language (script, country, variant)<br>
  1.1730 +     * language (country)<br>
  1.1731 +     * language (variant)<br>
  1.1732 +     * script (country)<br>
  1.1733 +     * country<br>
  1.1734 +     * </blockquote>
  1.1735 +     * depending on which fields are specified in the locale.  If the
  1.1736 +     * language, sacript, country, and variant fields are all empty,
  1.1737 +     * this function returns the empty string.
  1.1738 +     */
  1.1739 +    public final String getDisplayName() {
  1.1740 +        return getDisplayName(getDefault(Category.DISPLAY));
  1.1741 +    }
  1.1742 +
  1.1743 +    /**
  1.1744 +     * Returns a name for the locale that is appropriate for display
  1.1745 +     * to the user.  This will be the values returned by
  1.1746 +     * getDisplayLanguage(), getDisplayScript(),getDisplayCountry(),
  1.1747 +     * and getDisplayVariant() assembled into a single string.
  1.1748 +     * The non-empty values are used in order,
  1.1749 +     * with the second and subsequent names in parentheses.  For example:
  1.1750 +     * <blockquote>
  1.1751 +     * language (script, country, variant)<br>
  1.1752 +     * language (country)<br>
  1.1753 +     * language (variant)<br>
  1.1754 +     * script (country)<br>
  1.1755 +     * country<br>
  1.1756 +     * </blockquote>
  1.1757 +     * depending on which fields are specified in the locale.  If the
  1.1758 +     * language, script, country, and variant fields are all empty,
  1.1759 +     * this function returns the empty string.
  1.1760 +     *
  1.1761 +     * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
  1.1762 +     */
  1.1763 +    public String getDisplayName(Locale inLocale) {
  1.1764 +        OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1.1765 +
  1.1766 +        String languageName = getDisplayLanguage(inLocale);
  1.1767 +        String scriptName = getDisplayScript(inLocale);
  1.1768 +        String countryName = getDisplayCountry(inLocale);
  1.1769 +        String[] variantNames = getDisplayVariantArray(bundle, inLocale);
  1.1770 +
  1.1771 +        // Get the localized patterns for formatting a display name.
  1.1772 +        String displayNamePattern = null;
  1.1773 +        String listPattern = null;
  1.1774 +        String listCompositionPattern = null;
  1.1775 +        try {
  1.1776 +            displayNamePattern = bundle.getString("DisplayNamePattern");
  1.1777 +            listPattern = bundle.getString("ListPattern");
  1.1778 +            listCompositionPattern = bundle.getString("ListCompositionPattern");
  1.1779 +        } catch (MissingResourceException e) {
  1.1780 +        }
  1.1781 +
  1.1782 +        // The display name consists of a main name, followed by qualifiers.
  1.1783 +        // Typically, the format is "MainName (Qualifier, Qualifier)" but this
  1.1784 +        // depends on what pattern is stored in the display locale.
  1.1785 +        String   mainName       = null;
  1.1786 +        String[] qualifierNames = null;
  1.1787 +
  1.1788 +        // The main name is the language, or if there is no language, the script,
  1.1789 +        // then if no script, the country. If there is no language/script/country
  1.1790 +        // (an anomalous situation) then the display name is simply the variant's
  1.1791 +        // display name.
  1.1792 +        if (languageName.length() == 0 && scriptName.length() == 0 && countryName.length() == 0) {
  1.1793 +            if (variantNames.length == 0) {
  1.1794 +                return "";
  1.1795 +            } else {
  1.1796 +                return formatList(variantNames, listPattern, listCompositionPattern);
  1.1797 +            }
  1.1798 +        }
  1.1799 +        ArrayList<String> names = new ArrayList<>(4);
  1.1800 +        if (languageName.length() != 0) {
  1.1801 +            names.add(languageName);
  1.1802 +        }
  1.1803 +        if (scriptName.length() != 0) {
  1.1804 +            names.add(scriptName);
  1.1805 +        }
  1.1806 +        if (countryName.length() != 0) {
  1.1807 +            names.add(countryName);
  1.1808 +        }
  1.1809 +        if (variantNames.length != 0) {
  1.1810 +            for (String var : variantNames) {
  1.1811 +                names.add(var);
  1.1812 +            }
  1.1813 +        }
  1.1814 +
  1.1815 +        // The first one in the main name
  1.1816 +        mainName = names.get(0);
  1.1817 +
  1.1818 +        // Others are qualifiers
  1.1819 +        int numNames = names.size();
  1.1820 +        qualifierNames = (numNames > 1) ?
  1.1821 +                names.subList(1, numNames).toArray(new String[numNames - 1]) : new String[0];
  1.1822 +
  1.1823 +        // Create an array whose first element is the number of remaining
  1.1824 +        // elements.  This serves as a selector into a ChoiceFormat pattern from
  1.1825 +        // the resource.  The second and third elements are the main name and
  1.1826 +        // the qualifier; if there are no qualifiers, the third element is
  1.1827 +        // unused by the format pattern.
  1.1828 +        Object[] displayNames = {
  1.1829 +            new Integer(qualifierNames.length != 0 ? 2 : 1),
  1.1830 +            mainName,
  1.1831 +            // We could also just call formatList() and have it handle the empty
  1.1832 +            // list case, but this is more efficient, and we want it to be
  1.1833 +            // efficient since all the language-only locales will not have any
  1.1834 +            // qualifiers.
  1.1835 +            qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null
  1.1836 +        };
  1.1837 +
  1.1838 +        if (displayNamePattern != null) {
  1.1839 +            return new MessageFormat(displayNamePattern).format(displayNames);
  1.1840 +        }
  1.1841 +        else {
  1.1842 +            // If we cannot get the message format pattern, then we use a simple
  1.1843 +            // hard-coded pattern.  This should not occur in practice unless the
  1.1844 +            // installation is missing some core files (FormatData etc.).
  1.1845 +            StringBuilder result = new StringBuilder();
  1.1846 +            result.append((String)displayNames[1]);
  1.1847 +            if (displayNames.length > 2) {
  1.1848 +                result.append(" (");
  1.1849 +                result.append((String)displayNames[2]);
  1.1850 +                result.append(')');
  1.1851 +            }
  1.1852 +            return result.toString();
  1.1853 +        }
  1.1854 +    }
  1.1855 +
  1.1856 +    /**
  1.1857 +     * Overrides Cloneable.
  1.1858 +     */
  1.1859 +    public Object clone()
  1.1860 +    {
  1.1861 +        try {
  1.1862 +            Locale that = (Locale)super.clone();
  1.1863 +            return that;
  1.1864 +        } catch (CloneNotSupportedException e) {
  1.1865 +            throw new InternalError();
  1.1866 +        }
  1.1867 +    }
  1.1868 +
  1.1869 +    /**
  1.1870 +     * Override hashCode.
  1.1871 +     * Since Locales are often used in hashtables, caches the value
  1.1872 +     * for speed.
  1.1873 +     */
  1.1874 +    @Override
  1.1875 +    public int hashCode() {
  1.1876 +        int hc = hashCodeValue;
  1.1877 +        if (hc == 0) {
  1.1878 +            hc = baseLocale.hashCode();
  1.1879 +            if (localeExtensions != null) {
  1.1880 +                hc ^= localeExtensions.hashCode();
  1.1881 +            }
  1.1882 +            hashCodeValue = hc;
  1.1883 +        }
  1.1884 +        return hc;
  1.1885 +    }
  1.1886 +
  1.1887 +    // Overrides
  1.1888 +
  1.1889 +    /**
  1.1890 +     * Returns true if this Locale is equal to another object.  A Locale is
  1.1891 +     * deemed equal to another Locale with identical language, script, country,
  1.1892 +     * variant and extensions, and unequal to all other objects.
  1.1893 +     *
  1.1894 +     * @return true if this Locale is equal to the specified object.
  1.1895 +     */
  1.1896 +    @Override
  1.1897 +    public boolean equals(Object obj) {
  1.1898 +        if (this == obj)                      // quick check
  1.1899 +            return true;
  1.1900 +        if (!(obj instanceof Locale))
  1.1901 +            return false;
  1.1902 +        BaseLocale otherBase = ((Locale)obj).baseLocale;
  1.1903 +        if (!baseLocale.equals(otherBase)) {
  1.1904 +            return false;
  1.1905 +        }
  1.1906 +        if (localeExtensions == null) {
  1.1907 +            return ((Locale)obj).localeExtensions == null;
  1.1908 +        }
  1.1909 +        return localeExtensions.equals(((Locale)obj).localeExtensions);
  1.1910 +    }
  1.1911 +
  1.1912 +    // ================= privates =====================================
  1.1913 +
  1.1914 +    private transient BaseLocale baseLocale;
  1.1915 +    private transient LocaleExtensions localeExtensions;
  1.1916 +
  1.1917 +    /**
  1.1918 +     * Calculated hashcode
  1.1919 +     */
  1.1920 +    private transient volatile int hashCodeValue = 0;
  1.1921 +
  1.1922 +    private static Locale defaultLocale = null;
  1.1923 +    private static Locale defaultDisplayLocale = null;
  1.1924 +    private static Locale defaultFormatLocale = null;
  1.1925 +
  1.1926 +    /**
  1.1927 +     * Return an array of the display names of the variant.
  1.1928 +     * @param bundle the ResourceBundle to use to get the display names
  1.1929 +     * @return an array of display names, possible of zero length.
  1.1930 +     */
  1.1931 +    private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
  1.1932 +        // Split the variant name into tokens separated by '_'.
  1.1933 +        StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
  1.1934 +        String[] names = new String[tokenizer.countTokens()];
  1.1935 +
  1.1936 +        // For each variant token, lookup the display name.  If
  1.1937 +        // not found, use the variant name itself.
  1.1938 +        for (int i=0; i<names.length; ++i) {
  1.1939 +            names[i] = getDisplayString(tokenizer.nextToken(),
  1.1940 +                                inLocale, DISPLAY_VARIANT);
  1.1941 +        }
  1.1942 +
  1.1943 +        return names;
  1.1944 +    }
  1.1945 +
  1.1946 +    /**
  1.1947 +     * Format a list using given pattern strings.
  1.1948 +     * If either of the patterns is null, then a the list is
  1.1949 +     * formatted by concatenation with the delimiter ','.
  1.1950 +     * @param stringList the list of strings to be formatted.
  1.1951 +     * @param listPattern should create a MessageFormat taking 0-3 arguments
  1.1952 +     * and formatting them into a list.
  1.1953 +     * @param listCompositionPattern should take 2 arguments
  1.1954 +     * and is used by composeList.
  1.1955 +     * @return a string representing the list.
  1.1956 +     */
  1.1957 +    private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
  1.1958 +        // If we have no list patterns, compose the list in a simple,
  1.1959 +        // non-localized way.
  1.1960 +        if (listPattern == null || listCompositionPattern == null) {
  1.1961 +            StringBuffer result = new StringBuffer();
  1.1962 +            for (int i=0; i<stringList.length; ++i) {
  1.1963 +                if (i>0) result.append(',');
  1.1964 +                result.append(stringList[i]);
  1.1965 +            }
  1.1966 +            return result.toString();
  1.1967 +        }
  1.1968 +
  1.1969 +        // Compose the list down to three elements if necessary
  1.1970 +        if (stringList.length > 3) {
  1.1971 +            MessageFormat format = new MessageFormat(listCompositionPattern);
  1.1972 +            stringList = composeList(format, stringList);
  1.1973 +        }
  1.1974 +
  1.1975 +        // Rebuild the argument list with the list length as the first element
  1.1976 +        Object[] args = new Object[stringList.length + 1];
  1.1977 +        System.arraycopy(stringList, 0, args, 1, stringList.length);
  1.1978 +        args[0] = new Integer(stringList.length);
  1.1979 +
  1.1980 +        // Format it using the pattern in the resource
  1.1981 +        MessageFormat format = new MessageFormat(listPattern);
  1.1982 +        return format.format(args);
  1.1983 +    }
  1.1984 +
  1.1985 +    /**
  1.1986 +     * Given a list of strings, return a list shortened to three elements.
  1.1987 +     * Shorten it by applying the given format to the first two elements
  1.1988 +     * recursively.
  1.1989 +     * @param format a format which takes two arguments
  1.1990 +     * @param list a list of strings
  1.1991 +     * @return if the list is three elements or shorter, the same list;
  1.1992 +     * otherwise, a new list of three elements.
  1.1993 +     */
  1.1994 +    private static String[] composeList(MessageFormat format, String[] list) {
  1.1995 +        if (list.length <= 3) return list;
  1.1996 +
  1.1997 +        // Use the given format to compose the first two elements into one
  1.1998 +        String[] listItems = { list[0], list[1] };
  1.1999 +        String newItem = format.format(listItems);
  1.2000 +
  1.2001 +        // Form a new list one element shorter
  1.2002 +        String[] newList = new String[list.length-1];
  1.2003 +        System.arraycopy(list, 2, newList, 1, newList.length-1);
  1.2004 +        newList[0] = newItem;
  1.2005 +
  1.2006 +        // Recurse
  1.2007 +        return composeList(format, newList);
  1.2008 +    }
  1.2009 +
  1.2010 +    /**
  1.2011 +     * @serialField language    String
  1.2012 +     *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
  1.2013 +     * @serialField country     String
  1.2014 +     *      country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
  1.2015 +     * @serialField variant     String
  1.2016 +     *      variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>)
  1.2017 +     * @serialField hashcode    int
  1.2018 +     *      deprecated, for forward compatibility only
  1.2019 +     * @serialField script      String
  1.2020 +     *      script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>)
  1.2021 +     * @serialField extensions  String
  1.2022 +     *      canonical representation of extensions, that is,
  1.2023 +     *      BCP47 extensions in alphabetical order followed by
  1.2024 +     *      BCP47 private use subtags, all in lower case letters
  1.2025 +     *      separated by HYPHEN-MINUS characters.
  1.2026 +     *      (See <a href="java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>,
  1.2027 +     *      <a href="java/util/Locale.html#getExtension(char)">getExtension(char)</a>)
  1.2028 +     */
  1.2029 +    private static final ObjectStreamField[] serialPersistentFields = {
  1.2030 +        new ObjectStreamField("language", String.class),
  1.2031 +        new ObjectStreamField("country", String.class),
  1.2032 +        new ObjectStreamField("variant", String.class),
  1.2033 +        new ObjectStreamField("hashcode", int.class),
  1.2034 +        new ObjectStreamField("script", String.class),
  1.2035 +        new ObjectStreamField("extensions", String.class),
  1.2036 +    };
  1.2037 +
  1.2038 +    /**
  1.2039 +     * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>.
  1.2040 +     * @param out the <code>ObjectOutputStream</code> to write
  1.2041 +     * @throws IOException
  1.2042 +     * @since 1.7
  1.2043 +     */
  1.2044 +    private void writeObject(ObjectOutputStream out) throws IOException {
  1.2045 +        ObjectOutputStream.PutField fields = out.putFields();
  1.2046 +        fields.put("language", baseLocale.getLanguage());
  1.2047 +        fields.put("script", baseLocale.getScript());
  1.2048 +        fields.put("country", baseLocale.getRegion());
  1.2049 +        fields.put("variant", baseLocale.getVariant());
  1.2050 +        fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID());
  1.2051 +        fields.put("hashcode", -1); // place holder just for backward support
  1.2052 +        out.writeFields();
  1.2053 +    }
  1.2054 +
  1.2055 +    /**
  1.2056 +     * Deserializes this <code>Locale</code>.
  1.2057 +     * @param in the <code>ObjectInputStream</code> to read
  1.2058 +     * @throws IOException
  1.2059 +     * @throws ClassNotFoundException
  1.2060 +     * @throws IllformdLocaleException
  1.2061 +     * @since 1.7
  1.2062 +     */
  1.2063 +    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
  1.2064 +        ObjectInputStream.GetField fields = in.readFields();
  1.2065 +        String language = (String)fields.get("language", "");
  1.2066 +        String script = (String)fields.get("script", "");
  1.2067 +        String country = (String)fields.get("country", "");
  1.2068 +        String variant = (String)fields.get("variant", "");
  1.2069 +        String extStr = (String)fields.get("extensions", "");
  1.2070 +        baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
  1.2071 +        if (extStr.length() > 0) {
  1.2072 +            try {
  1.2073 +                InternalLocaleBuilder bldr = new InternalLocaleBuilder();
  1.2074 +                bldr.setExtensions(extStr);
  1.2075 +                localeExtensions = bldr.getLocaleExtensions();
  1.2076 +            } catch (LocaleSyntaxException e) {
  1.2077 +                throw new IllformedLocaleException(e.getMessage());
  1.2078 +            }
  1.2079 +        } else {
  1.2080 +            localeExtensions = null;
  1.2081 +        }
  1.2082 +    }
  1.2083 +
  1.2084 +    /**
  1.2085 +     * Returns a cached <code>Locale</code> instance equivalent to
  1.2086 +     * the deserialized <code>Locale</code>. When serialized
  1.2087 +     * language, country and variant fields read from the object data stream
  1.2088 +     * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
  1.2089 +     * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
  1.2090 +     * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
  1.2091 +     * type is "thai"). See <a href="Locale.html#special_cases_constructor"/>Special Cases</a>
  1.2092 +     * for more information.
  1.2093 +     *
  1.2094 +     * @return an instance of <code>Locale</code> equivalent to
  1.2095 +     * the deserialized <code>Locale</code>.
  1.2096 +     * @throws java.io.ObjectStreamException
  1.2097 +     */
  1.2098 +    private Object readResolve() throws java.io.ObjectStreamException {
  1.2099 +        return getInstance(baseLocale.getLanguage(), baseLocale.getScript(),
  1.2100 +                baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
  1.2101 +    }
  1.2102 +
  1.2103 +    private static volatile String[] isoLanguages = null;
  1.2104 +
  1.2105 +    private static volatile String[] isoCountries = null;
  1.2106 +
  1.2107 +    private static String convertOldISOCodes(String language) {
  1.2108 +        // we accept both the old and the new ISO codes for the languages whose ISO
  1.2109 +        // codes have changed, but we always store the OLD code, for backward compatibility
  1.2110 +        language = LocaleUtils.toLowerString(language).intern();
  1.2111 +        if (language == "he") {
  1.2112 +            return "iw";
  1.2113 +        } else if (language == "yi") {
  1.2114 +            return "ji";
  1.2115 +        } else if (language == "id") {
  1.2116 +            return "in";
  1.2117 +        } else {
  1.2118 +            return language;
  1.2119 +        }
  1.2120 +    }
  1.2121 +
  1.2122 +    private static LocaleExtensions getCompatibilityExtensions(String language,
  1.2123 +                                                               String script,
  1.2124 +                                                               String country,
  1.2125 +                                                               String variant) {
  1.2126 +        LocaleExtensions extensions = null;
  1.2127 +        // Special cases for backward compatibility support
  1.2128 +        if (LocaleUtils.caseIgnoreMatch(language, "ja")
  1.2129 +                && script.length() == 0
  1.2130 +                && LocaleUtils.caseIgnoreMatch(country, "jp")
  1.2131 +                && "JP".equals(variant)) {
  1.2132 +            // ja_JP_JP -> u-ca-japanese (calendar = japanese)
  1.2133 +            extensions = LocaleExtensions.CALENDAR_JAPANESE;
  1.2134 +        } else if (LocaleUtils.caseIgnoreMatch(language, "th")
  1.2135 +                && script.length() == 0
  1.2136 +                && LocaleUtils.caseIgnoreMatch(country, "th")
  1.2137 +                && "TH".equals(variant)) {
  1.2138 +            // th_TH_TH -> u-nu-thai (numbersystem = thai)
  1.2139 +            extensions = LocaleExtensions.NUMBER_THAI;
  1.2140 +        }
  1.2141 +        return extensions;
  1.2142 +    }
  1.2143 +
  1.2144 +    /**
  1.2145 +     * Obtains a localized locale names from a LocaleNameProvider
  1.2146 +     * implementation.
  1.2147 +     */
  1.2148 +    private static class LocaleNameGetter
  1.2149 +        implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
  1.2150 +        private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
  1.2151 +
  1.2152 +        public String getObject(LocaleNameProvider localeNameProvider,
  1.2153 +                                Locale locale,
  1.2154 +                                String key,
  1.2155 +                                Object... params) {
  1.2156 +            assert params.length == 2;
  1.2157 +            int type = (Integer)params[0];
  1.2158 +            String code = (String)params[1];
  1.2159 +
  1.2160 +            switch(type) {
  1.2161 +            case DISPLAY_LANGUAGE:
  1.2162 +                return localeNameProvider.getDisplayLanguage(code, locale);
  1.2163 +            case DISPLAY_COUNTRY:
  1.2164 +                return localeNameProvider.getDisplayCountry(code, locale);
  1.2165 +            case DISPLAY_VARIANT:
  1.2166 +                return localeNameProvider.getDisplayVariant(code, locale);
  1.2167 +            case DISPLAY_SCRIPT:
  1.2168 +                return localeNameProvider.getDisplayScript(code, locale);
  1.2169 +            default:
  1.2170 +                assert false; // shouldn't happen
  1.2171 +            }
  1.2172 +
  1.2173 +            return null;
  1.2174 +        }
  1.2175 +    }
  1.2176 +
  1.2177 +    /**
  1.2178 +     * Enum for locale categories.  These locale categories are used to get/set
  1.2179 +     * the default locale for the specific functionality represented by the
  1.2180 +     * category.
  1.2181 +     *
  1.2182 +     * @see #getDefault(Locale.Category)
  1.2183 +     * @see #setDefault(Locale.Category, Locale)
  1.2184 +     * @since 1.7
  1.2185 +     */
  1.2186 +    public enum Category {
  1.2187 +
  1.2188 +        /**
  1.2189 +         * Category used to represent the default locale for
  1.2190 +         * displaying user interfaces.
  1.2191 +         */
  1.2192 +        DISPLAY("user.language.display",
  1.2193 +                "user.script.display",
  1.2194 +                "user.country.display",
  1.2195 +                "user.variant.display"),
  1.2196 +
  1.2197 +        /**
  1.2198 +         * Category used to represent the default locale for
  1.2199 +         * formatting dates, numbers, and/or currencies.
  1.2200 +         */
  1.2201 +        FORMAT("user.language.format",
  1.2202 +               "user.script.format",
  1.2203 +               "user.country.format",
  1.2204 +               "user.variant.format");
  1.2205 +
  1.2206 +        Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
  1.2207 +            this.languageKey = languageKey;
  1.2208 +            this.scriptKey = scriptKey;
  1.2209 +            this.countryKey = countryKey;
  1.2210 +            this.variantKey = variantKey;
  1.2211 +        }
  1.2212 +
  1.2213 +        final String languageKey;
  1.2214 +        final String scriptKey;
  1.2215 +        final String countryKey;
  1.2216 +        final String variantKey;
  1.2217 +    }
  1.2218 +
  1.2219 +    /**
  1.2220 +     * <code>Builder</code> is used to build instances of <code>Locale</code>
  1.2221 +     * from values configured by the setters.  Unlike the <code>Locale</code>
  1.2222 +     * constructors, the <code>Builder</code> checks if a value configured by a
  1.2223 +     * setter satisfies the syntax requirements defined by the <code>Locale</code>
  1.2224 +     * class.  A <code>Locale</code> object created by a <code>Builder</code> is
  1.2225 +     * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
  1.2226 +     * without losing information.
  1.2227 +     *
  1.2228 +     * <p><b>Note:</b> The <code>Locale</code> class does not provide any
  1.2229 +     * syntactic restrictions on variant, while BCP 47 requires each variant
  1.2230 +     * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
  1.2231 +     * alphanumerics.  The method <code>setVariant</code> throws
  1.2232 +     * <code>IllformedLocaleException</code> for a variant that does not satisfy
  1.2233 +     * this restriction. If it is necessary to support such a variant, use a
  1.2234 +     * Locale constructor.  However, keep in mind that a <code>Locale</code>
  1.2235 +     * object created this way might lose the variant information when
  1.2236 +     * transformed to a BCP 47 language tag.
  1.2237 +     *
  1.2238 +     * <p>The following example shows how to create a <code>Locale</code> object
  1.2239 +     * with the <code>Builder</code>.
  1.2240 +     * <blockquote>
  1.2241 +     * <pre>
  1.2242 +     *     Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
  1.2243 +     * </pre>
  1.2244 +     * </blockquote>
  1.2245 +     *
  1.2246 +     * <p>Builders can be reused; <code>clear()</code> resets all
  1.2247 +     * fields to their default values.
  1.2248 +     *
  1.2249 +     * @see Locale#forLanguageTag
  1.2250 +     * @since 1.7
  1.2251 +     */
  1.2252 +    public static final class Builder {
  1.2253 +        private final InternalLocaleBuilder localeBuilder;
  1.2254 +
  1.2255 +        /**
  1.2256 +         * Constructs an empty Builder. The default value of all
  1.2257 +         * fields, extensions, and private use information is the
  1.2258 +         * empty string.
  1.2259 +         */
  1.2260 +        public Builder() {
  1.2261 +            localeBuilder = new InternalLocaleBuilder();
  1.2262 +        }
  1.2263 +
  1.2264 +        /**
  1.2265 +         * Resets the <code>Builder</code> to match the provided
  1.2266 +         * <code>locale</code>.  Existing state is discarded.
  1.2267 +         *
  1.2268 +         * <p>All fields of the locale must be well-formed, see {@link Locale}.
  1.2269 +         *
  1.2270 +         * <p>Locales with any ill-formed fields cause
  1.2271 +         * <code>IllformedLocaleException</code> to be thrown, except for the
  1.2272 +         * following three cases which are accepted for compatibility
  1.2273 +         * reasons:<ul>
  1.2274 +         * <li>Locale("ja", "JP", "JP") is treated as "ja-JP-u-ca-japanese"
  1.2275 +         * <li>Locale("th", "TH", "TH") is treated as "th-TH-u-nu-thai"
  1.2276 +         * <li>Locale("no", "NO", "NY") is treated as "nn-NO"</ul>
  1.2277 +         *
  1.2278 +         * @param locale the locale
  1.2279 +         * @return This builder.
  1.2280 +         * @throws IllformedLocaleException if <code>locale</code> has
  1.2281 +         * any ill-formed fields.
  1.2282 +         * @throws NullPointerException if <code>locale</code> is null.
  1.2283 +         */
  1.2284 +        public Builder setLocale(Locale locale) {
  1.2285 +            try {
  1.2286 +                localeBuilder.setLocale(locale.baseLocale, locale.localeExtensions);
  1.2287 +            } catch (LocaleSyntaxException e) {
  1.2288 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2289 +            }
  1.2290 +            return this;
  1.2291 +        }
  1.2292 +
  1.2293 +        /**
  1.2294 +         * Resets the Builder to match the provided IETF BCP 47
  1.2295 +         * language tag.  Discards the existing state.  Null and the
  1.2296 +         * empty string cause the builder to be reset, like {@link
  1.2297 +         * #clear}.  Grandfathered tags (see {@link
  1.2298 +         * Locale#forLanguageTag}) are converted to their canonical
  1.2299 +         * form before being processed.  Otherwise, the language tag
  1.2300 +         * must be well-formed (see {@link Locale}) or an exception is
  1.2301 +         * thrown (unlike <code>Locale.forLanguageTag</code>, which
  1.2302 +         * just discards ill-formed and following portions of the
  1.2303 +         * tag).
  1.2304 +         *
  1.2305 +         * @param languageTag the language tag
  1.2306 +         * @return This builder.
  1.2307 +         * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed
  1.2308 +         * @see Locale#forLanguageTag(String)
  1.2309 +         */
  1.2310 +        public Builder setLanguageTag(String languageTag) {
  1.2311 +            ParseStatus sts = new ParseStatus();
  1.2312 +            LanguageTag tag = LanguageTag.parse(languageTag, sts);
  1.2313 +            if (sts.isError()) {
  1.2314 +                throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
  1.2315 +            }
  1.2316 +            localeBuilder.setLanguageTag(tag);
  1.2317 +            return this;
  1.2318 +        }
  1.2319 +
  1.2320 +        /**
  1.2321 +         * Sets the language.  If <code>language</code> is the empty string or
  1.2322 +         * null, the language in this <code>Builder</code> is removed.  Otherwise,
  1.2323 +         * the language must be <a href="./Locale.html#def_language">well-formed</a>
  1.2324 +         * or an exception is thrown.
  1.2325 +         *
  1.2326 +         * <p>The typical language value is a two or three-letter language
  1.2327 +         * code as defined in ISO639.
  1.2328 +         *
  1.2329 +         * @param language the language
  1.2330 +         * @return This builder.
  1.2331 +         * @throws IllformedLocaleException if <code>language</code> is ill-formed
  1.2332 +         */
  1.2333 +        public Builder setLanguage(String language) {
  1.2334 +            try {
  1.2335 +                localeBuilder.setLanguage(language);
  1.2336 +            } catch (LocaleSyntaxException e) {
  1.2337 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2338 +            }
  1.2339 +            return this;
  1.2340 +        }
  1.2341 +
  1.2342 +        /**
  1.2343 +         * Sets the script. If <code>script</code> is null or the empty string,
  1.2344 +         * the script in this <code>Builder</code> is removed.
  1.2345 +         * Otherwise, the script must be <a href="./Locale.html#def_script">well-formed</a> or an
  1.2346 +         * exception is thrown.
  1.2347 +         *
  1.2348 +         * <p>The typical script value is a four-letter script code as defined by ISO 15924.
  1.2349 +         *
  1.2350 +         * @param script the script
  1.2351 +         * @return This builder.
  1.2352 +         * @throws IllformedLocaleException if <code>script</code> is ill-formed
  1.2353 +         */
  1.2354 +        public Builder setScript(String script) {
  1.2355 +            try {
  1.2356 +                localeBuilder.setScript(script);
  1.2357 +            } catch (LocaleSyntaxException e) {
  1.2358 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2359 +            }
  1.2360 +            return this;
  1.2361 +        }
  1.2362 +
  1.2363 +        /**
  1.2364 +         * Sets the region.  If region is null or the empty string, the region
  1.2365 +         * in this <code>Builder</code> is removed.  Otherwise,
  1.2366 +         * the region must be <a href="./Locale.html#def_region">well-formed</a> or an
  1.2367 +         * exception is thrown.
  1.2368 +         *
  1.2369 +         * <p>The typical region value is a two-letter ISO 3166 code or a
  1.2370 +         * three-digit UN M.49 area code.
  1.2371 +         *
  1.2372 +         * <p>The country value in the <code>Locale</code> created by the
  1.2373 +         * <code>Builder</code> is always normalized to upper case.
  1.2374 +         *
  1.2375 +         * @param region the region
  1.2376 +         * @return This builder.
  1.2377 +         * @throws IllformedLocaleException if <code>region</code> is ill-formed
  1.2378 +         */
  1.2379 +        public Builder setRegion(String region) {
  1.2380 +            try {
  1.2381 +                localeBuilder.setRegion(region);
  1.2382 +            } catch (LocaleSyntaxException e) {
  1.2383 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2384 +            }
  1.2385 +            return this;
  1.2386 +        }
  1.2387 +
  1.2388 +        /**
  1.2389 +         * Sets the variant.  If variant is null or the empty string, the
  1.2390 +         * variant in this <code>Builder</code> is removed.  Otherwise, it
  1.2391 +         * must consist of one or more <a href="./Locale.html#def_variant">well-formed</a>
  1.2392 +         * subtags, or an exception is thrown.
  1.2393 +         *
  1.2394 +         * <p><b>Note:</b> This method checks if <code>variant</code>
  1.2395 +         * satisfies the IETF BCP 47 variant subtag's syntax requirements,
  1.2396 +         * and normalizes the value to lowercase letters.  However,
  1.2397 +         * the <code>Locale</code> class does not impose any syntactic
  1.2398 +         * restriction on variant, and the variant value in
  1.2399 +         * <code>Locale</code> is case sensitive.  To set such a variant,
  1.2400 +         * use a Locale constructor.
  1.2401 +         *
  1.2402 +         * @param variant the variant
  1.2403 +         * @return This builder.
  1.2404 +         * @throws IllformedLocaleException if <code>variant</code> is ill-formed
  1.2405 +         */
  1.2406 +        public Builder setVariant(String variant) {
  1.2407 +            try {
  1.2408 +                localeBuilder.setVariant(variant);
  1.2409 +            } catch (LocaleSyntaxException e) {
  1.2410 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2411 +            }
  1.2412 +            return this;
  1.2413 +        }
  1.2414 +
  1.2415 +        /**
  1.2416 +         * Sets the extension for the given key. If the value is null or the
  1.2417 +         * empty string, the extension is removed.  Otherwise, the extension
  1.2418 +         * must be <a href="./Locale.html#def_extensions">well-formed</a> or an exception
  1.2419 +         * is thrown.
  1.2420 +         *
  1.2421 +         * <p><b>Note:</b> The key {@link Locale#UNICODE_LOCALE_EXTENSION
  1.2422 +         * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension.
  1.2423 +         * Setting a value for this key replaces any existing Unicode locale key/type
  1.2424 +         * pairs with those defined in the extension.
  1.2425 +         *
  1.2426 +         * <p><b>Note:</b> The key {@link Locale#PRIVATE_USE_EXTENSION
  1.2427 +         * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be
  1.2428 +         * well-formed, the value for this key needs only to have subtags of one to
  1.2429 +         * eight alphanumeric characters, not two to eight as in the general case.
  1.2430 +         *
  1.2431 +         * @param key the extension key
  1.2432 +         * @param value the extension value
  1.2433 +         * @return This builder.
  1.2434 +         * @throws IllformedLocaleException if <code>key</code> is illegal
  1.2435 +         * or <code>value</code> is ill-formed
  1.2436 +         * @see #setUnicodeLocaleKeyword(String, String)
  1.2437 +         */
  1.2438 +        public Builder setExtension(char key, String value) {
  1.2439 +            try {
  1.2440 +                localeBuilder.setExtension(key, value);
  1.2441 +            } catch (LocaleSyntaxException e) {
  1.2442 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2443 +            }
  1.2444 +            return this;
  1.2445 +        }
  1.2446 +
  1.2447 +        /**
  1.2448 +         * Sets the Unicode locale keyword type for the given key.  If the type
  1.2449 +         * is null, the Unicode keyword is removed.  Otherwise, the key must be
  1.2450 +         * non-null and both key and type must be <a
  1.2451 +         * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
  1.2452 +         * is thrown.
  1.2453 +         *
  1.2454 +         * <p>Keys and types are converted to lower case.
  1.2455 +         *
  1.2456 +         * <p><b>Note</b>:Setting the 'u' extension via {@link #setExtension}
  1.2457 +         * replaces all Unicode locale keywords with those defined in the
  1.2458 +         * extension.
  1.2459 +         *
  1.2460 +         * @param key the Unicode locale key
  1.2461 +         * @param type the Unicode locale type
  1.2462 +         * @return This builder.
  1.2463 +         * @throws IllformedLocaleException if <code>key</code> or <code>type</code>
  1.2464 +         * is ill-formed
  1.2465 +         * @throws NullPointerException if <code>key</code> is null
  1.2466 +         * @see #setExtension(char, String)
  1.2467 +         */
  1.2468 +        public Builder setUnicodeLocaleKeyword(String key, String type) {
  1.2469 +            try {
  1.2470 +                localeBuilder.setUnicodeLocaleKeyword(key, type);
  1.2471 +            } catch (LocaleSyntaxException e) {
  1.2472 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2473 +            }
  1.2474 +            return this;
  1.2475 +        }
  1.2476 +
  1.2477 +        /**
  1.2478 +         * Adds a unicode locale attribute, if not already present, otherwise
  1.2479 +         * has no effect.  The attribute must not be null and must be <a
  1.2480 +         * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
  1.2481 +         * is thrown.
  1.2482 +         *
  1.2483 +         * @param attribute the attribute
  1.2484 +         * @return This builder.
  1.2485 +         * @throws NullPointerException if <code>attribute</code> is null
  1.2486 +         * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
  1.2487 +         * @see #setExtension(char, String)
  1.2488 +         */
  1.2489 +        public Builder addUnicodeLocaleAttribute(String attribute) {
  1.2490 +            try {
  1.2491 +                localeBuilder.addUnicodeLocaleAttribute(attribute);
  1.2492 +            } catch (LocaleSyntaxException e) {
  1.2493 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2494 +            }
  1.2495 +            return this;
  1.2496 +        }
  1.2497 +
  1.2498 +        /**
  1.2499 +         * Removes a unicode locale attribute, if present, otherwise has no
  1.2500 +         * effect.  The attribute must not be null and must be <a
  1.2501 +         * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
  1.2502 +         * is thrown.
  1.2503 +         *
  1.2504 +         * <p>Attribute comparision for removal is case-insensitive.
  1.2505 +         *
  1.2506 +         * @param attribute the attribute
  1.2507 +         * @return This builder.
  1.2508 +         * @throws NullPointerException if <code>attribute</code> is null
  1.2509 +         * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
  1.2510 +         * @see #setExtension(char, String)
  1.2511 +         */
  1.2512 +        public Builder removeUnicodeLocaleAttribute(String attribute) {
  1.2513 +            try {
  1.2514 +                localeBuilder.removeUnicodeLocaleAttribute(attribute);
  1.2515 +            } catch (LocaleSyntaxException e) {
  1.2516 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
  1.2517 +            }
  1.2518 +            return this;
  1.2519 +        }
  1.2520 +
  1.2521 +        /**
  1.2522 +         * Resets the builder to its initial, empty state.
  1.2523 +         *
  1.2524 +         * @return This builder.
  1.2525 +         */
  1.2526 +        public Builder clear() {
  1.2527 +            localeBuilder.clear();
  1.2528 +            return this;
  1.2529 +        }
  1.2530 +
  1.2531 +        /**
  1.2532 +         * Resets the extensions to their initial, empty state.
  1.2533 +         * Language, script, region and variant are unchanged.
  1.2534 +         *
  1.2535 +         * @return This builder.
  1.2536 +         * @see #setExtension(char, String)
  1.2537 +         */
  1.2538 +        public Builder clearExtensions() {
  1.2539 +            localeBuilder.clearExtensions();
  1.2540 +            return this;
  1.2541 +        }
  1.2542 +
  1.2543 +        /**
  1.2544 +         * Returns an instance of <code>Locale</code> created from the fields set
  1.2545 +         * on this builder.
  1.2546 +         *
  1.2547 +         * <p>This applies the conversions listed in {@link Locale#forLanguageTag}
  1.2548 +         * when constructing a Locale. (Grandfathered tags are handled in
  1.2549 +         * {@link #setLanguageTag}.)
  1.2550 +         *
  1.2551 +         * @return A Locale.
  1.2552 +         */
  1.2553 +        public Locale build() {
  1.2554 +            BaseLocale baseloc = localeBuilder.getBaseLocale();
  1.2555 +            LocaleExtensions extensions = localeBuilder.getLocaleExtensions();
  1.2556 +            if (extensions == null && baseloc.getVariant().length() > 0) {
  1.2557 +                extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(),
  1.2558 +                        baseloc.getRegion(), baseloc.getVariant());
  1.2559 +            }
  1.2560 +            return Locale.getInstance(baseloc, extensions);
  1.2561 +        }
  1.2562 +    }
  1.2563 +}