Mercurial > hg > jdk9-shenandoah > jdk
view src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java @ 12723:56cc614c57f5
8134915: Improve performance of CLDRLocaleProviderAdapter.getCandidateLocales
Reviewed-by: okutsu
author | naoto |
---|---|
date | Thu, 10 Sep 2015 16:50:39 -0700 |
parents | 22f901cf304f |
children |
line wrap: on
line source
/* * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.util.cldr; 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.HashMap; 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.stream.Stream; import sun.util.locale.provider.JRELocaleProviderAdapter; import sun.util.locale.provider.LocaleProviderAdapter; import sun.util.locale.provider.LocaleDataMetaInfo; /** * LocaleProviderAdapter implementation for the CLDR locale data. * * @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 volatile Map<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; } } return null; } }); } catch (Exception e) { // Catch any exception, and fail gracefully as if CLDR locales do not exist. // 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."); } } /** * Returns the type of this LocaleProviderAdapter * @return the type of this */ @Override public LocaleProviderAdapter.Type getAdapterType() { return LocaleProviderAdapter.Type.CLDR; } @Override public BreakIteratorProvider getBreakIteratorProvider() { return null; } @Override public CollatorProvider getCollatorProvider() { return null; } @Override public Locale[] getAvailableLocales() { Set<String> all = createLanguageTagSet("AvailableLocales"); Locale[] locs = new Locale[all.size()]; int index = 0; for (String tag : all) { locs[index++] = Locale.forLanguageTag(tag); } 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)) { Map<Locale, Locale> map = new HashMap<>(); baseMetaInfo.parentLocales().forEach((parent, children) -> { Stream.of(children).forEach(child -> { map.put(Locale.forLanguageTag(child), parent); }); }); parentLocalesMap = Collections.unmodifiableMap(map); } // 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()); } }