src/java.base/share/classes/sun/util/locale/BaseLocale.java
changeset 54412 41356f083e93
parent 48763 3d17a524da95
equal deleted inserted replaced
54411:1ad7f5bcc670 54412:41356f083e93
    30  *******************************************************************************
    30  *******************************************************************************
    31  */
    31  */
    32 
    32 
    33 package sun.util.locale;
    33 package sun.util.locale;
    34 
    34 
       
    35 import jdk.internal.misc.VM;
       
    36 import jdk.internal.vm.annotation.Stable;
       
    37 
    35 import java.lang.ref.SoftReference;
    38 import java.lang.ref.SoftReference;
    36 import java.util.StringJoiner;
    39 import java.util.StringJoiner;
    37 
    40 
    38 public final class BaseLocale {
    41 public final class BaseLocale {
    39 
    42 
       
    43     public static @Stable BaseLocale[] constantBaseLocales;
       
    44     public static final byte ENGLISH = 0,
       
    45             FRENCH = 1,
       
    46             GERMAN = 2,
       
    47             ITALIAN = 3,
       
    48             JAPANESE = 4,
       
    49             KOREAN = 5,
       
    50             CHINESE = 6,
       
    51             SIMPLIFIED_CHINESE = 7,
       
    52             TRADITIONAL_CHINESE = 8,
       
    53             FRANCE = 9,
       
    54             GERMANY = 10,
       
    55             ITALY = 11,
       
    56             JAPAN = 12,
       
    57             KOREA = 13,
       
    58             UK = 14,
       
    59             US = 15,
       
    60             CANADA = 16,
       
    61             CANADA_FRENCH = 17,
       
    62             ROOT = 18,
       
    63             NUM_CONSTANTS = 19;
       
    64     static {
       
    65         VM.initializeFromArchive(BaseLocale.class);
       
    66         BaseLocale[] baseLocales = constantBaseLocales;
       
    67         if (baseLocales == null) {
       
    68             baseLocales = new BaseLocale[NUM_CONSTANTS];
       
    69             baseLocales[ENGLISH] = createInstance("en", "");
       
    70             baseLocales[FRENCH] = createInstance("fr", "");
       
    71             baseLocales[GERMAN] = createInstance("de", "");
       
    72             baseLocales[ITALIAN] = createInstance("it", "");
       
    73             baseLocales[JAPANESE] = createInstance("ja", "");
       
    74             baseLocales[KOREAN] = createInstance("ko", "");
       
    75             baseLocales[CHINESE] = createInstance("zh", "");
       
    76             baseLocales[SIMPLIFIED_CHINESE] = createInstance("zh", "CN");
       
    77             baseLocales[TRADITIONAL_CHINESE] = createInstance("zh", "TW");
       
    78             baseLocales[FRANCE] = createInstance("fr", "FR");
       
    79             baseLocales[GERMANY] = createInstance("de", "DE");
       
    80             baseLocales[ITALY] = createInstance("it", "IT");
       
    81             baseLocales[JAPAN] = createInstance("ja", "JP");
       
    82             baseLocales[KOREA] = createInstance("ko", "KR");
       
    83             baseLocales[UK] = createInstance("en", "GB");
       
    84             baseLocales[US] = createInstance("en", "US");
       
    85             baseLocales[CANADA] = createInstance("en", "CA");
       
    86             baseLocales[CANADA_FRENCH] = createInstance("fr", "CA");
       
    87             baseLocales[ROOT] = createInstance("", "");
       
    88             constantBaseLocales = baseLocales;
       
    89         }
       
    90     }
       
    91 
    40     public static final String SEP = "_";
    92     public static final String SEP = "_";
    41 
       
    42     private static final Cache CACHE = new Cache();
       
    43 
    93 
    44     private final String language;
    94     private final String language;
    45     private final String script;
    95     private final String script;
    46     private final String region;
    96     private final String region;
    47     private final String variant;
    97     private final String variant;
    65         }
   115         }
    66     }
   116     }
    67 
   117 
    68     // Called for creating the Locale.* constants. No argument
   118     // Called for creating the Locale.* constants. No argument
    69     // validation is performed.
   119     // validation is performed.
    70     public static BaseLocale createInstance(String language, String region) {
   120     private static BaseLocale createInstance(String language, String region) {
    71         BaseLocale base = new BaseLocale(language, "", region, "", false);
   121         return new BaseLocale(language, "", region, "", false);
    72         CACHE.put(new Key(base), base);
       
    73         return base;
       
    74     }
   122     }
    75 
   123 
    76     public static BaseLocale getInstance(String language, String script,
   124     public static BaseLocale getInstance(String language, String script,
    77                                          String region, String variant) {
   125                                          String region, String variant) {
       
   126 
       
   127         if (script == null) {
       
   128             script = "";
       
   129         }
       
   130         if (region == null) {
       
   131             region = "";
       
   132         }
       
   133         if (language == null) {
       
   134             language = null;
       
   135         }
       
   136         if (variant == null) {
       
   137             variant = "";
       
   138         }
       
   139 
       
   140         // Non-allocating for most uses
       
   141         language = LocaleUtils.toLowerString(language);
       
   142         region = LocaleUtils.toUpperString(region);
       
   143 
       
   144         // Check for constant base locales first
       
   145         if (script.isEmpty() && variant.isEmpty()) {
       
   146             for (BaseLocale baseLocale : constantBaseLocales) {
       
   147                 if (baseLocale.getLanguage().equals(language)
       
   148                         && baseLocale.getRegion().equals(region)) {
       
   149                     return baseLocale;
       
   150                 }
       
   151             }
       
   152         }
       
   153 
    78         // JDK uses deprecated ISO639.1 language codes for he, yi and id
   154         // JDK uses deprecated ISO639.1 language codes for he, yi and id
    79         if (language != null) {
   155         if (!language.isEmpty()) {
    80             if (LocaleUtils.caseIgnoreMatch(language, "he")) {
   156             if (language.equals("he")) {
    81                 language = "iw";
   157                 language = "iw";
    82             } else if (LocaleUtils.caseIgnoreMatch(language, "yi")) {
   158             } else if (language.equals("yi")) {
    83                 language = "ji";
   159                 language = "ji";
    84             } else if (LocaleUtils.caseIgnoreMatch(language, "id")) {
   160             } else if (language.equals("id")) {
    85                 language = "in";
   161                 language = "in";
    86             }
   162             }
    87         }
   163         }
    88 
   164 
    89         Key key = new Key(language, script, region, variant, false);
   165         Key key = new Key(language, script, region, variant, false);
    90         BaseLocale baseLocale = CACHE.get(key);
   166         return Cache.CACHE.get(key);
    91         return baseLocale;
       
    92     }
   167     }
    93 
   168 
    94     public String getLanguage() {
   169     public String getLanguage() {
    95         return language;
   170         return language;
    96     }
   171     }
   169         private final BaseLocale holder;
   244         private final BaseLocale holder;
   170 
   245 
   171         private final boolean normalized;
   246         private final boolean normalized;
   172         private final int hash;
   247         private final int hash;
   173 
   248 
   174         /**
       
   175          * Creates a Key. language and region must be normalized
       
   176          * (intern'ed in the proper case).
       
   177          */
       
   178         private Key(BaseLocale locale) {
       
   179             this.holder = locale;
       
   180             this.holderRef = null;
       
   181             this.normalized = true;
       
   182             String language = locale.getLanguage();
       
   183             String region = locale.getRegion();
       
   184             assert LocaleUtils.toLowerString(language).intern() == language
       
   185                     && LocaleUtils.toUpperString(region).intern() == region
       
   186                     && locale.getVariant() == ""
       
   187                     && locale.getScript() == "";
       
   188 
       
   189             int h = language.hashCode();
       
   190             if (region != "") {
       
   191                 int len = region.length();
       
   192                 for (int i = 0; i < len; i++) {
       
   193                     h = 31 * h + LocaleUtils.toLower(region.charAt(i));
       
   194                 }
       
   195             }
       
   196             hash = h;
       
   197         }
       
   198 
       
   199         private Key(String language, String script, String region,
   249         private Key(String language, String script, String region,
   200                     String variant, boolean normalize) {
   250                     String variant, boolean normalize) {
   201             if (language == null) {
       
   202                 language = "";
       
   203             }
       
   204             if (script == null) {
       
   205                 script = "";
       
   206             }
       
   207             if (region == null) {
       
   208                 region = "";
       
   209             }
       
   210             if (variant == null) {
       
   211                 variant = "";
       
   212             }
       
   213 
       
   214             BaseLocale locale = new BaseLocale(language, script, region, variant, normalize);
   251             BaseLocale locale = new BaseLocale(language, script, region, variant, normalize);
   215             this.normalized = normalize;
   252             this.normalized = normalize;
   216             if (normalized) {
   253             if (normalized) {
   217                 this.holderRef = new SoftReference<>(locale);
   254                 this.holderRef = new SoftReference<>(locale);
   218                 this.holder = null;
   255                 this.holder = null;
   289         }
   326         }
   290     }
   327     }
   291 
   328 
   292     private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
   329     private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
   293 
   330 
       
   331         private static final Cache CACHE = new Cache();
       
   332 
   294         public Cache() {
   333         public Cache() {
   295         }
   334         }
   296 
   335 
   297         @Override
   336         @Override
   298         protected Key normalizeKey(Key key) {
   337         protected Key normalizeKey(Key key) {