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