28 import java.security.AccessController;
29 import java.security.AccessControlException;
30 import java.security.PrivilegedAction;
31 import java.security.PrivilegedActionException;
32 import java.security.PrivilegedExceptionAction;
33 import java.text.spi.BreakIteratorProvider;
34 import java.text.spi.CollatorProvider;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.Optional;
42 import java.util.ServiceLoader;
43 import java.util.ServiceConfigurationError;
44 import java.util.Set;
45 import java.util.StringTokenizer;
46 import java.util.concurrent.ConcurrentHashMap;
47 import java.util.spi.CalendarDataProvider;
48 import java.util.spi.TimeZoneNameProvider;
49 import sun.util.locale.provider.JRELocaleProviderAdapter;
50 import sun.util.locale.provider.LocaleDataMetaInfo;
51 import sun.util.locale.provider.LocaleProviderAdapter;
52
53 /**
54 * LocaleProviderAdapter implementation for the CLDR locale data.
55 *
56 * @author Masayoshi Okutsu
57 * @author Naoto Sato
58 */
59 public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
60
61 private static final CLDRBaseLocaleDataMetaInfo baseMetaInfo = new CLDRBaseLocaleDataMetaInfo();
62 // Assumption: CLDR has only one non-Base module.
63 private final LocaleDataMetaInfo nonBaseMetaInfo;
64
65 // parent locales map
66 private static volatile Map<Locale, Locale> parentLocalesMap;
67 // language aliases map
116
117 @Override
118 public CalendarDataProvider getCalendarDataProvider() {
119 if (calendarDataProvider == null) {
120 CalendarDataProvider provider = AccessController.doPrivileged(
121 (PrivilegedAction<CalendarDataProvider>) () ->
122 new CLDRCalendarDataProviderImpl(
123 getAdapterType(),
124 getLanguageTagSet("CalendarData")));
125
126 synchronized (this) {
127 if (calendarDataProvider == null) {
128 calendarDataProvider = provider;
129 }
130 }
131 }
132 return calendarDataProvider;
133 }
134
135 @Override
136 public CollatorProvider getCollatorProvider() {
137 return null;
138 }
139
140 @Override
141 public TimeZoneNameProvider getTimeZoneNameProvider() {
142 if (timeZoneNameProvider == null) {
143 TimeZoneNameProvider provider = AccessController.doPrivileged(
144 (PrivilegedAction<TimeZoneNameProvider>) () ->
145 new CLDRTimeZoneNameProviderImpl(
146 getAdapterType(),
147 getLanguageTagSet("TimeZoneNames")));
148
149 synchronized (this) {
150 if (timeZoneNameProvider == null) {
151 timeZoneNameProvider = provider;
152 }
153 }
154 }
155 return timeZoneNameProvider;
156 }
157
158 @Override
159 public Locale[] getAvailableLocales() {
160 Set<String> all = createLanguageTagSet("AvailableLocales");
161 Locale[] locs = new Locale[all.size()];
162 int index = 0;
163 for (String tag : all) {
164 locs[index++] = Locale.forLanguageTag(tag);
165 }
166 return locs;
167 }
168
169 private Locale applyAliases(Locale loc) {
170 if (langAliasesMap.isEmpty()) {
171 langAliasesMap = baseMetaInfo.getLanguageAliasMap();
172 }
173 Locale locale = langAliasesCache.get(loc);
174 if (locale == null) {
175 String locTag = loc.toLanguageTag();
176 Locale aliasLocale = langAliasesMap.containsKey(locTag)
177 ? Locale.forLanguageTag(langAliasesMap.get(locTag)) : loc;
178 langAliasesCache.putIfAbsent(loc, aliasLocale);
179 return aliasLocale;
180 } else {
181 return locale;
182 }
183 }
184
185 @Override
186 protected Set<String> createLanguageTagSet(String category) {
187 // Assume all categories support the same set as AvailableLocales
188 // in CLDR adapter.
189 category = "AvailableLocales";
247 if (Arrays.binarySearch(entry.getValue(), tag) >= 0) {
248 parent = entry.getKey();
249 break;
250 }
251 }
252 if (parent == null) {
253 parent = locale; // non existent marker
254 }
255 parentLocalesMap.putIfAbsent(locale, parent);
256 }
257
258 if (locale.equals(parent)) {
259 // means no irregular parent.
260 parent = null;
261 }
262
263 return parent;
264 }
265
266 /**
267 * This method returns equivalent CLDR supported locale for zh-HK,
268 * no, no-NO locales so that COMPAT locales do not precede
269 * those locales during ResourceBundle search path.
270 */
271 private static Locale getEquivalentLoc(Locale locale) {
272 switch (locale.toString()) {
273 case "zh_HK":
274 return Locale.forLanguageTag("zh-Hant-HK");
275 case "no":
276 case "no_NO":
277 return Locale.forLanguageTag("nb");
278 }
279 return locale;
280 }
281
282 @Override
283 public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
284 return Locale.ROOT.equals(locale)
285 || langtags.contains(locale.stripExtensions().toLanguageTag())
286 || langtags.contains(getEquivalentLoc(locale).toLanguageTag());
287 }
288
289 /**
290 * Returns the canonical ID for the given ID
291 */
292 public Optional<String> canonicalTZID(String id) {
293 return Optional.ofNullable(baseMetaInfo.tzCanonicalIDs().get(id));
294 }
295 }
|
28 import java.security.AccessController;
29 import java.security.AccessControlException;
30 import java.security.PrivilegedAction;
31 import java.security.PrivilegedActionException;
32 import java.security.PrivilegedExceptionAction;
33 import java.text.spi.BreakIteratorProvider;
34 import java.text.spi.CollatorProvider;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.Optional;
42 import java.util.ServiceLoader;
43 import java.util.ServiceConfigurationError;
44 import java.util.Set;
45 import java.util.StringTokenizer;
46 import java.util.concurrent.ConcurrentHashMap;
47 import java.util.spi.CalendarDataProvider;
48 import java.util.spi.CalendarNameProvider;
49 import java.util.spi.TimeZoneNameProvider;
50 import sun.util.locale.provider.JRELocaleProviderAdapter;
51 import sun.util.locale.provider.LocaleDataMetaInfo;
52 import sun.util.locale.provider.LocaleProviderAdapter;
53
54 /**
55 * LocaleProviderAdapter implementation for the CLDR locale data.
56 *
57 * @author Masayoshi Okutsu
58 * @author Naoto Sato
59 */
60 public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
61
62 private static final CLDRBaseLocaleDataMetaInfo baseMetaInfo = new CLDRBaseLocaleDataMetaInfo();
63 // Assumption: CLDR has only one non-Base module.
64 private final LocaleDataMetaInfo nonBaseMetaInfo;
65
66 // parent locales map
67 private static volatile Map<Locale, Locale> parentLocalesMap;
68 // language aliases map
117
118 @Override
119 public CalendarDataProvider getCalendarDataProvider() {
120 if (calendarDataProvider == null) {
121 CalendarDataProvider provider = AccessController.doPrivileged(
122 (PrivilegedAction<CalendarDataProvider>) () ->
123 new CLDRCalendarDataProviderImpl(
124 getAdapterType(),
125 getLanguageTagSet("CalendarData")));
126
127 synchronized (this) {
128 if (calendarDataProvider == null) {
129 calendarDataProvider = provider;
130 }
131 }
132 }
133 return calendarDataProvider;
134 }
135
136 @Override
137 public CalendarNameProvider getCalendarNameProvider() {
138 if (calendarNameProvider == null) {
139 CalendarNameProvider provider = AccessController.doPrivileged(
140 (PrivilegedAction<CalendarNameProvider>) ()
141 -> new CLDRCalendarNameProviderImpl(
142 getAdapterType(),
143 getLanguageTagSet("FormatData")));
144
145 synchronized (this) {
146 if (calendarNameProvider == null) {
147 calendarNameProvider = provider;
148 }
149 }
150 }
151 return calendarNameProvider;
152 }
153
154 @Override
155 public CollatorProvider getCollatorProvider() {
156 return null;
157 }
158
159 @Override
160 public TimeZoneNameProvider getTimeZoneNameProvider() {
161 if (timeZoneNameProvider == null) {
162 TimeZoneNameProvider provider = AccessController.doPrivileged(
163 (PrivilegedAction<TimeZoneNameProvider>) () ->
164 new CLDRTimeZoneNameProviderImpl(
165 getAdapterType(),
166 getLanguageTagSet("TimeZoneNames")));
167
168 synchronized (this) {
169 if (timeZoneNameProvider == null) {
170 timeZoneNameProvider = provider;
171 }
172 }
173 }
174 return timeZoneNameProvider;
175 }
176
177 @Override
178 public Locale[] getAvailableLocales() {
179 Set<String> all = createLanguageTagSet("AvailableLocales");
180 Locale[] locs = new Locale[all.size()];
181 int index = 0;
182 for (String tag : all) {
183 locs[index++] = Locale.forLanguageTag(tag);
184 }
185 return locs;
186 }
187
188 private static Locale applyAliases(Locale loc) {
189 if (langAliasesMap.isEmpty()) {
190 langAliasesMap = baseMetaInfo.getLanguageAliasMap();
191 }
192 Locale locale = langAliasesCache.get(loc);
193 if (locale == null) {
194 String locTag = loc.toLanguageTag();
195 Locale aliasLocale = langAliasesMap.containsKey(locTag)
196 ? Locale.forLanguageTag(langAliasesMap.get(locTag)) : loc;
197 langAliasesCache.putIfAbsent(loc, aliasLocale);
198 return aliasLocale;
199 } else {
200 return locale;
201 }
202 }
203
204 @Override
205 protected Set<String> createLanguageTagSet(String category) {
206 // Assume all categories support the same set as AvailableLocales
207 // in CLDR adapter.
208 category = "AvailableLocales";
266 if (Arrays.binarySearch(entry.getValue(), tag) >= 0) {
267 parent = entry.getKey();
268 break;
269 }
270 }
271 if (parent == null) {
272 parent = locale; // non existent marker
273 }
274 parentLocalesMap.putIfAbsent(locale, parent);
275 }
276
277 if (locale.equals(parent)) {
278 // means no irregular parent.
279 parent = null;
280 }
281
282 return parent;
283 }
284
285 /**
286 * This method returns equivalent CLDR supported locale
287 * for no, no-NO locales so that COMPAT locales do not precede
288 * those locales during ResourceBundle search path, also if an alias exists for a locale,
289 * it returns equivalent locale, e.g for zh_HK it returns zh_Hant-HK.
290 */
291 private static Locale getEquivalentLoc(Locale locale) {
292 switch (locale.toString()) {
293 case "no":
294 case "no_NO":
295 return Locale.forLanguageTag("nb");
296 }
297 return applyAliases(locale);
298 }
299
300 @Override
301 public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
302 return Locale.ROOT.equals(locale)
303 || langtags.contains(locale.stripExtensions().toLanguageTag())
304 || langtags.contains(getEquivalentLoc(locale).toLanguageTag());
305 }
306
307 /**
308 * Returns the canonical ID for the given ID
309 */
310 public Optional<String> canonicalTZID(String id) {
311 return Optional.ofNullable(baseMetaInfo.tzCanonicalIDs().get(id));
312 }
313 }
|