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()); + } }