--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ *******************************************************************************
+ * Copyright (C) 2009-2010, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ *******************************************************************************
+ */
+
+package sun.util.locale;
+import java.lang.ref.SoftReference;
+
+import java.util.StringJoiner;
+
+public final class BaseLocale {
+
+ public static final String SEP = "_";
+
+ private static final Cache CACHE = new Cache();
+
+ private final String language;
+ private final String script;
+ private final String region;
+ private final String variant;
+
+ private volatile int hash;
+
+ // This method must be called only when creating the Locale.* constants.
+ private BaseLocale(String language, String region) {
+ this.language = language;
+ this.script = "";
+ this.region = region;
+ this.variant = "";
+ }
+
+ private BaseLocale(String language, String script, String region, String variant) {
+ this.language = (language != null) ? LocaleUtils.toLowerString(language).intern() : "";
+ this.script = (script != null) ? LocaleUtils.toTitleString(script).intern() : "";
+ this.region = (region != null) ? LocaleUtils.toUpperString(region).intern() : "";
+ this.variant = (variant != null) ? variant.intern() : "";
+ }
+
+ // Called for creating the Locale.* constants. No argument
+ // validation is performed.
+ public static BaseLocale createInstance(String language, String region) {
+ BaseLocale base = new BaseLocale(language, region);
+ CACHE.put(new Key(language, region), base);
+ return base;
+ }
+
+ public static BaseLocale getInstance(String language, String script,
+ String region, String variant) {
+ // JDK uses deprecated ISO639.1 language codes for he, yi and id
+ if (language != null) {
+ if (LocaleUtils.caseIgnoreMatch(language, "he")) {
+ language = "iw";
+ } else if (LocaleUtils.caseIgnoreMatch(language, "yi")) {
+ language = "ji";
+ } else if (LocaleUtils.caseIgnoreMatch(language, "id")) {
+ language = "in";
+ }
+ }
+
+ Key key = new Key(language, script, region, variant);
+ BaseLocale baseLocale = CACHE.get(key);
+ return baseLocale;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public String getScript() {
+ return script;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ public String getVariant() {
+ return variant;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof BaseLocale)) {
+ return false;
+ }
+ BaseLocale other = (BaseLocale)obj;
+ return language == other.language
+ && script == other.script
+ && region == other.region
+ && variant == other.variant;
+ }
+
+ @Override
+ public String toString() {
+ StringJoiner sj = new StringJoiner(", ");
+ if (language.length() > 0) {
+ sj.add("language=" + language);
+ }
+ if (script.length() > 0) {
+ sj.add("script=" + script);
+ }
+ if (region.length() > 0) {
+ sj.add("region=" + region);
+ }
+ if (variant.length() > 0) {
+ sj.add("variant=" + variant);
+ }
+ return sj.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int h = hash;
+ if (h == 0) {
+ // Generating a hash value from language, script, region and variant
+ h = language.hashCode();
+ h = 31 * h + script.hashCode();
+ h = 31 * h + region.hashCode();
+ h = 31 * h + variant.hashCode();
+ if (h != 0) {
+ hash = h;
+ }
+ }
+ return h;
+ }
+
+ private static final class Key {
+ private final SoftReference<String> lang;
+ private final SoftReference<String> scrt;
+ private final SoftReference<String> regn;
+ private final SoftReference<String> vart;
+ private final boolean normalized;
+ private final int hash;
+
+ /**
+ * Creates a Key. language and region must be normalized
+ * (intern'ed in the proper case).
+ */
+ private Key(String language, String region) {
+ assert language.intern() == language
+ && region.intern() == region;
+
+ lang = new SoftReference<>(language);
+ scrt = new SoftReference<>("");
+ regn = new SoftReference<>(region);
+ vart = new SoftReference<>("");
+ this.normalized = true;
+
+ int h = language.hashCode();
+ if (region != "") {
+ int len = region.length();
+ for (int i = 0; i < len; i++) {
+ h = 31 * h + LocaleUtils.toLower(region.charAt(i));
+ }
+ }
+ hash = h;
+ }
+
+ public Key(String language, String script, String region, String variant) {
+ this(language, script, region, variant, false);
+ }
+
+ private Key(String language, String script, String region,
+ String variant, boolean normalized) {
+ int h = 0;
+ if (language != null) {
+ lang = new SoftReference<>(language);
+ int len = language.length();
+ for (int i = 0; i < len; i++) {
+ h = 31*h + LocaleUtils.toLower(language.charAt(i));
+ }
+ } else {
+ lang = new SoftReference<>("");
+ }
+ if (script != null) {
+ scrt = new SoftReference<>(script);
+ int len = script.length();
+ for (int i = 0; i < len; i++) {
+ h = 31*h + LocaleUtils.toLower(script.charAt(i));
+ }
+ } else {
+ scrt = new SoftReference<>("");
+ }
+ if (region != null) {
+ regn = new SoftReference<>(region);
+ int len = region.length();
+ for (int i = 0; i < len; i++) {
+ h = 31*h + LocaleUtils.toLower(region.charAt(i));
+ }
+ } else {
+ regn = new SoftReference<>("");
+ }
+ if (variant != null) {
+ vart = new SoftReference<>(variant);
+ int len = variant.length();
+ for (int i = 0; i < len; i++) {
+ h = 31*h + variant.charAt(i);
+ }
+ } else {
+ vart = new SoftReference<>("");
+ }
+ hash = h;
+ this.normalized = normalized;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof Key && this.hash == ((Key)obj).hash) {
+ String tl = this.lang.get();
+ String ol = ((Key)obj).lang.get();
+ if (tl != null && ol != null &&
+ LocaleUtils.caseIgnoreMatch(ol, tl)) {
+ String ts = this.scrt.get();
+ String os = ((Key)obj).scrt.get();
+ if (ts != null && os != null &&
+ LocaleUtils.caseIgnoreMatch(os, ts)) {
+ String tr = this.regn.get();
+ String or = ((Key)obj).regn.get();
+ if (tr != null && or != null &&
+ LocaleUtils.caseIgnoreMatch(or, tr)) {
+ String tv = this.vart.get();
+ String ov = ((Key)obj).vart.get();
+ return (ov != null && ov.equals(tv));
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ public static Key normalize(Key key) {
+ if (key.normalized) {
+ return key;
+ }
+
+ String lang = LocaleUtils.toLowerString(key.lang.get()).intern();
+ String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern();
+ String regn = LocaleUtils.toUpperString(key.regn.get()).intern();
+ String vart = key.vart.get().intern(); // preserve upper/lower cases
+
+ return new Key(lang, scrt, regn, vart, true);
+ }
+ }
+
+ private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
+
+ public Cache() {
+ }
+
+ @Override
+ protected Key normalizeKey(Key key) {
+ assert key.lang.get() != null &&
+ key.scrt.get() != null &&
+ key.regn.get() != null &&
+ key.vart.get() != null;
+
+ return Key.normalize(key);
+ }
+
+ @Override
+ protected BaseLocale createObject(Key key) {
+ return new BaseLocale(key.lang.get(), key.scrt.get(),
+ key.regn.get(), key.vart.get());
+ }
+ }
+}