History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/util/Locale.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/util/Locale.java+2560−0
@@ -0,0 +1,2560 @@
1+/*
2+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+/*
27+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29+ *
30+ * The original version of this source code and documentation
31+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
32+ * subsidiary of IBM. These materials are provided under terms
33+ * of a License Agreement between Taligent and Sun. This technology
34+ * is protected by multiple US and International patents.
35+ *
36+ * This notice and attribution to Taligent may not be removed.
37+ * Taligent is a registered trademark of Taligent, Inc.
38+ *
39+ */
40+
41+package java.util;
42+
43+import java.io.IOException;
44+import java.io.ObjectInputStream;
45+import java.io.ObjectOutputStream;
46+import java.io.ObjectStreamField;
47+import java.io.Serializable;
48+import java.security.AccessController;
49+import java.text.MessageFormat;
50+import java.util.spi.LocaleNameProvider;
51+
52+import sun.security.action.GetPropertyAction;
53+import sun.util.LocaleServiceProviderPool;
54+import sun.util.locale.BaseLocale;
55+import sun.util.locale.InternalLocaleBuilder;
56+import sun.util.locale.LanguageTag;
57+import sun.util.locale.LocaleExtensions;
58+import sun.util.locale.LocaleObjectCache;
59+import sun.util.locale.LocaleSyntaxException;
60+import sun.util.locale.LocaleUtils;
61+import sun.util.locale.ParseStatus;
62+import sun.util.locale.UnicodeLocaleExtension;
63+import sun.util.resources.LocaleData;
64+import sun.util.resources.OpenListResourceBundle;
65+
66+/**
67+ * A <code>Locale</code> object represents a specific geographical, political,
68+ * or cultural region. An operation that requires a <code>Locale</code> to perform
69+ * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
70+ * to tailor information for the user. For example, displaying a number
71+ * is a locale-sensitive operation&mdash; the number should be formatted
72+ * according to the customs and conventions of the user's native country,
73+ * region, or culture.
74+ *
75+ * <p> The <code>Locale</code> class implements identifiers
76+ * interchangeable with BCP 47 (IETF BCP 47, "Tags for Identifying
77+ * Languages"), with support for the LDML (UTS#35, "Unicode Locale
78+ * Data Markup Language") BCP 47-compatible extensions for locale data
79+ * exchange.
80+ *
81+ * <p> A <code>Locale</code> object logically consists of the fields
82+ * described below.
83+ *
84+ * <dl>
85+ * <dt><a name="def_language"/><b>language</b></dt>
86+ *
87+ * <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
88+ * language subtags up to 8 alpha letters (for future enhancements).
89+ * When a language has both an alpha-2 code and an alpha-3 code, the
90+ * alpha-2 code must be used. You can find a full list of valid
91+ * language codes in the IANA Language Subtag Registry (search for
92+ * "Type: language"). The language field is case insensitive, but
93+ * <code>Locale</code> always canonicalizes to lower case.</dd><br>
94+ *
95+ * <dd>Well-formed language values have the form
96+ * <code>[a-zA-Z]{2,8}</code>. Note that this is not the the full
97+ * BCP47 language production, since it excludes extlang. They are
98+ * not needed since modern three-letter language codes replace
99+ * them.</dd><br>
100+ *
101+ * <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
102+ *
103+ * <dt><a name="def_script"/><b>script</b></dt>
104+ *
105+ * <dd>ISO 15924 alpha-4 script code. You can find a full list of
106+ * valid script codes in the IANA Language Subtag Registry (search
107+ * for "Type: script"). The script field is case insensitive, but
108+ * <code>Locale</code> always canonicalizes to title case (the first
109+ * letter is upper case and the rest of the letters are lower
110+ * case).</dd><br>
111+ *
112+ * <dd>Well-formed script values have the form
113+ * <code>[a-zA-Z]{4}</code></dd><br>
114+ *
115+ * <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
116+ *
117+ * <dt><a name="def_region"/><b>country (region)</b></dt>
118+ *
119+ * <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
120+ * You can find a full list of valid country and region codes in the
121+ * IANA Language Subtag Registry (search for "Type: region"). The
122+ * country (region) field is case insensitive, but
123+ * <code>Locale</code> always canonicalizes to upper case.</dd><br>
124+ *
125+ * <dd>Well-formed country/region values have
126+ * the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd><br>
127+ *
128+ * <dd>Example: "US" (United States), "FR" (France), "029"
129+ * (Caribbean)</dd><br>
130+ *
131+ * <dt><a name="def_variant"/><b>variant</b></dt>
132+ *
133+ * <dd>Any arbitrary value used to indicate a variation of a
134+ * <code>Locale</code>. Where there are two or more variant values
135+ * each indicating its own semantics, these values should be ordered
136+ * by importance, with most important first, separated by
137+ * underscore('_'). The variant field is case sensitive.</dd><br>
138+ *
139+ * <dd>Note: IETF BCP 47 places syntactic restrictions on variant
140+ * subtags. Also BCP 47 subtags are strictly used to indicate
141+ * additional variations that define a language or its dialects that
142+ * are not covered by any combinations of language, script and
143+ * region subtags. You can find a full list of valid variant codes
144+ * in the IANA Language Subtag Registry (search for "Type: variant").
145+ *
146+ * <p>However, the variant field in <code>Locale</code> has
147+ * historically been used for any kind of variation, not just
148+ * language variations. For example, some supported variants
149+ * available in Java SE Runtime Environments indicate alternative
150+ * cultural behaviors such as calendar type or number script. In
151+ * BCP 47 this kind of information, which does not identify the
152+ * language, is supported by extension subtags or private use
153+ * subtags.</dd><br>
154+ *
155+ * <dd>Well-formed variant values have the form <code>SUBTAG
156+ * (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
157+ * [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
158+ * uses hyphen ('-') as a delimiter, this is more lenient).</dd><br>
159+ *
160+ * <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
161+ *
162+ * <dt><a name="def_extensions"/><b>extensions</b></dt>
163+ *
164+ * <dd>A map from single character keys to string values, indicating
165+ * extensions apart from language identification. The extensions in
166+ * <code>Locale</code> implement the semantics and syntax of BCP 47
167+ * extension subtags and private use subtags. The extensions are
168+ * case insensitive, but <code>Locale</code> canonicalizes all
169+ * extension keys and values to lower case. Note that extensions
170+ * cannot have empty values.</dd><br>
171+ *
172+ * <dd>Well-formed keys are single characters from the set
173+ * <code>[0-9a-zA-Z]</code>. Well-formed values have the form
174+ * <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
175+ * <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
176+ * <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
177+ * single-character subtags).</dd><br>
178+ *
179+ * <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
180+ * key="x"/value="java-1-7"</dd>
181+ * </dl>
182+ *
183+ * <b>Note:</b> Although BCP 47 requires field values to be registered
184+ * in the IANA Language Subtag Registry, the <code>Locale</code> class
185+ * does not provide any validation features. The <code>Builder</code>
186+ * only checks if an individual field satisfies the syntactic
187+ * requirement (is well-formed), but does not validate the value
188+ * itself. See {@link Builder} for details.
189+ *
190+ * <h4><a name="def_locale_extension">Unicode locale/language extension</h4>
191+ *
192+ * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
193+ * attributes and keywords to override or refine the default behavior
194+ * associated with a locale. A keyword is represented by a pair of
195+ * key and type. For example, "nu-thai" indicates that Thai local
196+ * digits (value:"thai") should be used for formatting numbers
197+ * (key:"nu").
198+ *
199+ * <p>The keywords are mapped to a BCP 47 extension value using the
200+ * extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}). The above
201+ * example, "nu-thai", becomes the extension "u-nu-thai".code
202+ *
203+ * <p>Thus, when a <code>Locale</code> object contains Unicode locale
204+ * attributes and keywords,
205+ * <code>getExtension(UNICODE_LOCALE_EXTENSION)</code> will return a
206+ * String representing this information, for example, "nu-thai". The
207+ * <code>Locale</code> class also provides {@link
208+ * #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and
209+ * {@link #getUnicodeLocaleType} which allow you to access Unicode
210+ * locale attributes and key/type pairs directly. When represented as
211+ * a string, the Unicode Locale Extension lists attributes
212+ * alphabetically, followed by key/type sequences with keys listed
213+ * alphabetically (the order of subtags comprising a key's type is
214+ * fixed when the type is defined)
215+ *
216+ * <p>A well-formed locale key has the form
217+ * <code>[0-9a-zA-Z]{2}</code>. A well-formed locale type has the
218+ * form <code>"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*</code> (it
219+ * can be empty, or a series of subtags 3-8 alphanums in length). A
220+ * well-formed locale attribute has the form
221+ * <code>[0-9a-zA-Z]{3,8}</code> (it is a single subtag with the same
222+ * form as a locale type subtag).
223+ *
224+ * <p>The Unicode locale extension specifies optional behavior in
225+ * locale-sensitive services. Although the LDML specification defines
226+ * various keys and values, actual locale-sensitive service
227+ * implementations in a Java Runtime Environment might not support any
228+ * particular Unicode locale attributes or key/type pairs.
229+ *
230+ * <h4>Creating a Locale</h4>
231+ *
232+ * <p>There are several different ways to create a <code>Locale</code>
233+ * object.
234+ *
235+ * <h5>Builder</h5>
236+ *
237+ * <p>Using {@link Builder} you can construct a <code>Locale</code> object
238+ * that conforms to BCP 47 syntax.
239+ *
240+ * <h5>Constructors</h5>
241+ *
242+ * <p>The <code>Locale</code> class provides three constructors:
243+ * <blockquote>
244+ * <pre>
245+ * {@link #Locale(String language)}
246+ * {@link #Locale(String language, String country)}
247+ * {@link #Locale(String language, String country, String variant)}
248+ * </pre>
249+ * </blockquote>
250+ * These constructors allow you to create a <code>Locale</code> object
251+ * with language, country and variant, but you cannot specify
252+ * script or extensions.
253+ *
254+ * <h5>Factory Methods</h5>
255+ *
256+ * <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
257+ * object for a well-formed BCP 47 language tag.
258+ *
259+ * <h5>Locale Constants</h5>
260+ *
261+ * <p>The <code>Locale</code> class provides a number of convenient constants
262+ * that you can use to create <code>Locale</code> objects for commonly used
263+ * locales. For example, the following creates a <code>Locale</code> object
264+ * for the United States:
265+ * <blockquote>
266+ * <pre>
267+ * Locale.US
268+ * </pre>
269+ * </blockquote>
270+ *
271+ * <h4>Use of Locale</h4>
272+ *
273+ * <p>Once you've created a <code>Locale</code> you can query it for information
274+ * about itself. Use <code>getCountry</code> to get the country (or region)
275+ * code and <code>getLanguage</code> to get the language code.
276+ * You can use <code>getDisplayCountry</code> to get the
277+ * name of the country suitable for displaying to the user. Similarly,
278+ * you can use <code>getDisplayLanguage</code> to get the name of
279+ * the language suitable for displaying to the user. Interestingly,
280+ * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
281+ * and have two versions: one that uses the default locale and one
282+ * that uses the locale specified as an argument.
283+ *
284+ * <p>The Java Platform provides a number of classes that perform locale-sensitive
285+ * operations. For example, the <code>NumberFormat</code> class formats
286+ * numbers, currency, and percentages in a locale-sensitive manner. Classes
287+ * such as <code>NumberFormat</code> have several convenience methods
288+ * for creating a default object of that type. For example, the
289+ * <code>NumberFormat</code> class provides these three convenience methods
290+ * for creating a default <code>NumberFormat</code> object:
291+ * <blockquote>
292+ * <pre>
293+ * NumberFormat.getInstance()
294+ * NumberFormat.getCurrencyInstance()
295+ * NumberFormat.getPercentInstance()
296+ * </pre>
297+ * </blockquote>
298+ * Each of these methods has two variants; one with an explicit locale
299+ * and one without; the latter uses the default locale:
300+ * <blockquote>
301+ * <pre>
302+ * NumberFormat.getInstance(myLocale)
303+ * NumberFormat.getCurrencyInstance(myLocale)
304+ * NumberFormat.getPercentInstance(myLocale)
305+ * </pre>
306+ * </blockquote>
307+ * A <code>Locale</code> is the mechanism for identifying the kind of object
308+ * (<code>NumberFormat</code>) that you would like to get. The locale is
309+ * <STRONG>just</STRONG> a mechanism for identifying objects,
310+ * <STRONG>not</STRONG> a container for the objects themselves.
311+ *
312+ * <h4>Compatibility</h4>
313+ *
314+ * <p>In order to maintain compatibility with existing usage, Locale's
315+ * constructors retain their behavior prior to the Java Runtime
316+ * Environment version 1.7. The same is largely true for the
317+ * <code>toString</code> method. Thus Locale objects can continue to
318+ * be used as they were. In particular, clients who parse the output
319+ * of toString into language, country, and variant fields can continue
320+ * to do so (although this is strongly discouraged), although the
321+ * variant field will have additional information in it if script or
322+ * extensions are present.
323+ *
324+ * <p>In addition, BCP 47 imposes syntax restrictions that are not
325+ * imposed by Locale's constructors. This means that conversions
326+ * between some Locales and BCP 47 language tags cannot be made without
327+ * losing information. Thus <code>toLanguageTag</code> cannot
328+ * represent the state of locales whose language, country, or variant
329+ * do not conform to BCP 47.
330+ *
331+ * <p>Because of these issues, it is recommended that clients migrate
332+ * away from constructing non-conforming locales and use the
333+ * <code>forLanguageTag</code> and <code>Locale.Builder</code> APIs instead.
334+ * Clients desiring a string representation of the complete locale can
335+ * then always rely on <code>toLanguageTag</code> for this purpose.
336+ *
337+ * <h5><a name="special_cases_constructor"/>Special cases</h5>
338+ *
339+ * <p>For compatibility reasons, two
340+ * non-conforming locales are treated as special cases. These are
341+ * <b><tt>ja_JP_JP</tt></b> and <b><tt>th_TH_TH</tt></b>. These are ill-formed
342+ * in BCP 47 since the variants are too short. To ease migration to BCP 47,
343+ * these are treated specially during construction. These two cases (and only
344+ * these) cause a constructor to generate an extension, all other values behave
345+ * exactly as they did prior to Java 7.
346+ *
347+ * <p>Java has used <tt>ja_JP_JP</tt> to represent Japanese as used in
348+ * Japan together with the Japanese Imperial calendar. This is now
349+ * representable using a Unicode locale extension, by specifying the
350+ * Unicode locale key <tt>ca</tt> (for "calendar") and type
351+ * <tt>japanese</tt>. When the Locale constructor is called with the
352+ * arguments "ja", "JP", "JP", the extension "u-ca-japanese" is
353+ * automatically added.
354+ *
355+ * <p>Java has used <tt>th_TH_TH</tt> to represent Thai as used in
356+ * Thailand together with Thai digits. This is also now representable using
357+ * a Unicode locale extension, by specifying the Unicode locale key
358+ * <tt>nu</tt> (for "number") and value <tt>thai</tt>. When the Locale
359+ * constructor is called with the arguments "th", "TH", "TH", the
360+ * extension "u-nu-thai" is automatically added.
361+ *
362+ * <h5>Serialization</h5>
363+ *
364+ * <p>During serialization, writeObject writes all fields to the output
365+ * stream, including extensions.
366+ *
367+ * <p>During deserialization, readResolve adds extensions as described
368+ * in <a href="#special_cases_constructor">Special Cases</a>, only
369+ * for the two cases th_TH_TH and ja_JP_JP.
370+ *
371+ * <h5>Legacy language codes</h5>
372+ *
373+ * <p>Locale's constructor has always converted three language codes to
374+ * their earlier, obsoleted forms: <tt>he</tt> maps to <tt>iw</tt>,
375+ * <tt>yi</tt> maps to <tt>ji</tt>, and <tt>id</tt> maps to
376+ * <tt>in</tt>. This continues to be the case, in order to not break
377+ * backwards compatibility.
378+ *
379+ * <p>The APIs added in 1.7 map between the old and new language codes,
380+ * maintaining the old codes internal to Locale (so that
381+ * <code>getLanguage</code> and <code>toString</code> reflect the old
382+ * code), but using the new codes in the BCP 47 language tag APIs (so
383+ * that <code>toLanguageTag</code> reflects the new one). This
384+ * preserves the equivalence between Locales no matter which code or
385+ * API is used to construct them. Java's default resource bundle
386+ * lookup mechanism also implements this mapping, so that resources
387+ * can be named using either convention, see {@link ResourceBundle.Control}.
388+ *
389+ * <h5>Three-letter language/country(region) codes</h5>
390+ *
391+ * <p>The Locale constructors have always specified that the language
392+ * and the country param be two characters in length, although in
393+ * practice they have accepted any length. The specification has now
394+ * been relaxed to allow language codes of two to eight characters and
395+ * country (region) codes of two to three characters, and in
396+ * particular, three-letter language codes and three-digit region
397+ * codes as specified in the IANA Language Subtag Registry. For
398+ * compatibility, the implementation still does not impose a length
399+ * constraint.
400+ *
401+ * @see Builder
402+ * @see ResourceBundle
403+ * @see java.text.Format
404+ * @see java.text.NumberFormat
405+ * @see java.text.Collator
406+ * @author Mark Davis
407+ * @since 1.1
408+ */
409+public final class Locale implements Cloneable, Serializable {
410+
411+ static private final Cache LOCALECACHE = new Cache();
412+
413+ /** Useful constant for language.
414+ */
415+ static public final Locale ENGLISH = createConstant("en", "");
416+
417+ /** Useful constant for language.
418+ */
419+ static public final Locale FRENCH = createConstant("fr", "");
420+
421+ /** Useful constant for language.
422+ */
423+ static public final Locale GERMAN = createConstant("de", "");
424+
425+ /** Useful constant for language.
426+ */
427+ static public final Locale ITALIAN = createConstant("it", "");
428+
429+ /** Useful constant for language.
430+ */
431+ static public final Locale JAPANESE = createConstant("ja", "");
432+
433+ /** Useful constant for language.
434+ */
435+ static public final Locale KOREAN = createConstant("ko", "");
436+
437+ /** Useful constant for language.
438+ */
439+ static public final Locale CHINESE = createConstant("zh", "");
440+
441+ /** Useful constant for language.
442+ */
443+ static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
444+
445+ /** Useful constant for language.
446+ */
447+ static public final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
448+
449+ /** Useful constant for country.
450+ */
451+ static public final Locale FRANCE = createConstant("fr", "FR");
452+
453+ /** Useful constant for country.
454+ */
455+ static public final Locale GERMANY = createConstant("de", "DE");
456+
457+ /** Useful constant for country.
458+ */
459+ static public final Locale ITALY = createConstant("it", "IT");
460+
461+ /** Useful constant for country.
462+ */
463+ static public final Locale JAPAN = createConstant("ja", "JP");
464+
465+ /** Useful constant for country.
466+ */
467+ static public final Locale KOREA = createConstant("ko", "KR");
468+
469+ /** Useful constant for country.
470+ */
471+ static public final Locale CHINA = SIMPLIFIED_CHINESE;
472+
473+ /** Useful constant for country.
474+ */
475+ static public final Locale PRC = SIMPLIFIED_CHINESE;
476+
477+ /** Useful constant for country.
478+ */
479+ static public final Locale TAIWAN = TRADITIONAL_CHINESE;
480+
481+ /** Useful constant for country.
482+ */
483+ static public final Locale UK = createConstant("en", "GB");
484+
485+ /** Useful constant for country.
486+ */
487+ static public final Locale US = createConstant("en", "US");
488+
489+ /** Useful constant for country.
490+ */
491+ static public final Locale CANADA = createConstant("en", "CA");
492+
493+ /** Useful constant for country.
494+ */
495+ static public final Locale CANADA_FRENCH = createConstant("fr", "CA");
496+
497+ /**
498+ * Useful constant for the root locale. The root locale is the locale whose
499+ * language, country, and variant are empty ("") strings. This is regarded
500+ * as the base locale of all locales, and is used as the language/country
501+ * neutral locale for the locale sensitive operations.
502+ *
503+ * @since 1.6
504+ */
505+ static public final Locale ROOT = createConstant("", "");
506+
507+ /**
508+ * The key for the private use extension ('x').
509+ *
510+ * @see #getExtension(char)
511+ * @see Builder#setExtension(char, String)
512+ * @since 1.7
513+ */
514+ static public final char PRIVATE_USE_EXTENSION = 'x';
515+
516+ /**
517+ * The key for Unicode locale extension ('u').
518+ *
519+ * @see #getExtension(char)
520+ * @see Builder#setExtension(char, String)
521+ * @since 1.7
522+ */
523+ static public final char UNICODE_LOCALE_EXTENSION = 'u';
524+
525+ /** serialization ID
526+ */
527+ static final long serialVersionUID = 9149081749638150636L;
528+
529+ /**
530+ * Display types for retrieving localized names from the name providers.
531+ */
532+ private static final int DISPLAY_LANGUAGE = 0;
533+ private static final int DISPLAY_COUNTRY = 1;
534+ private static final int DISPLAY_VARIANT = 2;
535+ private static final int DISPLAY_SCRIPT = 3;
536+
537+ /**
538+ * Private constructor used by getInstance method
539+ */
540+ private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
541+ this.baseLocale = baseLocale;
542+ this.localeExtensions = extensions;
543+ }
544+
545+ /**
546+ * Construct a locale from language, country and variant.
547+ * This constructor normalizes the language value to lowercase and
548+ * the country value to uppercase.
549+ * <p>
550+ * <b>Note:</b>
551+ * <ul>
552+ * <li>ISO 639 is not a stable standard; some of the language codes it defines
553+ * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
554+ * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
555+ * API on Locale will return only the OLD codes.
556+ * <li>For backward compatibility reasons, this constructor does not make
557+ * any syntactic checks on the input.
558+ * <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
559+ * see <a href="#special_cases_constructor">Special Cases</a> for more information.
560+ * </ul>
561+ *
562+ * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
563+ * up to 8 characters in length. See the <code>Locale</code> class description about
564+ * valid language values.
565+ * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
566+ * See the <code>Locale</code> class description about valid country values.
567+ * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>.
568+ * See the <code>Locale</code> class description for the details.
569+ * @exception NullPointerException thrown if any argument is null.
570+ */
571+ public Locale(String language, String country, String variant) {
572+ if (language== null || country == null || variant == null) {
573+ throw new NullPointerException();
574+ }
575+ baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
576+ localeExtensions = getCompatibilityExtensions(language, "", country, variant);
577+ }
578+
579+ /**
580+ * Construct a locale from language and country.
581+ * This constructor normalizes the language value to lowercase and
582+ * the country value to uppercase.
583+ * <p>
584+ * <b>Note:</b>
585+ * <ul>
586+ * <li>ISO 639 is not a stable standard; some of the language codes it defines
587+ * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
588+ * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
589+ * API on Locale will return only the OLD codes.
590+ * <li>For backward compatibility reasons, this constructor does not make
591+ * any syntactic checks on the input.
592+ * </ul>
593+ *
594+ * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
595+ * up to 8 characters in length. See the <code>Locale</code> class description about
596+ * valid language values.
597+ * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
598+ * See the <code>Locale</code> class description about valid country values.
599+ * @exception NullPointerException thrown if either argument is null.
600+ */
601+ public Locale(String language, String country) {
602+ this(language, country, "");
603+ }
604+
605+ /**
606+ * Construct a locale from a language code.
607+ * This constructor normalizes the language value to lowercase.
608+ * <p>
609+ * <b>Note:</b>
610+ * <ul>
611+ * <li>ISO 639 is not a stable standard; some of the language codes it defines
612+ * (specifically "iw", "ji", and "in") have changed. This constructor accepts both the
613+ * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
614+ * API on Locale will return only the OLD codes.
615+ * <li>For backward compatibility reasons, this constructor does not make
616+ * any syntactic checks on the input.
617+ * </ul>
618+ *
619+ * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
620+ * up to 8 characters in length. See the <code>Locale</code> class description about
621+ * valid language values.
622+ * @exception NullPointerException thrown if argument is null.
623+ * @since 1.4
624+ */
625+ public Locale(String language) {
626+ this(language, "", "");
627+ }
628+
629+ /**
630+ * This method must be called only for creating the Locale.*
631+ * constants due to making shortcuts.
632+ */
633+ private static Locale createConstant(String lang, String country) {
634+ BaseLocale base = BaseLocale.createInstance(lang, country);
635+ return getInstance(base, null);
636+ }
637+
638+ /**
639+ * Returns a <code>Locale</code> constructed from the given
640+ * <code>language</code>, <code>country</code> and
641+ * <code>variant</code>. If the same <code>Locale</code> instance
642+ * is available in the cache, then that instance is
643+ * returned. Otherwise, a new <code>Locale</code> instance is
644+ * created and cached.
645+ *
646+ * @param language lowercase 2 to 8 language code.
647+ * @param country uppercase two-letter ISO-3166 code and numric-3 UN M.49 area code.
648+ * @param variant vendor and browser specific code. See class description.
649+ * @return the <code>Locale</code> instance requested
650+ * @exception NullPointerException if any argument is null.
651+ */
652+ static Locale getInstance(String language, String country, String variant) {
653+ return getInstance(language, "", country, variant, null);
654+ }
655+
656+ static Locale getInstance(String language, String script, String country,
657+ String variant, LocaleExtensions extensions) {
658+ if (language== null || script == null || country == null || variant == null) {
659+ throw new NullPointerException();
660+ }
661+
662+ if (extensions == null) {
663+ extensions = getCompatibilityExtensions(language, script, country, variant);
664+ }
665+
666+ BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
667+ return getInstance(baseloc, extensions);
668+ }
669+
670+ static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
671+ LocaleKey key = new LocaleKey(baseloc, extensions);
672+ return LOCALECACHE.get(key);
673+ }
674+
675+ private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
676+ private Cache() {
677+ }
678+
679+ @Override
680+ protected Locale createObject(LocaleKey key) {
681+ return new Locale(key.base, key.exts);
682+ }
683+ }
684+
685+ private static final class LocaleKey {
686+ private final BaseLocale base;
687+ private final LocaleExtensions exts;
688+ private final int hash;
689+
690+ private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) {
691+ base = baseLocale;
692+ exts = extensions;
693+
694+ // Calculate the hash value here because it's always used.
695+ int h = base.hashCode();
696+ if (exts != null) {
697+ h ^= exts.hashCode();
698+ }
699+ hash = h;
700+ }
701+
702+ @Override
703+ public boolean equals(Object obj) {
704+ if (this == obj) {
705+ return true;
706+ }
707+ if (!(obj instanceof LocaleKey)) {
708+ return false;
709+ }
710+ LocaleKey other = (LocaleKey)obj;
711+ if (hash != other.hash || !base.equals(other.base)) {
712+ return false;
713+ }
714+ if (exts == null) {
715+ return other.exts == null;
716+ }
717+ return exts.equals(other.exts);
718+ }
719+
720+ @Override
721+ public int hashCode() {
722+ return hash;
723+ }
724+ }
725+
726+ /**
727+ * Gets the current value of the default locale for this instance
728+ * of the Java Virtual Machine.
729+ * <p>
730+ * The Java Virtual Machine sets the default locale during startup
731+ * based on the host environment. It is used by many locale-sensitive
732+ * methods if no locale is explicitly specified.
733+ * It can be changed using the
734+ * {@link #setDefault(java.util.Locale) setDefault} method.
735+ *
736+ * @return the default locale for this instance of the Java Virtual Machine
737+ */
738+ public static Locale getDefault() {
739+ // do not synchronize this method - see 4071298
740+ // it's OK if more than one default locale happens to be created
741+ if (defaultLocale == null) {
742+ initDefault();
743+ }
744+ return defaultLocale;
745+ }
746+
747+ /**
748+ * Gets the current value of the default locale for the specified Category
749+ * for this instance of the Java Virtual Machine.
750+ * <p>
751+ * The Java Virtual Machine sets the default locale during startup based
752+ * on the host environment. It is used by many locale-sensitive methods
753+ * if no locale is explicitly specified. It can be changed using the
754+ * setDefault(Locale.Category, Locale) method.
755+ *
756+ * @param category - the specified category to get the default locale
757+ * @throws NullPointerException - if category is null
758+ * @return the default locale for the specified Category for this instance
759+ * of the Java Virtual Machine
760+ * @see #setDefault(Locale.Category, Locale)
761+ * @since 1.7
762+ */
763+ public static Locale getDefault(Locale.Category category) {
764+ // do not synchronize this method - see 4071298
765+ // it's OK if more than one default locale happens to be created
766+ switch (category) {
767+ case DISPLAY:
768+ if (defaultDisplayLocale == null) {
769+ initDefault(category);
770+ }
771+ return defaultDisplayLocale;
772+ case FORMAT:
773+ if (defaultFormatLocale == null) {
774+ initDefault(category);
775+ }
776+ return defaultFormatLocale;
777+ default:
778+ assert false: "Unknown Category";
779+ }
780+ return getDefault();
781+ }
782+
783+ private static void initDefault() {
784+ String language, region, script, country, variant;
785+ language = AccessController.doPrivileged(
786+ new GetPropertyAction("user.language", "en"));
787+ // for compatibility, check for old user.region property
788+ region = AccessController.doPrivileged(
789+ new GetPropertyAction("user.region"));
790+ if (region != null) {
791+ // region can be of form country, country_variant, or _variant
792+ int i = region.indexOf('_');
793+ if (i >= 0) {
794+ country = region.substring(0, i);
795+ variant = region.substring(i + 1);
796+ } else {
797+ country = region;
798+ variant = "";
799+ }
800+ script = "";
801+ } else {
802+ script = AccessController.doPrivileged(
803+ new GetPropertyAction("user.script", ""));
804+ country = AccessController.doPrivileged(
805+ new GetPropertyAction("user.country", ""));
806+ variant = AccessController.doPrivileged(
807+ new GetPropertyAction("user.variant", ""));
808+ }
809+ defaultLocale = getInstance(language, script, country, variant, null);
810+ }
811+
812+ private static void initDefault(Locale.Category category) {
813+ // make sure defaultLocale is initialized
814+ if (defaultLocale == null) {
815+ initDefault();
816+ }
817+
818+ Locale defaultCategoryLocale = getInstance(
819+ AccessController.doPrivileged(
820+ new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
821+ AccessController.doPrivileged(
822+ new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
823+ AccessController.doPrivileged(
824+ new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
825+ AccessController.doPrivileged(
826+ new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
827+ null);
828+
829+ switch (category) {
830+ case DISPLAY:
831+ defaultDisplayLocale = defaultCategoryLocale;
832+ break;
833+ case FORMAT:
834+ defaultFormatLocale = defaultCategoryLocale;
835+ break;
836+ }
837+ }
838+
839+ /**
840+ * Sets the default locale for this instance of the Java Virtual Machine.
841+ * This does not affect the host locale.
842+ * <p>
843+ * If there is a security manager, its <code>checkPermission</code>
844+ * method is called with a <code>PropertyPermission("user.language", "write")</code>
845+ * permission before the default locale is changed.
846+ * <p>
847+ * The Java Virtual Machine sets the default locale during startup
848+ * based on the host environment. It is used by many locale-sensitive
849+ * methods if no locale is explicitly specified.
850+ * <p>
851+ * Since changing the default locale may affect many different areas
852+ * of functionality, this method should only be used if the caller
853+ * is prepared to reinitialize locale-sensitive code running
854+ * within the same Java Virtual Machine.
855+ * <p>
856+ * By setting the default locale with this method, all of the default
857+ * locales for each Category are also set to the specified default locale.
858+ *
859+ * @throws SecurityException
860+ * if a security manager exists and its
861+ * <code>checkPermission</code> method doesn't allow the operation.
862+ * @throws NullPointerException if <code>newLocale</code> is null
863+ * @param newLocale the new default locale
864+ * @see SecurityManager#checkPermission
865+ * @see java.util.PropertyPermission
866+ */
867+ public static synchronized void setDefault(Locale newLocale) {
868+ setDefault(Category.DISPLAY, newLocale);
869+ setDefault(Category.FORMAT, newLocale);
870+ defaultLocale = newLocale;
871+ }
872+
873+ /**
874+ * Sets the default locale for the specified Category for this instance
875+ * of the Java Virtual Machine. This does not affect the host locale.
876+ * <p>
877+ * If there is a security manager, its checkPermission method is called
878+ * with a PropertyPermission("user.language", "write") permission before
879+ * the default locale is changed.
880+ * <p>
881+ * The Java Virtual Machine sets the default locale during startup based
882+ * on the host environment. It is used by many locale-sensitive methods
883+ * if no locale is explicitly specified.
884+ * <p>
885+ * Since changing the default locale may affect many different areas of
886+ * functionality, this method should only be used if the caller is
887+ * prepared to reinitialize locale-sensitive code running within the
888+ * same Java Virtual Machine.
889+ * <p>
890+ *
891+ * @param category - the specified category to set the default locale
892+ * @param newLocale - the new default locale
893+ * @throws SecurityException - if a security manager exists and its
894+ * checkPermission method doesn't allow the operation.
895+ * @throws NullPointerException - if category and/or newLocale is null
896+ * @see SecurityManager#checkPermission(java.security.Permission)
897+ * @see PropertyPermission
898+ * @see #getDefault(Locale.Category)
899+ * @since 1.7
900+ */
901+ public static synchronized void setDefault(Locale.Category category,
902+ Locale newLocale) {
903+ if (category == null)
904+ throw new NullPointerException("Category cannot be NULL");
905+ if (newLocale == null)
906+ throw new NullPointerException("Can't set default locale to NULL");
907+
908+ SecurityManager sm = System.getSecurityManager();
909+ if (sm != null) sm.checkPermission(new PropertyPermission
910+ ("user.language", "write"));
911+ switch (category) {
912+ case DISPLAY:
913+ defaultDisplayLocale = newLocale;
914+ break;
915+ case FORMAT:
916+ defaultFormatLocale = newLocale;
917+ break;
918+ default:
919+ assert false: "Unknown Category";
920+ }
921+ }
922+
923+ /**
924+ * Returns an array of all installed locales.
925+ * The returned array represents the union of locales supported
926+ * by the Java runtime environment and by installed
927+ * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
928+ * implementations. It must contain at least a <code>Locale</code>
929+ * instance equal to {@link java.util.Locale#US Locale.US}.
930+ *
931+ * @return An array of installed locales.
932+ */
933+ public static Locale[] getAvailableLocales() {
934+ return LocaleServiceProviderPool.getAllAvailableLocales();
935+ }
936+
937+ /**
938+ * Returns a list of all 2-letter country codes defined in ISO 3166.
939+ * Can be used to create Locales.
940+ * <p>
941+ * <b>Note:</b> The <code>Locale</code> class also supports other codes for
942+ * country (region), such as 3-letter numeric UN M.49 area codes.
943+ * Therefore, the list returned by this method does not contain ALL valid
944+ * codes that can be used to create Locales.
945+ */
946+ public static String[] getISOCountries() {
947+ if (isoCountries == null) {
948+ isoCountries = getISO2Table(LocaleISOData.isoCountryTable);
949+ }
950+ String[] result = new String[isoCountries.length];
951+ System.arraycopy(isoCountries, 0, result, 0, isoCountries.length);
952+ return result;
953+ }
954+
955+ /**
956+ * Returns a list of all 2-letter language codes defined in ISO 639.
957+ * Can be used to create Locales.
958+ * <p>
959+ * <b>Note:</b>
960+ * <ul>
961+ * <li>ISO 639 is not a stable standard&mdash; some languages' codes have changed.
962+ * The list this function returns includes both the new and the old codes for the
963+ * languages whose codes have changed.
964+ * <li>The <code>Locale</code> class also supports language codes up to
965+ * 8 characters in length. Therefore, the list returned by this method does
966+ * not contain ALL valid codes that can be used to create Locales.
967+ * </ul>
968+ */
969+ public static String[] getISOLanguages() {
970+ if (isoLanguages == null) {
971+ isoLanguages = getISO2Table(LocaleISOData.isoLanguageTable);
972+ }
973+ String[] result = new String[isoLanguages.length];
974+ System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
975+ return result;
976+ }
977+
978+ private static final String[] getISO2Table(String table) {
979+ int len = table.length() / 5;
980+ String[] isoTable = new String[len];
981+ for (int i = 0, j = 0; i < len; i++, j += 5) {
982+ isoTable[i] = table.substring(j, j + 2);
983+ }
984+ return isoTable;
985+ }
986+
987+ /**
988+ * Returns the language code of this Locale.
989+ *
990+ * <p><b>Note:</b> ISO 639 is not a stable standard&mdash; some languages' codes have changed.
991+ * Locale's constructor recognizes both the new and the old codes for the languages
992+ * whose codes have changed, but this function always returns the old code. If you
993+ * want to check for a specific language whose code has changed, don't do
994+ * <pre>
995+ * if (locale.getLanguage().equals("he")) // BAD!
996+ * ...
997+ * </pre>
998+ * Instead, do
999+ * <pre>
1000+ * if (locale.getLanguage().equals(new Locale("he").getLanguage()))
1001+ * ...
1002+ * </pre>
1003+ * @return The language code, or the empty string if none is defined.
1004+ * @see #getDisplayLanguage
1005+ */
1006+ public String getLanguage() {
1007+ return baseLocale.getLanguage();
1008+ }
1009+
1010+ /**
1011+ * Returns the script for this locale, which should
1012+ * either be the empty string or an ISO 15924 4-letter script
1013+ * code. The first letter is uppercase and the rest are
1014+ * lowercase, for example, 'Latn', 'Cyrl'.
1015+ *
1016+ * @return The script code, or the empty string if none is defined.
1017+ * @see #getDisplayScript
1018+ * @since 1.7
1019+ */
1020+ public String getScript() {
1021+ return baseLocale.getScript();
1022+ }
1023+
1024+ /**
1025+ * Returns the country/region code for this locale, which should
1026+ * either be the empty string, an uppercase ISO 3166 2-letter code,
1027+ * or a UN M.49 3-digit code.
1028+ *
1029+ * @return The country/region code, or the empty string if none is defined.
1030+ * @see #getDisplayCountry
1031+ */
1032+ public String getCountry() {
1033+ return baseLocale.getRegion();
1034+ }
1035+
1036+ /**
1037+ * Returns the variant code for this locale.
1038+ *
1039+ * @return The variant code, or the empty string if none is defined.
1040+ * @see #getDisplayVariant
1041+ */
1042+ public String getVariant() {
1043+ return baseLocale.getVariant();
1044+ }
1045+
1046+ /**
1047+ * Returns the extension (or private use) value associated with
1048+ * the specified key, or null if there is no extension
1049+ * associated with the key. To be well-formed, the key must be one
1050+ * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
1051+ * for example 'z' and 'Z' represent the same extension.
1052+ *
1053+ * @param key the extension key
1054+ * @return The extension, or null if this locale defines no
1055+ * extension for the specified key.
1056+ * @throws IllegalArgumentException if key is not well-formed
1057+ * @see #PRIVATE_USE_EXTENSION
1058+ * @see #UNICODE_LOCALE_EXTENSION
1059+ * @since 1.7
1060+ */
1061+ public String getExtension(char key) {
1062+ if (!LocaleExtensions.isValidKey(key)) {
1063+ throw new IllegalArgumentException("Ill-formed extension key: " + key);
1064+ }
1065+ return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key);
1066+ }
1067+
1068+ /**
1069+ * Returns the set of extension keys associated with this locale, or the
1070+ * empty set if it has no extensions. The returned set is unmodifiable.
1071+ * The keys will all be lower-case.
1072+ *
1073+ * @return The set of extension keys, or the empty set if this locale has
1074+ * no extensions.
1075+ * @since 1.7
1076+ */
1077+ public Set<Character> getExtensionKeys() {
1078+ if (localeExtensions == null) {
1079+ return Collections.emptySet();
1080+ }
1081+ return localeExtensions.getKeys();
1082+ }
1083+
1084+ /**
1085+ * Returns the set of unicode locale attributes associated with
1086+ * this locale, or the empty set if it has no attributes. The
1087+ * returned set is unmodifiable.
1088+ *
1089+ * @return The set of attributes.
1090+ * @since 1.7
1091+ */
1092+ public Set<String> getUnicodeLocaleAttributes() {
1093+ if (localeExtensions == null) {
1094+ return Collections.emptySet();
1095+ }
1096+ return localeExtensions.getUnicodeLocaleAttributes();
1097+ }
1098+
1099+ /**
1100+ * Returns the Unicode locale type associated with the specified Unicode locale key
1101+ * for this locale. Returns the empty string for keys that are defined with no type.
1102+ * Returns null if the key is not defined. Keys are case-insensitive. The key must
1103+ * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is
1104+ * thrown.
1105+ *
1106+ * @param key the Unicode locale key
1107+ * @return The Unicode locale type associated with the key, or null if the
1108+ * locale does not define the key.
1109+ * @throws IllegalArgumentException if the key is not well-formed
1110+ * @throws NullPointerException if <code>key</code> is null
1111+ * @since 1.7
1112+ */
1113+ public String getUnicodeLocaleType(String key) {
1114+ if (!UnicodeLocaleExtension.isKey(key)) {
1115+ throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
1116+ }
1117+ return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key);
1118+ }
1119+
1120+ /**
1121+ * Returns the set of Unicode locale keys defined by this locale, or the empty set if
1122+ * this locale has none. The returned set is immutable. Keys are all lower case.
1123+ *
1124+ * @return The set of Unicode locale keys, or the empty set if this locale has
1125+ * no Unicode locale keywords.
1126+ * @since 1.7
1127+ */
1128+ public Set<String> getUnicodeLocaleKeys() {
1129+ if (localeExtensions == null) {
1130+ return Collections.emptySet();
1131+ }
1132+ return localeExtensions.getUnicodeLocaleKeys();
1133+ }
1134+
1135+ /**
1136+ * Package locale method returning the Locale's BaseLocale,
1137+ * used by ResourceBundle
1138+ * @return base locale of this Locale
1139+ */
1140+ BaseLocale getBaseLocale() {
1141+ return baseLocale;
1142+ }
1143+
1144+ /**
1145+ * Package private method returning the Locale's LocaleExtensions,
1146+ * used by ResourceBundle.
1147+ * @return locale exnteions of this Locale,
1148+ * or {@code null} if no extensions are defined
1149+ */
1150+ LocaleExtensions getLocaleExtensions() {
1151+ return localeExtensions;
1152+ }
1153+
1154+ /**
1155+ * Returns a string representation of this <code>Locale</code>
1156+ * object, consisting of language, country, variant, script,
1157+ * and extensions as below:
1158+ * <p><blockquote>
1159+ * language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
1160+ * </blockquote>
1161+ *
1162+ * Language is always lower case, country is always upper case, script is always title
1163+ * case, and extensions are always lower case. Extensions and private use subtags
1164+ * will be in canonical order as explained in {@link #toLanguageTag}.
1165+ *
1166+ * <p>When the locale has neither script nor extensions, the result is the same as in
1167+ * Java 6 and prior.
1168+ *
1169+ * <p>If both the language and country fields are missing, this function will return
1170+ * the empty string, even if the variant, script, or extensions field is present (you
1171+ * can't have a locale with just a variant, the variant must accompany a well-formed
1172+ * language or country code).
1173+ *
1174+ * <p>If script or extensions are present and variant is missing, no underscore is
1175+ * added before the "#".
1176+ *
1177+ * <p>This behavior is designed to support debugging and to be compatible with
1178+ * previous uses of <code>toString</code> that expected language, country, and variant
1179+ * fields only. To represent a Locale as a String for interchange purposes, use
1180+ * {@link #toLanguageTag}.
1181+ *
1182+ * <p>Examples: <ul><tt>
1183+ * <li>en
1184+ * <li>de_DE
1185+ * <li>_GB
1186+ * <li>en_US_WIN
1187+ * <li>de__POSIX
1188+ * <li>zh_CN_#Hans
1189+ * <li>zh_TW_#Hant-x-java
1190+ * <li>th_TH_TH_#u-nu-thai</tt></ul>
1191+ *
1192+ * @return A string representation of the Locale, for debugging.
1193+ * @see #getDisplayName
1194+ * @see #toLanguageTag
1195+ */
1196+ @Override
1197+ public final String toString() {
1198+ boolean l = (baseLocale.getLanguage().length() != 0);
1199+ boolean s = (baseLocale.getScript().length() != 0);
1200+ boolean r = (baseLocale.getRegion().length() != 0);
1201+ boolean v = (baseLocale.getVariant().length() != 0);
1202+ boolean e = (localeExtensions != null && localeExtensions.getID().length() != 0);
1203+
1204+ StringBuilder result = new StringBuilder(baseLocale.getLanguage());
1205+ if (r || (l && (v || s || e))) {
1206+ result.append('_')
1207+ .append(baseLocale.getRegion()); // This may just append '_'
1208+ }
1209+ if (v && (l || r)) {
1210+ result.append('_')
1211+ .append(baseLocale.getVariant());
1212+ }
1213+
1214+ if (s && (l || r)) {
1215+ result.append("_#")
1216+ .append(baseLocale.getScript());
1217+ }
1218+
1219+ if (e && (l || r)) {
1220+ result.append('_');
1221+ if (!s) {
1222+ result.append('#');
1223+ }
1224+ result.append(localeExtensions.getID());
1225+ }
1226+
1227+ return result.toString();
1228+ }
1229+
1230+ /**
1231+ * Returns a well-formed IETF BCP 47 language tag representing
1232+ * this locale.
1233+ *
1234+ * <p>If this <code>Locale</code> has a language, country, or
1235+ * variant that does not satisfy the IETF BCP 47 language tag
1236+ * syntax requirements, this method handles these fields as
1237+ * described below:
1238+ *
1239+ * <p><b>Language:</b> If language is empty, or not <a
1240+ * href="#def_language" >well-formed</a> (for example "a" or
1241+ * "e2"), it will be emitted as "und" (Undetermined).
1242+ *
1243+ * <p><b>Country:</b> If country is not <a
1244+ * href="#def_region">well-formed</a> (for example "12" or "USA"),
1245+ * it will be omitted.
1246+ *
1247+ * <p><b>Variant:</b> If variant <b>is</b> <a
1248+ * href="#def_variant">well-formed</a>, each sub-segment
1249+ * (delimited by '-' or '_') is emitted as a subtag. Otherwise:
1250+ * <ul>
1251+ *
1252+ * <li>if all sub-segments match <code>[0-9a-zA-Z]{1,8}</code>
1253+ * (for example "WIN" or "Oracle_JDK_Standard_Edition"), the first
1254+ * ill-formed sub-segment and all following will be appended to
1255+ * the private use subtag. The first appended subtag will be
1256+ * "lvariant", followed by the sub-segments in order, separated by
1257+ * hyphen. For example, "x-lvariant-WIN",
1258+ * "Oracle-x-lvariant-JDK-Standard-Edition".
1259+ *
1260+ * <li>if any sub-segment does not match
1261+ * <code>[0-9a-zA-Z]{1,8}</code>, the variant will be truncated
1262+ * and the problematic sub-segment and all following sub-segments
1263+ * will be omitted. If the remainder is non-empty, it will be
1264+ * emitted as a private use subtag as above (even if the remainder
1265+ * turns out to be well-formed). For example,
1266+ * "Solaris_isjustthecoolestthing" is emitted as
1267+ * "x-lvariant-Solaris", not as "solaris".</li></ul>
1268+ *
1269+ * <p><b>Special Conversions:</b> Java supports some old locale
1270+ * representations, including deprecated ISO language codes,
1271+ * for compatibility. This method performs the following
1272+ * conversions:
1273+ * <ul>
1274+ *
1275+ * <li>Deprecated ISO language codes "iw", "ji", and "in" are
1276+ * converted to "he", "yi", and "id", respectively.
1277+ *
1278+ * <li>A locale with language "no", country "NO", and variant
1279+ * "NY", representing Norwegian Nynorsk (Norway), is converted
1280+ * to a language tag "nn-NO".</li></ul>
1281+ *
1282+ * <p><b>Note:</b> Although the language tag created by this
1283+ * method is well-formed (satisfies the syntax requirements
1284+ * defined by the IETF BCP 47 specification), it is not
1285+ * necessarily a valid BCP 47 language tag. For example,
1286+ * <pre>
1287+ * new Locale("xx", "YY").toLanguageTag();</pre>
1288+ *
1289+ * will return "xx-YY", but the language subtag "xx" and the
1290+ * region subtag "YY" are invalid because they are not registered
1291+ * in the IANA Language Subtag Registry.
1292+ *
1293+ * @return a BCP47 language tag representing the locale
1294+ * @see #forLanguageTag(String)
1295+ * @since 1.7
1296+ */
1297+ public String toLanguageTag() {
1298+ LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
1299+ StringBuilder buf = new StringBuilder();
1300+
1301+ String subtag = tag.getLanguage();
1302+ if (subtag.length() > 0) {
1303+ buf.append(LanguageTag.canonicalizeLanguage(subtag));
1304+ }
1305+
1306+ subtag = tag.getScript();
1307+ if (subtag.length() > 0) {
1308+ buf.append(LanguageTag.SEP);
1309+ buf.append(LanguageTag.canonicalizeScript(subtag));
1310+ }
1311+
1312+ subtag = tag.getRegion();
1313+ if (subtag.length() > 0) {
1314+ buf.append(LanguageTag.SEP);
1315+ buf.append(LanguageTag.canonicalizeRegion(subtag));
1316+ }
1317+
1318+ List<String>subtags = tag.getVariants();
1319+ for (String s : subtags) {
1320+ buf.append(LanguageTag.SEP);
1321+ // preserve casing
1322+ buf.append(s);
1323+ }
1324+
1325+ subtags = tag.getExtensions();
1326+ for (String s : subtags) {
1327+ buf.append(LanguageTag.SEP);
1328+ buf.append(LanguageTag.canonicalizeExtension(s));
1329+ }
1330+
1331+ subtag = tag.getPrivateuse();
1332+ if (subtag.length() > 0) {
1333+ if (buf.length() > 0) {
1334+ buf.append(LanguageTag.SEP);
1335+ }
1336+ buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
1337+ // preserve casing
1338+ buf.append(subtag);
1339+ }
1340+
1341+ return buf.toString();
1342+ }
1343+
1344+ /**
1345+ * Returns a locale for the specified IETF BCP 47 language tag string.
1346+ *
1347+ * <p>If the specified language tag contains any ill-formed subtags,
1348+ * the first such subtag and all following subtags are ignored. Compare
1349+ * to {@link Locale.Builder#setLanguageTag} which throws an exception
1350+ * in this case.
1351+ *
1352+ * <p>The following <b>conversions</b> are performed:<ul>
1353+ *
1354+ * <li>The language code "und" is mapped to language "".
1355+ *
1356+ * <li>The language codes "he", "yi", and "id" are mapped to "iw",
1357+ * "ji", and "in" respectively. (This is the same canonicalization
1358+ * that's done in Locale's constructors.)
1359+ *
1360+ * <li>The portion of a private use subtag prefixed by "lvariant",
1361+ * if any, is removed and appended to the variant field in the
1362+ * result locale (without case normalization). If it is then
1363+ * empty, the private use subtag is discarded:
1364+ *
1365+ * <pre>
1366+ * Locale loc;
1367+ * loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX");
1368+ * loc.getVariant(); // returns "POSIX"
1369+ * loc.getExtension('x'); // returns null
1370+ *
1371+ * loc = Locale.forLanguageTag("de-POSIX-x-URP-lvariant-Abc-Def");
1372+ * loc.getVariant(); // returns "POSIX_Abc_Def"
1373+ * loc.getExtension('x'); // returns "urp"
1374+ * </pre>
1375+ *
1376+ * <li>When the languageTag argument contains an extlang subtag,
1377+ * the first such subtag is used as the language, and the primary
1378+ * language subtag and other extlang subtags are ignored:
1379+ *
1380+ * <pre>
1381+ * Locale.forLanguageTag("ar-aao").getLanguage(); // returns "aao"
1382+ * Locale.forLanguageTag("en-abc-def-us").toString(); // returns "abc_US"
1383+ * </pre>
1384+ *
1385+ * <li>Case is normalized except for variant tags, which are left
1386+ * unchanged. Language is normalized to lower case, script to
1387+ * title case, country to upper case, and extensions to lower
1388+ * case.
1389+ *
1390+ * <li>If, after processing, the locale would exactly match either
1391+ * ja_JP_JP or th_TH_TH with no extensions, the appropriate
1392+ * extensions are added as though the constructor had been called:
1393+ *
1394+ * <pre>
1395+ * Locale.forLanguageTag("ja-JP-x-lvariant-JP").toLanguageTag();
1396+ * // returns "ja-JP-u-ca-japanese-x-lvariant-JP"
1397+ * Locale.forLanguageTag("th-TH-x-lvariant-TH").toLanguageTag();
1398+ * // returns "th-TH-u-nu-thai-x-lvariant-TH"
1399+ * <pre></ul>
1400+ *
1401+ * <p>This implements the 'Language-Tag' production of BCP47, and
1402+ * so supports grandfathered (regular and irregular) as well as
1403+ * private use language tags. Stand alone private use tags are
1404+ * represented as empty language and extension 'x-whatever',
1405+ * and grandfathered tags are converted to their canonical replacements
1406+ * where they exist.
1407+ *
1408+ * <p>Grandfathered tags with canonical replacements are as follows:
1409+ *
1410+ * <table>
1411+ * <tbody align="center">
1412+ * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>modern replacement</th></tr>
1413+ * <tr><td>art-lojban</td><td>&nbsp;</td><td>jbo</td></tr>
1414+ * <tr><td>i-ami</td><td>&nbsp;</td><td>ami</td></tr>
1415+ * <tr><td>i-bnn</td><td>&nbsp;</td><td>bnn</td></tr>
1416+ * <tr><td>i-hak</td><td>&nbsp;</td><td>hak</td></tr>
1417+ * <tr><td>i-klingon</td><td>&nbsp;</td><td>tlh</td></tr>
1418+ * <tr><td>i-lux</td><td>&nbsp;</td><td>lb</td></tr>
1419+ * <tr><td>i-navajo</td><td>&nbsp;</td><td>nv</td></tr>
1420+ * <tr><td>i-pwn</td><td>&nbsp;</td><td>pwn</td></tr>
1421+ * <tr><td>i-tao</td><td>&nbsp;</td><td>tao</td></tr>
1422+ * <tr><td>i-tay</td><td>&nbsp;</td><td>tay</td></tr>
1423+ * <tr><td>i-tsu</td><td>&nbsp;</td><td>tsu</td></tr>
1424+ * <tr><td>no-bok</td><td>&nbsp;</td><td>nb</td></tr>
1425+ * <tr><td>no-nyn</td><td>&nbsp;</td><td>nn</td></tr>
1426+ * <tr><td>sgn-BE-FR</td><td>&nbsp;</td><td>sfb</td></tr>
1427+ * <tr><td>sgn-BE-NL</td><td>&nbsp;</td><td>vgt</td></tr>
1428+ * <tr><td>sgn-CH-DE</td><td>&nbsp;</td><td>sgg</td></tr>
1429+ * <tr><td>zh-guoyu</td><td>&nbsp;</td><td>cmn</td></tr>
1430+ * <tr><td>zh-hakka</td><td>&nbsp;</td><td>hak</td></tr>
1431+ * <tr><td>zh-min-nan</td><td>&nbsp;</td><td>nan</td></tr>
1432+ * <tr><td>zh-xiang</td><td>&nbsp;</td><td>hsn</td></tr>
1433+ * </tbody>
1434+ * </table>
1435+ *
1436+ * <p>Grandfathered tags with no modern replacement will be
1437+ * converted as follows:
1438+ *
1439+ * <table>
1440+ * <tbody align="center">
1441+ * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>converts to</th></tr>
1442+ * <tr><td>cel-gaulish</td><td>&nbsp;</td><td>xtg-x-cel-gaulish</td></tr>
1443+ * <tr><td>en-GB-oed</td><td>&nbsp;</td><td>en-GB-x-oed</td></tr>
1444+ * <tr><td>i-default</td><td>&nbsp;</td><td>en-x-i-default</td></tr>
1445+ * <tr><td>i-enochian</td><td>&nbsp;</td><td>und-x-i-enochian</td></tr>
1446+ * <tr><td>i-mingo</td><td>&nbsp;</td><td>see-x-i-mingo</td></tr>
1447+ * <tr><td>zh-min</td><td>&nbsp;</td><td>nan-x-zh-min</td></tr>
1448+ * </tbody>
1449+ * </table>
1450+ *
1451+ * <p>For a list of all grandfathered tags, see the
1452+ * IANA Language Subtag Registry (search for "Type: grandfathered").
1453+ *
1454+ * <p><b>Note</b>: there is no guarantee that <code>toLanguageTag</code>
1455+ * and <code>forLanguageTag</code> will round-trip.
1456+ *
1457+ * @param languageTag the language tag
1458+ * @return The locale that best represents the language tag.
1459+ * @throws NullPointerException if <code>languageTag</code> is <code>null</code>
1460+ * @see #toLanguageTag()
1461+ * @see java.util.Locale.Builder#setLanguageTag(String)
1462+ * @since 1.7
1463+ */
1464+ public static Locale forLanguageTag(String languageTag) {
1465+ LanguageTag tag = LanguageTag.parse(languageTag, null);
1466+ InternalLocaleBuilder bldr = new InternalLocaleBuilder();
1467+ bldr.setLanguageTag(tag);
1468+ BaseLocale base = bldr.getBaseLocale();
1469+ LocaleExtensions exts = bldr.getLocaleExtensions();
1470+ if (exts == null && base.getVariant().length() > 0) {
1471+ exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(),
1472+ base.getRegion(), base.getVariant());
1473+ }
1474+ return getInstance(base, exts);
1475+ }
1476+
1477+ /**
1478+ * Returns a three-letter abbreviation of this locale's language.
1479+ * If the language matches an ISO 639-1 two-letter code, the
1480+ * corresponding ISO 639-2/T three-letter lowercase code is
1481+ * returned. The ISO 639-2 language codes can be found on-line,
1482+ * see "Codes for the Representation of Names of Languages Part 2:
1483+ * Alpha-3 Code". If the locale specifies a three-letter
1484+ * language, the language is returned as is. If the locale does
1485+ * not specify a language the empty string is returned.
1486+ *
1487+ * @return A three-letter abbreviation of this locale's language.
1488+ * @exception MissingResourceException Throws MissingResourceException if
1489+ * three-letter language abbreviation is not available for this locale.
1490+ */
1491+ public String getISO3Language() throws MissingResourceException {
1492+ String lang = baseLocale.getLanguage();
1493+ if (lang.length() == 3) {
1494+ return lang;
1495+ }
1496+
1497+ String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
1498+ if (language3 == null) {
1499+ throw new MissingResourceException("Couldn't find 3-letter language code for "
1500+ + lang, "FormatData_" + toString(), "ShortLanguage");
1501+ }
1502+ return language3;
1503+ }
1504+
1505+ /**
1506+ * Returns a three-letter abbreviation for this locale's country.
1507+ * If the country matches an ISO 3166-1 alpha-2 code, the
1508+ * corresponding ISO 3166-1 alpha-3 uppercase code is returned.
1509+ * If the locale doesn't specify a country, this will be the empty
1510+ * string.
1511+ *
1512+ * <p>The ISO 3166-1 codes can be found on-line.
1513+ *
1514+ * @return A three-letter abbreviation of this locale's country.
1515+ * @exception MissingResourceException Throws MissingResourceException if the
1516+ * three-letter country abbreviation is not available for this locale.
1517+ */
1518+ public String getISO3Country() throws MissingResourceException {
1519+ String country3 = getISO3Code(baseLocale.getRegion(), LocaleISOData.isoCountryTable);
1520+ if (country3 == null) {
1521+ throw new MissingResourceException("Couldn't find 3-letter country code for "
1522+ + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
1523+ }
1524+ return country3;
1525+ }
1526+
1527+ private static final String getISO3Code(String iso2Code, String table) {
1528+ int codeLength = iso2Code.length();
1529+ if (codeLength == 0) {
1530+ return "";
1531+ }
1532+
1533+ int tableLength = table.length();
1534+ int index = tableLength;
1535+ if (codeLength == 2) {
1536+ char c1 = iso2Code.charAt(0);
1537+ char c2 = iso2Code.charAt(1);
1538+ for (index = 0; index < tableLength; index += 5) {
1539+ if (table.charAt(index) == c1
1540+ && table.charAt(index + 1) == c2) {
1541+ break;
1542+ }
1543+ }
1544+ }
1545+ return index < tableLength ? table.substring(index + 2, index + 5) : null;
1546+ }
1547+
1548+ /**
1549+ * Returns a name for the locale's language that is appropriate for display to the
1550+ * user.
1551+ * If possible, the name returned will be localized for the default locale.
1552+ * For example, if the locale is fr_FR and the default locale
1553+ * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
1554+ * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
1555+ * If the name returned cannot be localized for the default locale,
1556+ * (say, we don't have a Japanese name for Croatian),
1557+ * this function falls back on the English name, and uses the ISO code as a last-resort
1558+ * value. If the locale doesn't specify a language, this function returns the empty string.
1559+ */
1560+ public final String getDisplayLanguage() {
1561+ return getDisplayLanguage(getDefault(Category.DISPLAY));
1562+ }
1563+
1564+ /**
1565+ * Returns a name for the locale's language that is appropriate for display to the
1566+ * user.
1567+ * If possible, the name returned will be localized according to inLocale.
1568+ * For example, if the locale is fr_FR and inLocale
1569+ * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
1570+ * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
1571+ * If the name returned cannot be localized according to inLocale,
1572+ * (say, we don't have a Japanese name for Croatian),
1573+ * this function falls back on the English name, and finally
1574+ * on the ISO code as a last-resort value. If the locale doesn't specify a language,
1575+ * this function returns the empty string.
1576+ *
1577+ * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1578+ */
1579+ public String getDisplayLanguage(Locale inLocale) {
1580+ return getDisplayString(baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
1581+ }
1582+
1583+ /**
1584+ * Returns a name for the the locale's script that is appropriate for display to
1585+ * the user. If possible, the name will be localized for the default locale. Returns
1586+ * the empty string if this locale doesn't specify a script code.
1587+ *
1588+ * @return the display name of the script code for the current default locale
1589+ * @since 1.7
1590+ */
1591+ public String getDisplayScript() {
1592+ return getDisplayScript(getDefault());
1593+ }
1594+
1595+ /**
1596+ * Returns a name for the locale's script that is appropriate
1597+ * for display to the user. If possible, the name will be
1598+ * localized for the given locale. Returns the empty string if
1599+ * this locale doesn't specify a script code.
1600+ *
1601+ * @return the display name of the script code for the current default locale
1602+ * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1603+ * @since 1.7
1604+ */
1605+ public String getDisplayScript(Locale inLocale) {
1606+ return getDisplayString(baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
1607+ }
1608+
1609+ /**
1610+ * Returns a name for the locale's country that is appropriate for display to the
1611+ * user.
1612+ * If possible, the name returned will be localized for the default locale.
1613+ * For example, if the locale is fr_FR and the default locale
1614+ * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1615+ * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis".
1616+ * If the name returned cannot be localized for the default locale,
1617+ * (say, we don't have a Japanese name for Croatia),
1618+ * this function falls back on the English name, and uses the ISO code as a last-resort
1619+ * value. If the locale doesn't specify a country, this function returns the empty string.
1620+ */
1621+ public final String getDisplayCountry() {
1622+ return getDisplayCountry(getDefault(Category.DISPLAY));
1623+ }
1624+
1625+ /**
1626+ * Returns a name for the locale's country that is appropriate for display to the
1627+ * user.
1628+ * If possible, the name returned will be localized according to inLocale.
1629+ * For example, if the locale is fr_FR and inLocale
1630+ * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
1631+ * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
1632+ * If the name returned cannot be localized according to inLocale.
1633+ * (say, we don't have a Japanese name for Croatia),
1634+ * this function falls back on the English name, and finally
1635+ * on the ISO code as a last-resort value. If the locale doesn't specify a country,
1636+ * this function returns the empty string.
1637+ *
1638+ * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1639+ */
1640+ public String getDisplayCountry(Locale inLocale) {
1641+ return getDisplayString(baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
1642+ }
1643+
1644+ private String getDisplayString(String code, Locale inLocale, int type) {
1645+ if (code.length() == 0) {
1646+ return "";
1647+ }
1648+
1649+ if (inLocale == null) {
1650+ throw new NullPointerException();
1651+ }
1652+
1653+ try {
1654+ OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
1655+ String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
1656+ String result = null;
1657+
1658+ // Check whether a provider can provide an implementation that's closer
1659+ // to the requested locale than what the Java runtime itself can provide.
1660+ LocaleServiceProviderPool pool =
1661+ LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
1662+ if (pool.hasProviders()) {
1663+ result = pool.getLocalizedObject(
1664+ LocaleNameGetter.INSTANCE,
1665+ inLocale, bundle, key,
1666+ type, code);
1667+ }
1668+
1669+ if (result == null) {
1670+ result = bundle.getString(key);
1671+ }
1672+
1673+ if (result != null) {
1674+ return result;
1675+ }
1676+ }
1677+ catch (Exception e) {
1678+ // just fall through
1679+ }
1680+ return code;
1681+ }
1682+
1683+ /**
1684+ * Returns a name for the locale's variant code that is appropriate for display to the
1685+ * user. If possible, the name will be localized for the default locale. If the locale
1686+ * doesn't specify a variant code, this function returns the empty string.
1687+ */
1688+ public final String getDisplayVariant() {
1689+ return getDisplayVariant(getDefault(Category.DISPLAY));
1690+ }
1691+
1692+ /**
1693+ * Returns a name for the locale's variant code that is appropriate for display to the
1694+ * user. If possible, the name will be localized for inLocale. If the locale
1695+ * doesn't specify a variant code, this function returns the empty string.
1696+ *
1697+ * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
1698+ */
1699+ public String getDisplayVariant(Locale inLocale) {
1700+ if (baseLocale.getVariant().length() == 0)
1701+ return "";
1702+
1703+ OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
1704+
1705+ String names[] = getDisplayVariantArray(bundle, inLocale);
1706+
1707+ // Get the localized patterns for formatting a list, and use
1708+ // them to format the list.
1709+ String listPattern = null;
1710+ String listCompositionPattern = null;
1711+ try {
1712+ listPattern = bundle.getString("ListPattern");
1713+ listCompositionPattern = bundle.getString("ListCompositionPattern");
1714+ } catch (MissingResourceException e) {
1715+ }
1716+ return formatList(names, listPattern, listCompositionPattern);
1717+ }
1718+
1719+ /**
1720+ * Returns a name for the locale that is appropriate for display to the
1721+ * user. This will be the values returned by getDisplayLanguage(),
1722+ * getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled
1723+ * into a single string. The the non-empty values are used in order,
1724+ * with the second and subsequent names in parentheses. For example:
1725+ * <blockquote>
1726+ * language (script, country, variant)<br>
1727+ * language (country)<br>
1728+ * language (variant)<br>
1729+ * script (country)<br>
1730+ * country<br>
1731+ * </blockquote>
1732+ * depending on which fields are specified in the locale. If the
1733+ * language, sacript, country, and variant fields are all empty,
1734+ * this function returns the empty string.
1735+ */
1736+ public final String getDisplayName() {
1737+ return getDisplayName(getDefault(Category.DISPLAY));
1738+ }
1739+
1740+ /**
1741+ * Returns a name for the locale that is appropriate for display
1742+ * to the user. This will be the values returned by
1743+ * getDisplayLanguage(), getDisplayScript(),getDisplayCountry(),
1744+ * and getDisplayVariant() assembled into a single string.
1745+ * The non-empty values are used in order,
1746+ * with the second and subsequent names in parentheses. For example:
1747+ * <blockquote>
1748+ * language (script, country, variant)<br>
1749+ * language (country)<br>
1750+ * language (variant)<br>
1751+ * script (country)<br>
1752+ * country<br>
1753+ * </blockquote>
1754+ * depending on which fields are specified in the locale. If the
1755+ * language, script, country, and variant fields are all empty,
1756+ * this function returns the empty string.
1757+ *
1758+ * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
1759+ */
1760+ public String getDisplayName(Locale inLocale) {
1761+ OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
1762+
1763+ String languageName = getDisplayLanguage(inLocale);
1764+ String scriptName = getDisplayScript(inLocale);
1765+ String countryName = getDisplayCountry(inLocale);
1766+ String[] variantNames = getDisplayVariantArray(bundle, inLocale);
1767+
1768+ // Get the localized patterns for formatting a display name.
1769+ String displayNamePattern = null;
1770+ String listPattern = null;
1771+ String listCompositionPattern = null;
1772+ try {
1773+ displayNamePattern = bundle.getString("DisplayNamePattern");
1774+ listPattern = bundle.getString("ListPattern");
1775+ listCompositionPattern = bundle.getString("ListCompositionPattern");
1776+ } catch (MissingResourceException e) {
1777+ }
1778+
1779+ // The display name consists of a main name, followed by qualifiers.
1780+ // Typically, the format is "MainName (Qualifier, Qualifier)" but this
1781+ // depends on what pattern is stored in the display locale.
1782+ String mainName = null;
1783+ String[] qualifierNames = null;
1784+
1785+ // The main name is the language, or if there is no language, the script,
1786+ // then if no script, the country. If there is no language/script/country
1787+ // (an anomalous situation) then the display name is simply the variant's
1788+ // display name.
1789+ if (languageName.length() == 0 && scriptName.length() == 0 && countryName.length() == 0) {
1790+ if (variantNames.length == 0) {
1791+ return "";
1792+ } else {
1793+ return formatList(variantNames, listPattern, listCompositionPattern);
1794+ }
1795+ }
1796+ ArrayList<String> names = new ArrayList<>(4);
1797+ if (languageName.length() != 0) {
1798+ names.add(languageName);
1799+ }
1800+ if (scriptName.length() != 0) {
1801+ names.add(scriptName);
1802+ }
1803+ if (countryName.length() != 0) {
1804+ names.add(countryName);
1805+ }
1806+ if (variantNames.length != 0) {
1807+ for (String var : variantNames) {
1808+ names.add(var);
1809+ }
1810+ }
1811+
1812+ // The first one in the main name
1813+ mainName = names.get(0);
1814+
1815+ // Others are qualifiers
1816+ int numNames = names.size();
1817+ qualifierNames = (numNames > 1) ?
1818+ names.subList(1, numNames).toArray(new String[numNames - 1]) : new String[0];
1819+
1820+ // Create an array whose first element is the number of remaining
1821+ // elements. This serves as a selector into a ChoiceFormat pattern from
1822+ // the resource. The second and third elements are the main name and
1823+ // the qualifier; if there are no qualifiers, the third element is
1824+ // unused by the format pattern.
1825+ Object[] displayNames = {
1826+ new Integer(qualifierNames.length != 0 ? 2 : 1),
1827+ mainName,
1828+ // We could also just call formatList() and have it handle the empty
1829+ // list case, but this is more efficient, and we want it to be
1830+ // efficient since all the language-only locales will not have any
1831+ // qualifiers.
1832+ qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null
1833+ };
1834+
1835+ if (displayNamePattern != null) {
1836+ return new MessageFormat(displayNamePattern).format(displayNames);
1837+ }
1838+ else {
1839+ // If we cannot get the message format pattern, then we use a simple
1840+ // hard-coded pattern. This should not occur in practice unless the
1841+ // installation is missing some core files (FormatData etc.).
1842+ StringBuilder result = new StringBuilder();
1843+ result.append((String)displayNames[1]);
1844+ if (displayNames.length > 2) {
1845+ result.append(" (");
1846+ result.append((String)displayNames[2]);
1847+ result.append(')');
1848+ }
1849+ return result.toString();
1850+ }
1851+ }
1852+
1853+ /**
1854+ * Overrides Cloneable.
1855+ */
1856+ public Object clone()
1857+ {
1858+ try {
1859+ Locale that = (Locale)super.clone();
1860+ return that;
1861+ } catch (CloneNotSupportedException e) {
1862+ throw new InternalError();
1863+ }
1864+ }
1865+
1866+ /**
1867+ * Override hashCode.
1868+ * Since Locales are often used in hashtables, caches the value
1869+ * for speed.
1870+ */
1871+ @Override
1872+ public int hashCode() {
1873+ int hc = hashCodeValue;
1874+ if (hc == 0) {
1875+ hc = baseLocale.hashCode();
1876+ if (localeExtensions != null) {
1877+ hc ^= localeExtensions.hashCode();
1878+ }
1879+ hashCodeValue = hc;
1880+ }
1881+ return hc;
1882+ }
1883+
1884+ // Overrides
1885+
1886+ /**
1887+ * Returns true if this Locale is equal to another object. A Locale is
1888+ * deemed equal to another Locale with identical language, script, country,
1889+ * variant and extensions, and unequal to all other objects.
1890+ *
1891+ * @return true if this Locale is equal to the specified object.
1892+ */
1893+ @Override
1894+ public boolean equals(Object obj) {
1895+ if (this == obj) // quick check
1896+ return true;
1897+ if (!(obj instanceof Locale))
1898+ return false;
1899+ BaseLocale otherBase = ((Locale)obj).baseLocale;
1900+ if (!baseLocale.equals(otherBase)) {
1901+ return false;
1902+ }
1903+ if (localeExtensions == null) {
1904+ return ((Locale)obj).localeExtensions == null;
1905+ }
1906+ return localeExtensions.equals(((Locale)obj).localeExtensions);
1907+ }
1908+
1909+ // ================= privates =====================================
1910+
1911+ private transient BaseLocale baseLocale;
1912+ private transient LocaleExtensions localeExtensions;
1913+
1914+ /**
1915+ * Calculated hashcode
1916+ */
1917+ private transient volatile int hashCodeValue = 0;
1918+
1919+ private static Locale defaultLocale = null;
1920+ private static Locale defaultDisplayLocale = null;
1921+ private static Locale defaultFormatLocale = null;
1922+
1923+ /**
1924+ * Return an array of the display names of the variant.
1925+ * @param bundle the ResourceBundle to use to get the display names
1926+ * @return an array of display names, possible of zero length.
1927+ */
1928+ private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
1929+ // Split the variant name into tokens separated by '_'.
1930+ StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
1931+ String[] names = new String[tokenizer.countTokens()];
1932+
1933+ // For each variant token, lookup the display name. If
1934+ // not found, use the variant name itself.
1935+ for (int i=0; i<names.length; ++i) {
1936+ names[i] = getDisplayString(tokenizer.nextToken(),
1937+ inLocale, DISPLAY_VARIANT);
1938+ }
1939+
1940+ return names;
1941+ }
1942+
1943+ /**
1944+ * Format a list using given pattern strings.
1945+ * If either of the patterns is null, then a the list is
1946+ * formatted by concatenation with the delimiter ','.
1947+ * @param stringList the list of strings to be formatted.
1948+ * @param listPattern should create a MessageFormat taking 0-3 arguments
1949+ * and formatting them into a list.
1950+ * @param listCompositionPattern should take 2 arguments
1951+ * and is used by composeList.
1952+ * @return a string representing the list.
1953+ */
1954+ private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
1955+ // If we have no list patterns, compose the list in a simple,
1956+ // non-localized way.
1957+ if (listPattern == null || listCompositionPattern == null) {
1958+ StringBuffer result = new StringBuffer();
1959+ for (int i=0; i<stringList.length; ++i) {
1960+ if (i>0) result.append(',');
1961+ result.append(stringList[i]);
1962+ }
1963+ return result.toString();
1964+ }
1965+
1966+ // Compose the list down to three elements if necessary
1967+ if (stringList.length > 3) {
1968+ MessageFormat format = new MessageFormat(listCompositionPattern);
1969+ stringList = composeList(format, stringList);
1970+ }
1971+
1972+ // Rebuild the argument list with the list length as the first element
1973+ Object[] args = new Object[stringList.length + 1];
1974+ System.arraycopy(stringList, 0, args, 1, stringList.length);
1975+ args[0] = new Integer(stringList.length);
1976+
1977+ // Format it using the pattern in the resource
1978+ MessageFormat format = new MessageFormat(listPattern);
1979+ return format.format(args);
1980+ }
1981+
1982+ /**
1983+ * Given a list of strings, return a list shortened to three elements.
1984+ * Shorten it by applying the given format to the first two elements
1985+ * recursively.
1986+ * @param format a format which takes two arguments
1987+ * @param list a list of strings
1988+ * @return if the list is three elements or shorter, the same list;
1989+ * otherwise, a new list of three elements.
1990+ */
1991+ private static String[] composeList(MessageFormat format, String[] list) {
1992+ if (list.length <= 3) return list;
1993+
1994+ // Use the given format to compose the first two elements into one
1995+ String[] listItems = { list[0], list[1] };
1996+ String newItem = format.format(listItems);
1997+
1998+ // Form a new list one element shorter
1999+ String[] newList = new String[list.length-1];
2000+ System.arraycopy(list, 2, newList, 1, newList.length-1);
2001+ newList[0] = newItem;
2002+
2003+ // Recurse
2004+ return composeList(format, newList);
2005+ }
2006+
2007+ /**
2008+ * @serialField language String
2009+ * language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
2010+ * @serialField country String
2011+ * country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
2012+ * @serialField variant String
2013+ * variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>)
2014+ * @serialField hashcode int
2015+ * deprecated, for forward compatibility only
2016+ * @serialField script String
2017+ * script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>)
2018+ * @serialField extensions String
2019+ * canonical representation of extensions, that is,
2020+ * BCP47 extensions in alphabetical order followed by
2021+ * BCP47 private use subtags, all in lower case letters
2022+ * separated by HYPHEN-MINUS characters.
2023+ * (See <a href="java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>,
2024+ * <a href="java/util/Locale.html#getExtension(char)">getExtension(char)</a>)
2025+ */
2026+ private static final ObjectStreamField[] serialPersistentFields = {
2027+ new ObjectStreamField("language", String.class),
2028+ new ObjectStreamField("country", String.class),
2029+ new ObjectStreamField("variant", String.class),
2030+ new ObjectStreamField("hashcode", int.class),
2031+ new ObjectStreamField("script", String.class),
2032+ new ObjectStreamField("extensions", String.class),
2033+ };
2034+
2035+ /**
2036+ * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>.
2037+ * @param out the <code>ObjectOutputStream</code> to write
2038+ * @throws IOException
2039+ * @since 1.7
2040+ */
2041+ private void writeObject(ObjectOutputStream out) throws IOException {
2042+ ObjectOutputStream.PutField fields = out.putFields();
2043+ fields.put("language", baseLocale.getLanguage());
2044+ fields.put("script", baseLocale.getScript());
2045+ fields.put("country", baseLocale.getRegion());
2046+ fields.put("variant", baseLocale.getVariant());
2047+ fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID());
2048+ fields.put("hashcode", -1); // place holder just for backward support
2049+ out.writeFields();
2050+ }
2051+
2052+ /**
2053+ * Deserializes this <code>Locale</code>.
2054+ * @param in the <code>ObjectInputStream</code> to read
2055+ * @throws IOException
2056+ * @throws ClassNotFoundException
2057+ * @throws IllformdLocaleException
2058+ * @since 1.7
2059+ */
2060+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
2061+ ObjectInputStream.GetField fields = in.readFields();
2062+ String language = (String)fields.get("language", "");
2063+ String script = (String)fields.get("script", "");
2064+ String country = (String)fields.get("country", "");
2065+ String variant = (String)fields.get("variant", "");
2066+ String extStr = (String)fields.get("extensions", "");
2067+ baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
2068+ if (extStr.length() > 0) {
2069+ try {
2070+ InternalLocaleBuilder bldr = new InternalLocaleBuilder();
2071+ bldr.setExtensions(extStr);
2072+ localeExtensions = bldr.getLocaleExtensions();
2073+ } catch (LocaleSyntaxException e) {
2074+ throw new IllformedLocaleException(e.getMessage());
2075+ }
2076+ } else {
2077+ localeExtensions = null;
2078+ }
2079+ }
2080+
2081+ /**
2082+ * Returns a cached <code>Locale</code> instance equivalent to
2083+ * the deserialized <code>Locale</code>. When serialized
2084+ * language, country and variant fields read from the object data stream
2085+ * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
2086+ * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
2087+ * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
2088+ * type is "thai"). See <a href="Locale.html#special_cases_constructor"/>Special Cases</a>
2089+ * for more information.
2090+ *
2091+ * @return an instance of <code>Locale</code> equivalent to
2092+ * the deserialized <code>Locale</code>.
2093+ * @throws java.io.ObjectStreamException
2094+ */
2095+ private Object readResolve() throws java.io.ObjectStreamException {
2096+ return getInstance(baseLocale.getLanguage(), baseLocale.getScript(),
2097+ baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
2098+ }
2099+
2100+ private static volatile String[] isoLanguages = null;
2101+
2102+ private static volatile String[] isoCountries = null;
2103+
2104+ private static String convertOldISOCodes(String language) {
2105+ // we accept both the old and the new ISO codes for the languages whose ISO
2106+ // codes have changed, but we always store the OLD code, for backward compatibility
2107+ language = LocaleUtils.toLowerString(language).intern();
2108+ if (language == "he") {
2109+ return "iw";
2110+ } else if (language == "yi") {
2111+ return "ji";
2112+ } else if (language == "id") {
2113+ return "in";
2114+ } else {
2115+ return language;
2116+ }
2117+ }
2118+
2119+ private static LocaleExtensions getCompatibilityExtensions(String language,
2120+ String script,
2121+ String country,
2122+ String variant) {
2123+ LocaleExtensions extensions = null;
2124+ // Special cases for backward compatibility support
2125+ if (LocaleUtils.caseIgnoreMatch(language, "ja")
2126+ && script.length() == 0
2127+ && LocaleUtils.caseIgnoreMatch(country, "jp")
2128+ && "JP".equals(variant)) {
2129+ // ja_JP_JP -> u-ca-japanese (calendar = japanese)
2130+ extensions = LocaleExtensions.CALENDAR_JAPANESE;
2131+ } else if (LocaleUtils.caseIgnoreMatch(language, "th")
2132+ && script.length() == 0
2133+ && LocaleUtils.caseIgnoreMatch(country, "th")
2134+ && "TH".equals(variant)) {
2135+ // th_TH_TH -> u-nu-thai (numbersystem = thai)
2136+ extensions = LocaleExtensions.NUMBER_THAI;
2137+ }
2138+ return extensions;
2139+ }
2140+
2141+ /**
2142+ * Obtains a localized locale names from a LocaleNameProvider
2143+ * implementation.
2144+ */
2145+ private static class LocaleNameGetter
2146+ implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
2147+ private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
2148+
2149+ public String getObject(LocaleNameProvider localeNameProvider,
2150+ Locale locale,
2151+ String key,
2152+ Object... params) {
2153+ assert params.length == 2;
2154+ int type = (Integer)params[0];
2155+ String code = (String)params[1];
2156+
2157+ switch(type) {
2158+ case DISPLAY_LANGUAGE:
2159+ return localeNameProvider.getDisplayLanguage(code, locale);
2160+ case DISPLAY_COUNTRY:
2161+ return localeNameProvider.getDisplayCountry(code, locale);
2162+ case DISPLAY_VARIANT:
2163+ return localeNameProvider.getDisplayVariant(code, locale);
2164+ case DISPLAY_SCRIPT:
2165+ return localeNameProvider.getDisplayScript(code, locale);
2166+ default:
2167+ assert false; // shouldn't happen
2168+ }
2169+
2170+ return null;
2171+ }
2172+ }
2173+
2174+ /**
2175+ * Enum for locale categories. These locale categories are used to get/set
2176+ * the default locale for the specific functionality represented by the
2177+ * category.
2178+ *
2179+ * @see #getDefault(Locale.Category)
2180+ * @see #setDefault(Locale.Category, Locale)
2181+ * @since 1.7
2182+ */
2183+ public enum Category {
2184+
2185+ /**
2186+ * Category used to represent the default locale for
2187+ * displaying user interfaces.
2188+ */
2189+ DISPLAY("user.language.display",
2190+ "user.script.display",
2191+ "user.country.display",
2192+ "user.variant.display"),
2193+
2194+ /**
2195+ * Category used to represent the default locale for
2196+ * formatting dates, numbers, and/or currencies.
2197+ */
2198+ FORMAT("user.language.format",
2199+ "user.script.format",
2200+ "user.country.format",
2201+ "user.variant.format");
2202+
2203+ Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
2204+ this.languageKey = languageKey;
2205+ this.scriptKey = scriptKey;
2206+ this.countryKey = countryKey;
2207+ this.variantKey = variantKey;
2208+ }
2209+
2210+ final String languageKey;
2211+ final String scriptKey;
2212+ final String countryKey;
2213+ final String variantKey;
2214+ }
2215+
2216+ /**
2217+ * <code>Builder</code> is used to build instances of <code>Locale</code>
2218+ * from values configured by the setters. Unlike the <code>Locale</code>
2219+ * constructors, the <code>Builder</code> checks if a value configured by a
2220+ * setter satisfies the syntax requirements defined by the <code>Locale</code>
2221+ * class. A <code>Locale</code> object created by a <code>Builder</code> is
2222+ * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
2223+ * without losing information.
2224+ *
2225+ * <p><b>Note:</b> The <code>Locale</code> class does not provide any
2226+ * syntactic restrictions on variant, while BCP 47 requires each variant
2227+ * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
2228+ * alphanumerics. The method <code>setVariant</code> throws
2229+ * <code>IllformedLocaleException</code> for a variant that does not satisfy
2230+ * this restriction. If it is necessary to support such a variant, use a
2231+ * Locale constructor. However, keep in mind that a <code>Locale</code>
2232+ * object created this way might lose the variant information when
2233+ * transformed to a BCP 47 language tag.
2234+ *
2235+ * <p>The following example shows how to create a <code>Locale</code> object
2236+ * with the <code>Builder</code>.
2237+ * <blockquote>
2238+ * <pre>
2239+ * Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
2240+ * </pre>
2241+ * </blockquote>
2242+ *
2243+ * <p>Builders can be reused; <code>clear()</code> resets all
2244+ * fields to their default values.
2245+ *
2246+ * @see Locale#forLanguageTag
2247+ * @since 1.7
2248+ */
2249+ public static final class Builder {
2250+ private final InternalLocaleBuilder localeBuilder;
2251+
2252+ /**
2253+ * Constructs an empty Builder. The default value of all
2254+ * fields, extensions, and private use information is the
2255+ * empty string.
2256+ */
2257+ public Builder() {
2258+ localeBuilder = new InternalLocaleBuilder();
2259+ }
2260+
2261+ /**
2262+ * Resets the <code>Builder</code> to match the provided
2263+ * <code>locale</code>. Existing state is discarded.
2264+ *
2265+ * <p>All fields of the locale must be well-formed, see {@link Locale}.
2266+ *
2267+ * <p>Locales with any ill-formed fields cause
2268+ * <code>IllformedLocaleException</code> to be thrown, except for the
2269+ * following three cases which are accepted for compatibility
2270+ * reasons:<ul>
2271+ * <li>Locale("ja", "JP", "JP") is treated as "ja-JP-u-ca-japanese"
2272+ * <li>Locale("th", "TH", "TH") is treated as "th-TH-u-nu-thai"
2273+ * <li>Locale("no", "NO", "NY") is treated as "nn-NO"</ul>
2274+ *
2275+ * @param locale the locale
2276+ * @return This builder.
2277+ * @throws IllformedLocaleException if <code>locale</code> has
2278+ * any ill-formed fields.
2279+ * @throws NullPointerException if <code>locale</code> is null.
2280+ */
2281+ public Builder setLocale(Locale locale) {
2282+ try {
2283+ localeBuilder.setLocale(locale.baseLocale, locale.localeExtensions);
2284+ } catch (LocaleSyntaxException e) {
2285+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2286+ }
2287+ return this;
2288+ }
2289+
2290+ /**
2291+ * Resets the Builder to match the provided IETF BCP 47
2292+ * language tag. Discards the existing state. Null and the
2293+ * empty string cause the builder to be reset, like {@link
2294+ * #clear}. Grandfathered tags (see {@link
2295+ * Locale#forLanguageTag}) are converted to their canonical
2296+ * form before being processed. Otherwise, the language tag
2297+ * must be well-formed (see {@link Locale}) or an exception is
2298+ * thrown (unlike <code>Locale.forLanguageTag</code>, which
2299+ * just discards ill-formed and following portions of the
2300+ * tag).
2301+ *
2302+ * @param languageTag the language tag
2303+ * @return This builder.
2304+ * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed
2305+ * @see Locale#forLanguageTag(String)
2306+ */
2307+ public Builder setLanguageTag(String languageTag) {
2308+ ParseStatus sts = new ParseStatus();
2309+ LanguageTag tag = LanguageTag.parse(languageTag, sts);
2310+ if (sts.isError()) {
2311+ throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
2312+ }
2313+ localeBuilder.setLanguageTag(tag);
2314+ return this;
2315+ }
2316+
2317+ /**
2318+ * Sets the language. If <code>language</code> is the empty string or
2319+ * null, the language in this <code>Builder</code> is removed. Otherwise,
2320+ * the language must be <a href="./Locale.html#def_language">well-formed</a>
2321+ * or an exception is thrown.
2322+ *
2323+ * <p>The typical language value is a two or three-letter language
2324+ * code as defined in ISO639.
2325+ *
2326+ * @param language the language
2327+ * @return This builder.
2328+ * @throws IllformedLocaleException if <code>language</code> is ill-formed
2329+ */
2330+ public Builder setLanguage(String language) {
2331+ try {
2332+ localeBuilder.setLanguage(language);
2333+ } catch (LocaleSyntaxException e) {
2334+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2335+ }
2336+ return this;
2337+ }
2338+
2339+ /**
2340+ * Sets the script. If <code>script</code> is null or the empty string,
2341+ * the script in this <code>Builder</code> is removed.
2342+ * Otherwise, the script must be <a href="./Locale.html#def_script">well-formed</a> or an
2343+ * exception is thrown.
2344+ *
2345+ * <p>The typical script value is a four-letter script code as defined by ISO 15924.
2346+ *
2347+ * @param script the script
2348+ * @return This builder.
2349+ * @throws IllformedLocaleException if <code>script</code> is ill-formed
2350+ */
2351+ public Builder setScript(String script) {
2352+ try {
2353+ localeBuilder.setScript(script);
2354+ } catch (LocaleSyntaxException e) {
2355+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2356+ }
2357+ return this;
2358+ }
2359+
2360+ /**
2361+ * Sets the region. If region is null or the empty string, the region
2362+ * in this <code>Builder</code> is removed. Otherwise,
2363+ * the region must be <a href="./Locale.html#def_region">well-formed</a> or an
2364+ * exception is thrown.
2365+ *
2366+ * <p>The typical region value is a two-letter ISO 3166 code or a
2367+ * three-digit UN M.49 area code.
2368+ *
2369+ * <p>The country value in the <code>Locale</code> created by the
2370+ * <code>Builder</code> is always normalized to upper case.
2371+ *
2372+ * @param region the region
2373+ * @return This builder.
2374+ * @throws IllformedLocaleException if <code>region</code> is ill-formed
2375+ */
2376+ public Builder setRegion(String region) {
2377+ try {
2378+ localeBuilder.setRegion(region);
2379+ } catch (LocaleSyntaxException e) {
2380+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2381+ }
2382+ return this;
2383+ }
2384+
2385+ /**
2386+ * Sets the variant. If variant is null or the empty string, the
2387+ * variant in this <code>Builder</code> is removed. Otherwise, it
2388+ * must consist of one or more <a href="./Locale.html#def_variant">well-formed</a>
2389+ * subtags, or an exception is thrown.
2390+ *
2391+ * <p><b>Note:</b> This method checks if <code>variant</code>
2392+ * satisfies the IETF BCP 47 variant subtag's syntax requirements,
2393+ * and normalizes the value to lowercase letters. However,
2394+ * the <code>Locale</code> class does not impose any syntactic
2395+ * restriction on variant, and the variant value in
2396+ * <code>Locale</code> is case sensitive. To set such a variant,
2397+ * use a Locale constructor.
2398+ *
2399+ * @param variant the variant
2400+ * @return This builder.
2401+ * @throws IllformedLocaleException if <code>variant</code> is ill-formed
2402+ */
2403+ public Builder setVariant(String variant) {
2404+ try {
2405+ localeBuilder.setVariant(variant);
2406+ } catch (LocaleSyntaxException e) {
2407+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2408+ }
2409+ return this;
2410+ }
2411+
2412+ /**
2413+ * Sets the extension for the given key. If the value is null or the
2414+ * empty string, the extension is removed. Otherwise, the extension
2415+ * must be <a href="./Locale.html#def_extensions">well-formed</a> or an exception
2416+ * is thrown.
2417+ *
2418+ * <p><b>Note:</b> The key {@link Locale#UNICODE_LOCALE_EXTENSION
2419+ * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension.
2420+ * Setting a value for this key replaces any existing Unicode locale key/type
2421+ * pairs with those defined in the extension.
2422+ *
2423+ * <p><b>Note:</b> The key {@link Locale#PRIVATE_USE_EXTENSION
2424+ * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be
2425+ * well-formed, the value for this key needs only to have subtags of one to
2426+ * eight alphanumeric characters, not two to eight as in the general case.
2427+ *
2428+ * @param key the extension key
2429+ * @param value the extension value
2430+ * @return This builder.
2431+ * @throws IllformedLocaleException if <code>key</code> is illegal
2432+ * or <code>value</code> is ill-formed
2433+ * @see #setUnicodeLocaleKeyword(String, String)
2434+ */
2435+ public Builder setExtension(char key, String value) {
2436+ try {
2437+ localeBuilder.setExtension(key, value);
2438+ } catch (LocaleSyntaxException e) {
2439+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2440+ }
2441+ return this;
2442+ }
2443+
2444+ /**
2445+ * Sets the Unicode locale keyword type for the given key. If the type
2446+ * is null, the Unicode keyword is removed. Otherwise, the key must be
2447+ * non-null and both key and type must be <a
2448+ * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
2449+ * is thrown.
2450+ *
2451+ * <p>Keys and types are converted to lower case.
2452+ *
2453+ * <p><b>Note</b>:Setting the 'u' extension via {@link #setExtension}
2454+ * replaces all Unicode locale keywords with those defined in the
2455+ * extension.
2456+ *
2457+ * @param key the Unicode locale key
2458+ * @param type the Unicode locale type
2459+ * @return This builder.
2460+ * @throws IllformedLocaleException if <code>key</code> or <code>type</code>
2461+ * is ill-formed
2462+ * @throws NullPointerException if <code>key</code> is null
2463+ * @see #setExtension(char, String)
2464+ */
2465+ public Builder setUnicodeLocaleKeyword(String key, String type) {
2466+ try {
2467+ localeBuilder.setUnicodeLocaleKeyword(key, type);
2468+ } catch (LocaleSyntaxException e) {
2469+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2470+ }
2471+ return this;
2472+ }
2473+
2474+ /**
2475+ * Adds a unicode locale attribute, if not already present, otherwise
2476+ * has no effect. The attribute must not be null and must be <a
2477+ * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
2478+ * is thrown.
2479+ *
2480+ * @param attribute the attribute
2481+ * @return This builder.
2482+ * @throws NullPointerException if <code>attribute</code> is null
2483+ * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
2484+ * @see #setExtension(char, String)
2485+ */
2486+ public Builder addUnicodeLocaleAttribute(String attribute) {
2487+ try {
2488+ localeBuilder.addUnicodeLocaleAttribute(attribute);
2489+ } catch (LocaleSyntaxException e) {
2490+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2491+ }
2492+ return this;
2493+ }
2494+
2495+ /**
2496+ * Removes a unicode locale attribute, if present, otherwise has no
2497+ * effect. The attribute must not be null and must be <a
2498+ * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
2499+ * is thrown.
2500+ *
2501+ * <p>Attribute comparision for removal is case-insensitive.
2502+ *
2503+ * @param attribute the attribute
2504+ * @return This builder.
2505+ * @throws NullPointerException if <code>attribute</code> is null
2506+ * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
2507+ * @see #setExtension(char, String)
2508+ */
2509+ public Builder removeUnicodeLocaleAttribute(String attribute) {
2510+ try {
2511+ localeBuilder.removeUnicodeLocaleAttribute(attribute);
2512+ } catch (LocaleSyntaxException e) {
2513+ throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
2514+ }
2515+ return this;
2516+ }
2517+
2518+ /**
2519+ * Resets the builder to its initial, empty state.
2520+ *
2521+ * @return This builder.
2522+ */
2523+ public Builder clear() {
2524+ localeBuilder.clear();
2525+ return this;
2526+ }
2527+
2528+ /**
2529+ * Resets the extensions to their initial, empty state.
2530+ * Language, script, region and variant are unchanged.
2531+ *
2532+ * @return This builder.
2533+ * @see #setExtension(char, String)
2534+ */
2535+ public Builder clearExtensions() {
2536+ localeBuilder.clearExtensions();
2537+ return this;
2538+ }
2539+
2540+ /**
2541+ * Returns an instance of <code>Locale</code> created from the fields set
2542+ * on this builder.
2543+ *
2544+ * <p>This applies the conversions listed in {@link Locale#forLanguageTag}
2545+ * when constructing a Locale. (Grandfathered tags are handled in
2546+ * {@link #setLanguageTag}.)
2547+ *
2548+ * @return A Locale.
2549+ */
2550+ public Locale build() {
2551+ BaseLocale baseloc = localeBuilder.getBaseLocale();
2552+ LocaleExtensions extensions = localeBuilder.getLocaleExtensions();
2553+ if (extensions == null && baseloc.getVariant().length() > 0) {
2554+ extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(),
2555+ baseloc.getRegion(), baseloc.getVariant());
2556+ }
2557+ return Locale.getInstance(baseloc, extensions);
2558+ }
2559+ }
2560+}