< prev index next >

src/java.base/share/classes/sun/util/locale/BaseLocale.java

Print this page
rev 54380 : 8221701: Archive constant BaseLocales
Reviewed-by: naoto


  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  *******************************************************************************
  28  * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  29  * others. All Rights Reserved.                                                *
  30  *******************************************************************************
  31  */
  32 
  33 package sun.util.locale;
  34 



  35 import java.lang.ref.SoftReference;
  36 import java.util.StringJoiner;
  37 
  38 public final class BaseLocale {
  39 
  40     public static final String SEP = "_";















































  41 
  42     private static final Cache CACHE = new Cache();
  43 
  44     private final String language;
  45     private final String script;
  46     private final String region;
  47     private final String variant;
  48 
  49     private volatile int hash;
  50 
  51     // This method must be called with normalize = false only when creating the
  52     // Locale.* constants and non-normalized BaseLocale$Keys used for lookup.
  53     private BaseLocale(String language, String script, String region, String variant,
  54                        boolean normalize) {
  55         if (normalize) {
  56             this.language = LocaleUtils.toLowerString(language).intern();
  57             this.script = LocaleUtils.toTitleString(script).intern();
  58             this.region = LocaleUtils.toUpperString(region).intern();
  59             this.variant = variant.intern();
  60         } else {
  61             this.language = language;
  62             this.script = script;
  63             this.region = region;
  64             this.variant = variant;
  65         }
  66     }
  67 
  68     // Called for creating the Locale.* constants. No argument
  69     // validation is performed.
  70     public static BaseLocale createInstance(String language, String region) {
  71         BaseLocale base = new BaseLocale(language, "", region, "", false);
  72         CACHE.put(new Key(base), base);
  73         return base;
  74     }
  75 
  76     public static BaseLocale getInstance(String language, String script,
  77                                          String region, String variant) {




























  78         // JDK uses deprecated ISO639.1 language codes for he, yi and id
  79         if (language != null) {
  80             if (LocaleUtils.caseIgnoreMatch(language, "he")) {
  81                 language = "iw";
  82             } else if (LocaleUtils.caseIgnoreMatch(language, "yi")) {
  83                 language = "ji";
  84             } else if (LocaleUtils.caseIgnoreMatch(language, "id")) {
  85                 language = "in";
  86             }
  87         }
  88 
  89         Key key = new Key(language, script, region, variant, false);
  90         BaseLocale baseLocale = CACHE.get(key);
  91         return baseLocale;
  92     }
  93 
  94     public String getLanguage() {
  95         return language;
  96     }
  97 
  98     public String getScript() {
  99         return script;
 100     }
 101 
 102     public String getRegion() {
 103         return region;
 104     }
 105 
 106     public String getVariant() {
 107         return variant;
 108     }
 109 
 110     @Override
 111     public boolean equals(Object obj) {


 154             }
 155         }
 156         return h;
 157     }
 158 
 159     private static final class Key {
 160         /**
 161          * Keep a SoftReference to the Key data if normalized (actually used
 162          * as a cache key) and not initialized via the constant creation path.
 163          *
 164          * This allows us to avoid creating SoftReferences on lookup Keys
 165          * (which are short-lived) and for Locales created via
 166          * Locale#createConstant.
 167          */
 168         private final SoftReference<BaseLocale> holderRef;
 169         private final BaseLocale holder;
 170 
 171         private final boolean normalized;
 172         private final int hash;
 173 
 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,
 200                     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);
 215             this.normalized = normalize;
 216             if (normalized) {
 217                 this.holderRef = new SoftReference<>(locale);
 218                 this.holder = null;
 219             } else {
 220                 this.holderRef = null;
 221                 this.holder = locale;
 222             }
 223             this.hash = hashCode(locale);
 224         }
 225 
 226         public int hashCode() {
 227             return hash;
 228         }
 229 
 230         private int hashCode(BaseLocale locale) {
 231             int h = 0;
 232             String lang = locale.getLanguage();
 233             int len = lang.length();


 273                     return true;
 274                 }
 275             }
 276             return false;
 277         }
 278 
 279         public static Key normalize(Key key) {
 280             if (key.normalized) {
 281                 return key;
 282             }
 283 
 284             // Only normalized keys may be softly referencing the data holder
 285             assert (key.holder != null && key.holderRef == null);
 286             BaseLocale locale = key.holder;
 287             return new Key(locale.getLanguage(), locale.getScript(),
 288                     locale.getRegion(), locale.getVariant(), true);
 289         }
 290     }
 291 
 292     private static class Cache extends LocaleObjectCache<Key, BaseLocale> {


 293 
 294         public Cache() {
 295         }
 296 
 297         @Override
 298         protected Key normalizeKey(Key key) {
 299             return Key.normalize(key);
 300         }
 301 
 302         @Override
 303         protected BaseLocale createObject(Key key) {
 304             return Key.normalize(key).getBaseLocale();
 305         }
 306     }
 307 }


  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  *******************************************************************************
  28  * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  29  * others. All Rights Reserved.                                                *
  30  *******************************************************************************
  31  */
  32 
  33 package sun.util.locale;
  34 
  35 import jdk.internal.misc.VM;
  36 import jdk.internal.vm.annotation.Stable;
  37 
  38 import java.lang.ref.SoftReference;
  39 import java.util.StringJoiner;
  40 
  41 public final class BaseLocale {
  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 
  92     public static final String SEP = "_";
  93 
  94     private final String language;
  95     private final String script;
  96     private final String region;
  97     private final String variant;
  98 
  99     private volatile int hash;
 100 
 101     // This method must be called with normalize = false only when creating the
 102     // Locale.* constants and non-normalized BaseLocale$Keys used for lookup.
 103     private BaseLocale(String language, String script, String region, String variant,
 104                        boolean normalize) {
 105         if (normalize) {
 106             this.language = LocaleUtils.toLowerString(language).intern();
 107             this.script = LocaleUtils.toTitleString(script).intern();
 108             this.region = LocaleUtils.toUpperString(region).intern();
 109             this.variant = variant.intern();
 110         } else {
 111             this.language = language;
 112             this.script = script;
 113             this.region = region;
 114             this.variant = variant;
 115         }
 116     }
 117 
 118     // Called for creating the Locale.* constants. No argument
 119     // validation is performed.
 120     private static BaseLocale createInstance(String language, String region) {
 121         return new BaseLocale(language, "", region, "", false);


 122     }
 123 
 124     public static BaseLocale getInstance(String language, String script,
 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 
 154         // JDK uses deprecated ISO639.1 language codes for he, yi and id
 155         if (!language.isEmpty()) {
 156             if (language.equals("he")) {
 157                 language = "iw";
 158             } else if (language.equals("yi")) {
 159                 language = "ji";
 160             } else if (language.equals("id")) {
 161                 language = "in";
 162             }
 163         }
 164 
 165         Key key = new Key(language, script, region, variant, false);
 166         return Cache.CACHE.get(key);

 167     }
 168 
 169     public String getLanguage() {
 170         return language;
 171     }
 172 
 173     public String getScript() {
 174         return script;
 175     }
 176 
 177     public String getRegion() {
 178         return region;
 179     }
 180 
 181     public String getVariant() {
 182         return variant;
 183     }
 184 
 185     @Override
 186     public boolean equals(Object obj) {


 229             }
 230         }
 231         return h;
 232     }
 233 
 234     private static final class Key {
 235         /**
 236          * Keep a SoftReference to the Key data if normalized (actually used
 237          * as a cache key) and not initialized via the constant creation path.
 238          *
 239          * This allows us to avoid creating SoftReferences on lookup Keys
 240          * (which are short-lived) and for Locales created via
 241          * Locale#createConstant.
 242          */
 243         private final SoftReference<BaseLocale> holderRef;
 244         private final BaseLocale holder;
 245 
 246         private final boolean normalized;
 247         private final int hash;
 248 

























 249         private Key(String language, String script, String region,
 250                     String variant, boolean normalize) {













 251             BaseLocale locale = new BaseLocale(language, script, region, variant, normalize);
 252             this.normalized = normalize;
 253             if (normalized) {
 254                 this.holderRef = new SoftReference<>(locale);
 255                 this.holder = null;
 256             } else {
 257                 this.holderRef = null;
 258                 this.holder = locale;
 259             }
 260             this.hash = hashCode(locale);
 261         }
 262 
 263         public int hashCode() {
 264             return hash;
 265         }
 266 
 267         private int hashCode(BaseLocale locale) {
 268             int h = 0;
 269             String lang = locale.getLanguage();
 270             int len = lang.length();


 310                     return true;
 311                 }
 312             }
 313             return false;
 314         }
 315 
 316         public static Key normalize(Key key) {
 317             if (key.normalized) {
 318                 return key;
 319             }
 320 
 321             // Only normalized keys may be softly referencing the data holder
 322             assert (key.holder != null && key.holderRef == null);
 323             BaseLocale locale = key.holder;
 324             return new Key(locale.getLanguage(), locale.getScript(),
 325                     locale.getRegion(), locale.getVariant(), true);
 326         }
 327     }
 328 
 329     private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
 330 
 331         private static final Cache CACHE = new Cache();
 332 
 333         public Cache() {
 334         }
 335 
 336         @Override
 337         protected Key normalizeKey(Key key) {
 338             return Key.normalize(key);
 339         }
 340 
 341         @Override
 342         protected BaseLocale createObject(Key key) {
 343             return Key.normalize(key).getBaseLocale();
 344         }
 345     }
 346 }
< prev index next >