src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java
Print this page
*** 28,43 ****
--- 28,49 ----
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.text.spi.BreakIteratorProvider;
import java.text.spi.CollatorProvider;
+ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+ import java.util.List;
import java.util.Locale;
+ import java.util.Map;
+ import java.util.Objects;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.StringTokenizer;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
import sun.util.locale.provider.JRELocaleProviderAdapter;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleDataMetaInfo;
/**
*** 46,60 ****
* @author Masayoshi Okutsu
* @author Naoto Sato
*/
public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
! private final LocaleDataMetaInfo metaInfo;
public CLDRLocaleProviderAdapter() {
try {
! metaInfo = AccessController.doPrivileged(new PrivilegedExceptionAction<LocaleDataMetaInfo>() {
@Override
public LocaleDataMetaInfo run() {
for (LocaleDataMetaInfo ldmi : ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
if (ldmi.getType() == LocaleProviderAdapter.Type.CLDR) {
return ldmi;
--- 52,71 ----
* @author Masayoshi Okutsu
* @author Naoto Sato
*/
public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
! private static final CLDRBaseLocaleDataMetaInfo baseMetaInfo = new CLDRBaseLocaleDataMetaInfo();
! // Assumption: CLDR has only one non-Base module.
! private final LocaleDataMetaInfo nonBaseMetaInfo;
!
! // parent locales map
! private static ConcurrentMap<Locale, Locale> parentLocalesMap = null;
public CLDRLocaleProviderAdapter() {
try {
! nonBaseMetaInfo = AccessController.doPrivileged(new PrivilegedExceptionAction<LocaleDataMetaInfo>() {
@Override
public LocaleDataMetaInfo run() {
for (LocaleDataMetaInfo ldmi : ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
if (ldmi.getType() == LocaleProviderAdapter.Type.CLDR) {
return ldmi;
*** 68,78 ****
// It's ok ignore it if something wrong happens because there always is the
// JRE or FALLBACK LocaleProviderAdapter that will do the right thing.
throw new UnsupportedOperationException(e);
}
! if (metaInfo == null) {
throw new UnsupportedOperationException("CLDR locale data could not be found.");
}
}
/**
--- 79,89 ----
// It's ok ignore it if something wrong happens because there always is the
// JRE or FALLBACK LocaleProviderAdapter that will do the right thing.
throw new UnsupportedOperationException(e);
}
! if (nonBaseMetaInfo == null) {
throw new UnsupportedOperationException("CLDR locale data could not be found.");
}
}
/**
*** 105,121 ****
return locs;
}
@Override
protected Set<String> createLanguageTagSet(String category) {
! String supportedLocaleString = metaInfo.availableLanguageTags(category);
if (supportedLocaleString == null) {
return Collections.emptySet();
}
Set<String> tagset = new HashSet<>();
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
while (tokens.hasMoreTokens()) {
tagset.add(tokens.nextToken());
}
return tagset;
}
}
--- 116,182 ----
return locs;
}
@Override
protected Set<String> createLanguageTagSet(String category) {
! // Directly call Base tags, as we know it's in the base module.
! String supportedLocaleString = baseMetaInfo.availableLanguageTags(category);
! String nonBaseTags = nonBaseMetaInfo.availableLanguageTags(category);
! if (nonBaseTags != null) {
! if (supportedLocaleString != null) {
! supportedLocaleString += " " + nonBaseTags;
! } else {
! supportedLocaleString = nonBaseTags;
! }
! }
if (supportedLocaleString == null) {
return Collections.emptySet();
}
Set<String> tagset = new HashSet<>();
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
while (tokens.hasMoreTokens()) {
tagset.add(tokens.nextToken());
}
return tagset;
}
+
+ // Implementation of ResourceBundleBasedAdapter
+ @Override
+ public List<Locale> getCandidateLocales(String baseName, Locale locale) {
+ List<Locale> candidates = super.getCandidateLocales(baseName, locale);
+ return applyParentLocales(baseName, candidates);
+ }
+
+ private List<Locale> applyParentLocales(String baseName, List<Locale> candidates) {
+ if (Objects.isNull(parentLocalesMap)) {
+ parentLocalesMap = new ConcurrentHashMap<>();
+ Map<String, String> parentLocales = baseMetaInfo.parentLocales();
+ parentLocales.keySet().forEach(parent -> {
+ Arrays.asList(parentLocales.get(parent).split(" ")).stream().forEach(child -> {
+ parentLocalesMap.put(Locale.forLanguageTag(child),
+ "root".equals(parent) ? Locale.ROOT : Locale.forLanguageTag(parent));
+ });
+ });
+ }
+
+ // check irregular parents
+ for (int i = 0; i < candidates.size(); i++) {
+ Locale l = candidates.get(i);
+ Locale p = parentLocalesMap.get(l);
+ if (!l.equals(Locale.ROOT) &&
+ Objects.nonNull(p) &&
+ !candidates.get(i+1).equals(p)) {
+ List<Locale> applied = candidates.subList(0, i+1);
+ applied.addAll(applyParentLocales(baseName, super.getCandidateLocales(baseName, p)));
+ return applied;
+ }
+ }
+
+ return candidates;
+ }
+
+ @Override
+ public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
+ return Locale.ROOT.equals(locale) ||
+ langtags.contains(locale.stripExtensions().toLanguageTag());
+ }
}