< prev index next >

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

Print this page
rev 54349 : 8221701: Archive constant BaseLocales
Reviewed-by: TBD


  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) {
 112         if (this == 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.Map;
  40 import java.util.StringJoiner;
  41 
  42 public final class BaseLocale {
  43 
  44     // Initialized by java.util.Locale
  45     public static @Stable Map<String, Map<String, BaseLocale>> constantBaseLocales;
  46     static {
  47         VM.initializeFromArchive(BaseLocale.class);
  48     }
  49 
  50     public static final String SEP = "_";
  51 
  52     private final String language;
  53     private final String script;
  54     private final String region;
  55     private final String variant;
  56 
  57     private volatile int hash;
  58 
  59     // This method must be called with normalize = false only when creating the
  60     // Locale.* constants and non-normalized BaseLocale$Keys used for lookup.
  61     private BaseLocale(String language, String script, String region, String variant,
  62                        boolean normalize) {
  63         if (normalize) {
  64             this.language = LocaleUtils.toLowerString(language).intern();
  65             this.script = LocaleUtils.toTitleString(script).intern();
  66             this.region = LocaleUtils.toUpperString(region).intern();
  67             this.variant = variant.intern();
  68         } else {
  69             this.language = language;
  70             this.script = script;
  71             this.region = region;
  72             this.variant = variant;
  73         }
  74     }
  75 
  76     // Called for creating the Locale.* constants. No argument
  77     // validation is performed.
  78     public static BaseLocale createInstance(String language, String region) {
  79         assert LocaleUtils.toLowerString(language).intern() == language
  80                 && LocaleUtils.toUpperString(region).intern() == region;
  81         BaseLocale base = new BaseLocale(language, "", region, "", false);

  82         return base;
  83     }
  84 
  85     public static BaseLocale getInstance(String language, String script,
  86                                          String region, String variant) {
  87 
  88         if (language != null) {
  89             // JDK uses deprecated ISO639.1 language codes for he, yi and id
  90             if (LocaleUtils.caseIgnoreMatch(language, "he")) {
  91                 language = "iw";
  92             } else if (LocaleUtils.caseIgnoreMatch(language, "yi")) {
  93                 language = "ji";
  94             } else if (LocaleUtils.caseIgnoreMatch(language, "id")) {
  95                 language = "in";
  96             }
  97         } else {
  98             language = "";
  99         }
 100         if (script == null) {
 101             script = "";
 102         }
 103         if (region == null) {
 104             region = "";
 105         }
 106         if (variant == null) {
 107             variant = "";
 108         }
 109 
 110         // Check for constant base locales first
 111         if (script.isEmpty() && variant.isEmpty()) {
 112             BaseLocale baseLocale = constantBaseLocales
 113                     .getOrDefault(LocaleUtils.toLowerString(language), Map.of())
 114                     .get(LocaleUtils.toUpperString(region));
 115             if (baseLocale != null) {
 116                 return baseLocale;
 117             }
 118         }
 119 
 120         Key key = new Key(language, script, region, variant, false);
 121         return Cache.CACHE.get(key);
 122     }
 123 
 124     public String getLanguage() {
 125         return language;
 126     }
 127 
 128     public String getScript() {
 129         return script;
 130     }
 131 
 132     public String getRegion() {
 133         return region;
 134     }
 135 
 136     public String getVariant() {
 137         return variant;
 138     }
 139 
 140     @Override
 141     public boolean equals(Object obj) {
 142         if (this == obj) {


 184             }
 185         }
 186         return h;
 187     }
 188 
 189     private static final class Key {
 190         /**
 191          * Keep a SoftReference to the Key data if normalized (actually used
 192          * as a cache key) and not initialized via the constant creation path.
 193          *
 194          * This allows us to avoid creating SoftReferences on lookup Keys
 195          * (which are short-lived) and for Locales created via
 196          * Locale#createConstant.
 197          */
 198         private final SoftReference<BaseLocale> holderRef;
 199         private final BaseLocale holder;
 200 
 201         private final boolean normalized;
 202         private final int hash;
 203 

























 204         private Key(String language, String script, String region,
 205                     String variant, boolean normalize) {













 206             BaseLocale locale = new BaseLocale(language, script, region, variant, normalize);
 207             this.normalized = normalize;
 208             if (normalized) {
 209                 this.holderRef = new SoftReference<>(locale);
 210                 this.holder = null;
 211             } else {
 212                 this.holderRef = null;
 213                 this.holder = locale;
 214             }
 215             this.hash = hashCode(locale);
 216         }
 217 
 218         public int hashCode() {
 219             return hash;
 220         }
 221 
 222         private int hashCode(BaseLocale locale) {
 223             int h = 0;
 224             String lang = locale.getLanguage();
 225             int len = lang.length();


 265                     return true;
 266                 }
 267             }
 268             return false;
 269         }
 270 
 271         public static Key normalize(Key key) {
 272             if (key.normalized) {
 273                 return key;
 274             }
 275 
 276             // Only normalized keys may be softly referencing the data holder
 277             assert (key.holder != null && key.holderRef == null);
 278             BaseLocale locale = key.holder;
 279             return new Key(locale.getLanguage(), locale.getScript(),
 280                     locale.getRegion(), locale.getVariant(), true);
 281         }
 282     }
 283 
 284     private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
 285 
 286         private static final Cache CACHE = new Cache();
 287 
 288         public Cache() {
 289         }
 290 
 291         @Override
 292         protected Key normalizeKey(Key key) {
 293             return Key.normalize(key);
 294         }
 295 
 296         @Override
 297         protected BaseLocale createObject(Key key) {
 298             return Key.normalize(key).getBaseLocale();
 299         }
 300     }
 301 }
< prev index next >