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; |