616 /**
617 * The key for the private use extension ('x').
618 *
619 * @see #getExtension(char)
620 * @see Builder#setExtension(char, String)
621 * @since 1.7
622 */
623 public static final char PRIVATE_USE_EXTENSION = 'x';
624
625 /**
626 * The key for Unicode locale extension ('u').
627 *
628 * @see #getExtension(char)
629 * @see Builder#setExtension(char, String)
630 * @since 1.7
631 */
632 public static final char UNICODE_LOCALE_EXTENSION = 'u';
633
634 /** serialization ID
635 */
636 static final long serialVersionUID = 9149081749638150636L;
637
638 /**
639 * Enum for specifying the type defined in ISO 3166. This enum is used to
640 * retrieve the two-letter ISO3166-1 alpha-2, three-letter ISO3166-1
641 * alpha-3, four-letter ISO3166-3 country codes.
642 *
643 * @see #getISOCountries(Locale.IsoCountryCode)
644 * @since 9
645 */
646 public static enum IsoCountryCode {
647 /**
648 * PART1_ALPHA2 is used to represent the ISO3166-1 alpha-2 two letter
649 * country codes.
650 */
651 PART1_ALPHA2 {
652 @Override
653 Set<String> createCountryCodeSet() {
654 return Set.of(Locale.getISOCountries());
655 }
2284 * (See <a href="java.base/java/util/Locale.html#getLanguage()">getLanguage()</a>)
2285 * @serialField country String
2286 * country subtag in upper case.
2287 * (See <a href="java.base/java/util/Locale.html#getCountry()">getCountry()</a>)
2288 * @serialField variant String
2289 * variant subtags separated by LOWLINE characters.
2290 * (See <a href="java.base/java/util/Locale.html#getVariant()">getVariant()</a>)
2291 * @serialField hashcode int
2292 * deprecated, for forward compatibility only
2293 * @serialField script String
2294 * script subtag in title case
2295 * (See <a href="java.base/java/util/Locale.html#getScript()">getScript()</a>)
2296 * @serialField extensions String
2297 * canonical representation of extensions, that is,
2298 * BCP47 extensions in alphabetical order followed by
2299 * BCP47 private use subtags, all in lower case letters
2300 * separated by HYPHEN-MINUS characters.
2301 * (See <a href="java.base/java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>,
2302 * <a href="java.base/java/util/Locale.html#getExtension(char)">getExtension(char)</a>)
2303 */
2304 private static final ObjectStreamField[] serialPersistentFields = {
2305 new ObjectStreamField("language", String.class),
2306 new ObjectStreamField("country", String.class),
2307 new ObjectStreamField("variant", String.class),
2308 new ObjectStreamField("hashcode", int.class),
2309 new ObjectStreamField("script", String.class),
2310 new ObjectStreamField("extensions", String.class),
2311 };
2312
2313 /**
2314 * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>.
2315 * @param out the <code>ObjectOutputStream</code> to write
2316 * @throws IOException
2317 * @since 1.7
2318 */
2319 private void writeObject(ObjectOutputStream out) throws IOException {
2320 ObjectOutputStream.PutField fields = out.putFields();
2321 fields.put("language", baseLocale.getLanguage());
2322 fields.put("script", baseLocale.getScript());
2323 fields.put("country", baseLocale.getRegion());
2324 fields.put("variant", baseLocale.getVariant());
2325 fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID());
2326 fields.put("hashcode", -1); // place holder just for backward support
2327 out.writeFields();
2328 }
2329
2330 /**
2331 * Deserializes this <code>Locale</code>.
2332 * @param in the <code>ObjectInputStream</code> to read
2333 * @throws IOException
2334 * @throws ClassNotFoundException
2335 * @throws IllformedLocaleException
2336 * @since 1.7
2337 */
2338 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
2339 ObjectInputStream.GetField fields = in.readFields();
2340 String language = (String)fields.get("language", "");
2341 String script = (String)fields.get("script", "");
2342 String country = (String)fields.get("country", "");
2343 String variant = (String)fields.get("variant", "");
2344 String extStr = (String)fields.get("extensions", "");
2345
2346 baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
2347 if (!extStr.isEmpty()) {
2348 try {
2349 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
2350 bldr.setExtensions(extStr);
2351 localeExtensions = bldr.getLocaleExtensions();
2352 } catch (LocaleSyntaxException e) {
2353 throw new IllformedLocaleException(e.getMessage());
2354 }
2355 } else {
2356 localeExtensions = null;
2357 }
2358 }
2359
2360 /**
2361 * Returns a cached <code>Locale</code> instance equivalent to
2362 * the deserialized <code>Locale</code>. When serialized
2363 * language, country and variant fields read from the object data stream
2364 * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
2365 * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
2366 * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
2367 * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a>
2368 * for more information.
2369 *
2370 * @return an instance of <code>Locale</code> equivalent to
2371 * the deserialized <code>Locale</code>.
2372 * @throws java.io.ObjectStreamException
2373 */
2374 private Object readResolve() throws java.io.ObjectStreamException {
2375 return getInstance(baseLocale.getLanguage(), baseLocale.getScript(),
2376 baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
2377 }
2378
2379 private static volatile String[] isoLanguages;
2380
2381 private static volatile String[] isoCountries;
2382
2383 private static String convertOldISOCodes(String language) {
2384 // we accept both the old and the new ISO codes for the languages whose ISO
2385 // codes have changed, but we always store the OLD code, for backward compatibility
2386 language = LocaleUtils.toLowerString(language).intern();
2387 if (language == "he") {
2388 return "iw";
2389 } else if (language == "yi") {
2390 return "ji";
2391 } else if (language == "id") {
2392 return "in";
2393 } else {
|
616 /**
617 * The key for the private use extension ('x').
618 *
619 * @see #getExtension(char)
620 * @see Builder#setExtension(char, String)
621 * @since 1.7
622 */
623 public static final char PRIVATE_USE_EXTENSION = 'x';
624
625 /**
626 * The key for Unicode locale extension ('u').
627 *
628 * @see #getExtension(char)
629 * @see Builder#setExtension(char, String)
630 * @since 1.7
631 */
632 public static final char UNICODE_LOCALE_EXTENSION = 'u';
633
634 /** serialization ID
635 */
636 @java.io.Serial
637 static final long serialVersionUID = 9149081749638150636L;
638
639 /**
640 * Enum for specifying the type defined in ISO 3166. This enum is used to
641 * retrieve the two-letter ISO3166-1 alpha-2, three-letter ISO3166-1
642 * alpha-3, four-letter ISO3166-3 country codes.
643 *
644 * @see #getISOCountries(Locale.IsoCountryCode)
645 * @since 9
646 */
647 public static enum IsoCountryCode {
648 /**
649 * PART1_ALPHA2 is used to represent the ISO3166-1 alpha-2 two letter
650 * country codes.
651 */
652 PART1_ALPHA2 {
653 @Override
654 Set<String> createCountryCodeSet() {
655 return Set.of(Locale.getISOCountries());
656 }
2285 * (See <a href="java.base/java/util/Locale.html#getLanguage()">getLanguage()</a>)
2286 * @serialField country String
2287 * country subtag in upper case.
2288 * (See <a href="java.base/java/util/Locale.html#getCountry()">getCountry()</a>)
2289 * @serialField variant String
2290 * variant subtags separated by LOWLINE characters.
2291 * (See <a href="java.base/java/util/Locale.html#getVariant()">getVariant()</a>)
2292 * @serialField hashcode int
2293 * deprecated, for forward compatibility only
2294 * @serialField script String
2295 * script subtag in title case
2296 * (See <a href="java.base/java/util/Locale.html#getScript()">getScript()</a>)
2297 * @serialField extensions String
2298 * canonical representation of extensions, that is,
2299 * BCP47 extensions in alphabetical order followed by
2300 * BCP47 private use subtags, all in lower case letters
2301 * separated by HYPHEN-MINUS characters.
2302 * (See <a href="java.base/java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>,
2303 * <a href="java.base/java/util/Locale.html#getExtension(char)">getExtension(char)</a>)
2304 */
2305 @java.io.Serial
2306 private static final ObjectStreamField[] serialPersistentFields = {
2307 new ObjectStreamField("language", String.class),
2308 new ObjectStreamField("country", String.class),
2309 new ObjectStreamField("variant", String.class),
2310 new ObjectStreamField("hashcode", int.class),
2311 new ObjectStreamField("script", String.class),
2312 new ObjectStreamField("extensions", String.class),
2313 };
2314
2315 /**
2316 * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>.
2317 * @param out the <code>ObjectOutputStream</code> to write
2318 * @throws IOException
2319 * @since 1.7
2320 */
2321 @java.io.Serial
2322 private void writeObject(ObjectOutputStream out) throws IOException {
2323 ObjectOutputStream.PutField fields = out.putFields();
2324 fields.put("language", baseLocale.getLanguage());
2325 fields.put("script", baseLocale.getScript());
2326 fields.put("country", baseLocale.getRegion());
2327 fields.put("variant", baseLocale.getVariant());
2328 fields.put("extensions", localeExtensions == null ? "" : localeExtensions.getID());
2329 fields.put("hashcode", -1); // place holder just for backward support
2330 out.writeFields();
2331 }
2332
2333 /**
2334 * Deserializes this <code>Locale</code>.
2335 * @param in the <code>ObjectInputStream</code> to read
2336 * @throws IOException
2337 * @throws ClassNotFoundException
2338 * @throws IllformedLocaleException
2339 * @since 1.7
2340 */
2341 @java.io.Serial
2342 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
2343 ObjectInputStream.GetField fields = in.readFields();
2344 String language = (String)fields.get("language", "");
2345 String script = (String)fields.get("script", "");
2346 String country = (String)fields.get("country", "");
2347 String variant = (String)fields.get("variant", "");
2348 String extStr = (String)fields.get("extensions", "");
2349
2350 baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
2351 if (!extStr.isEmpty()) {
2352 try {
2353 InternalLocaleBuilder bldr = new InternalLocaleBuilder();
2354 bldr.setExtensions(extStr);
2355 localeExtensions = bldr.getLocaleExtensions();
2356 } catch (LocaleSyntaxException e) {
2357 throw new IllformedLocaleException(e.getMessage());
2358 }
2359 } else {
2360 localeExtensions = null;
2361 }
2362 }
2363
2364 /**
2365 * Returns a cached <code>Locale</code> instance equivalent to
2366 * the deserialized <code>Locale</code>. When serialized
2367 * language, country and variant fields read from the object data stream
2368 * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
2369 * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
2370 * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
2371 * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a>
2372 * for more information.
2373 *
2374 * @return an instance of <code>Locale</code> equivalent to
2375 * the deserialized <code>Locale</code>.
2376 * @throws java.io.ObjectStreamException
2377 */
2378 @java.io.Serial
2379 private Object readResolve() throws java.io.ObjectStreamException {
2380 return getInstance(baseLocale.getLanguage(), baseLocale.getScript(),
2381 baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
2382 }
2383
2384 private static volatile String[] isoLanguages;
2385
2386 private static volatile String[] isoCountries;
2387
2388 private static String convertOldISOCodes(String language) {
2389 // we accept both the old and the new ISO codes for the languages whose ISO
2390 // codes have changed, but we always store the OLD code, for backward compatibility
2391 language = LocaleUtils.toLowerString(language).intern();
2392 if (language == "he") {
2393 return "iw";
2394 } else if (language == "yi") {
2395 return "ji";
2396 } else if (language == "id") {
2397 return "in";
2398 } else {
|