• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4  *******************************************************************************
5  * Copyright (C) 2009-2010, International Business Machines Corporation and    *
6  * others. All Rights Reserved.                                                *
7  *******************************************************************************
8  */
9 
10 package com.ibm.icu.impl.locale;
11 
12 
13 public final class BaseLocale {
14 
15     private static final boolean JDKIMPL = false;
16 
17     public static final String SEP = "_";
18 
19     private static final Cache CACHE = new Cache();
20     public static final BaseLocale ROOT = BaseLocale.getInstance("", "", "", "");
21 
22     private String _language = "";
23     private String _script = "";
24     private String _region = "";
25     private String _variant = "";
26 
27     private transient volatile int _hash = 0;
28 
BaseLocale(String language, String script, String region, String variant)29     private BaseLocale(String language, String script, String region, String variant) {
30         if (language != null) {
31             _language = AsciiUtil.toLowerString(language).intern();
32         }
33         if (script != null) {
34             _script = AsciiUtil.toTitleString(script).intern();
35         }
36         if (region != null) {
37             _region = AsciiUtil.toUpperString(region).intern();
38         }
39         if (variant != null) {
40             if (JDKIMPL) {
41                 // preserve upper/lower cases
42                 _variant = variant.intern();
43             } else {
44                 _variant = AsciiUtil.toUpperString(variant).intern();
45             }
46         }
47     }
48 
getInstance(String language, String script, String region, String variant)49     public static BaseLocale getInstance(String language, String script, String region, String variant) {
50         if (JDKIMPL) {
51             // JDK uses deprecated ISO639.1 language codes for he, yi and id
52             if (AsciiUtil.caseIgnoreMatch(language, "he")) {
53                 language = "iw";
54             } else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
55                 language = "ji";
56             } else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
57                 language = "in";
58             }
59         }
60         Key key = new Key(language, script, region, variant);
61         BaseLocale baseLocale = CACHE.get(key);
62         return baseLocale;
63     }
64 
getLanguage()65     public String getLanguage() {
66         return _language;
67     }
68 
getScript()69     public String getScript() {
70         return _script;
71     }
72 
getRegion()73     public String getRegion() {
74         return _region;
75     }
76 
getVariant()77     public String getVariant() {
78         return _variant;
79     }
80 
81     @Override
equals(Object obj)82     public boolean equals(Object obj) {
83         if (this == obj) {
84             return true;
85         }
86         if (!(obj instanceof BaseLocale)) {
87             return false;
88         }
89         BaseLocale other = (BaseLocale)obj;
90         return hashCode() == other.hashCode()
91                 && _language.equals(other._language)
92                 && _script.equals(other._script)
93                 && _region.equals(other._region)
94                 && _variant.equals(other._variant);
95     }
96 
97     @Override
toString()98     public String toString() {
99         StringBuilder buf = new StringBuilder();
100         if (_language.length() > 0) {
101             buf.append("language=");
102             buf.append(_language);
103         }
104         if (_script.length() > 0) {
105             if (buf.length() > 0) {
106                 buf.append(", ");
107             }
108             buf.append("script=");
109             buf.append(_script);
110         }
111         if (_region.length() > 0) {
112             if (buf.length() > 0) {
113                 buf.append(", ");
114             }
115             buf.append("region=");
116             buf.append(_region);
117         }
118         if (_variant.length() > 0) {
119             if (buf.length() > 0) {
120                 buf.append(", ");
121             }
122             buf.append("variant=");
123             buf.append(_variant);
124         }
125         return buf.toString();
126     }
127 
128     @Override
hashCode()129     public int hashCode() {
130         int h = _hash;
131         if (h == 0) {
132             // Generating a hash value from language, script, region and variant
133             for (int i = 0; i < _language.length(); i++) {
134                 h = 31*h + _language.charAt(i);
135             }
136             for (int i = 0; i < _script.length(); i++) {
137                 h = 31*h + _script.charAt(i);
138             }
139             for (int i = 0; i < _region.length(); i++) {
140                 h = 31*h + _region.charAt(i);
141             }
142             for (int i = 0; i < _variant.length(); i++) {
143                 h = 31*h + _variant.charAt(i);
144             }
145             _hash = h;
146         }
147         return h;
148     }
149 
150     private static class Key implements Comparable<Key> {
151         private String _lang = "";
152         private String _scrt = "";
153         private String _regn = "";
154         private String _vart = "";
155 
156         private volatile int _hash; // Default to 0
157 
Key(String language, String script, String region, String variant)158         public Key(String language, String script, String region, String variant) {
159             if (language != null) {
160                 _lang = language;
161             }
162             if (script != null) {
163                 _scrt = script;
164             }
165             if (region != null) {
166                 _regn = region;
167             }
168             if (variant != null) {
169                 _vart = variant;
170             }
171         }
172 
173         @Override
equals(Object obj)174         public boolean equals(Object obj) {
175             if (JDKIMPL) {
176                 return (this == obj) ||
177                         (obj instanceof Key)
178                         && AsciiUtil.caseIgnoreMatch(((Key)obj)._lang, this._lang)
179                         && AsciiUtil.caseIgnoreMatch(((Key)obj)._scrt, this._scrt)
180                         && AsciiUtil.caseIgnoreMatch(((Key)obj)._regn, this._regn)
181                         && ((Key)obj)._vart.equals(_vart); // variant is case sensitive in JDK!
182             }
183             return (this == obj) ||
184                     (obj instanceof Key)
185                     && AsciiUtil.caseIgnoreMatch(((Key)obj)._lang, this._lang)
186                     && AsciiUtil.caseIgnoreMatch(((Key)obj)._scrt, this._scrt)
187                     && AsciiUtil.caseIgnoreMatch(((Key)obj)._regn, this._regn)
188                     && AsciiUtil.caseIgnoreMatch(((Key)obj)._vart, this._vart);
189         }
190 
191         @Override
compareTo(Key other)192         public int compareTo(Key other) {
193             int res = AsciiUtil.caseIgnoreCompare(this._lang, other._lang);
194             if (res == 0) {
195                 res = AsciiUtil.caseIgnoreCompare(this._scrt, other._scrt);
196                 if (res == 0) {
197                     res = AsciiUtil.caseIgnoreCompare(this._regn, other._regn);
198                     if (res == 0) {
199                         if (JDKIMPL) {
200                             res = this._vart.compareTo(other._vart);
201                         } else {
202                             res = AsciiUtil.caseIgnoreCompare(this._vart, other._vart);
203                         }
204                     }
205                 }
206             }
207             return res;
208         }
209 
210         @Override
hashCode()211         public int hashCode() {
212             int h = _hash;
213             if (h == 0) {
214                 // Generating a hash value from language, script, region and variant
215                 for (int i = 0; i < _lang.length(); i++) {
216                     h = 31*h + AsciiUtil.toLower(_lang.charAt(i));
217                 }
218                 for (int i = 0; i < _scrt.length(); i++) {
219                     h = 31*h + AsciiUtil.toLower(_scrt.charAt(i));
220                 }
221                 for (int i = 0; i < _regn.length(); i++) {
222                     h = 31*h + AsciiUtil.toLower(_regn.charAt(i));
223                 }
224                 for (int i = 0; i < _vart.length(); i++) {
225                     if (JDKIMPL) {
226                         h = 31*h + _vart.charAt(i);
227                     } else {
228                         h = 31*h + AsciiUtil.toLower(_vart.charAt(i));
229                     }
230                 }
231                 _hash = h;
232             }
233             return h;
234         }
235 
normalize(Key key)236         public static Key normalize(Key key) {
237             String lang = AsciiUtil.toLowerString(key._lang).intern();
238             String scrt = AsciiUtil.toTitleString(key._scrt).intern();
239             String regn = AsciiUtil.toUpperString(key._regn).intern();
240             String vart;
241             if (JDKIMPL) {
242                 // preserve upper/lower cases
243                 vart = key._vart.intern();
244             } else {
245                 vart = AsciiUtil.toUpperString(key._vart).intern();
246             }
247             return new Key(lang, scrt, regn, vart);
248         }
249     }
250 
251     private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
252 
Cache()253         public Cache() {
254         }
255 
256         @Override
normalizeKey(Key key)257         protected Key normalizeKey(Key key) {
258             return Key.normalize(key);
259         }
260 
261         @Override
createObject(Key key)262         protected BaseLocale createObject(Key key) {
263             return new BaseLocale(key._lang, key._scrt, key._regn, key._vart);
264         }
265 
266     }
267 }
268