| /* |
| ******************************************************************************* |
| * Copyright (C) 2008-2010, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| package com.ibm.icu.impl.javaspi; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Locale; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import com.ibm.icu.impl.ICUResourceBundle; |
| import com.ibm.icu.text.DecimalFormatSymbols; |
| import com.ibm.icu.util.ULocale; |
| |
| public class ICULocaleServiceProvider { |
| private static final String SPI_PROP_FILE = "com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties"; |
| |
| private static final String SUFFIX_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.icuVariantSuffix"; |
| private static final String ENABLE_VARIANTS_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIcuVariants"; |
| private static final String ENABLE_ISO3_LANG_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIso3Languages"; |
| private static final String USE_DECIMALFORMAT_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.useDecimalFormat"; |
| |
| private static boolean configLoaded = false; |
| |
| private static String suffix = "ICU"; |
| private static boolean enableVariants = true; |
| private static boolean enableIso3Lang = true; |
| private static boolean useDecimalFormat = false; |
| |
| private static final Locale[] SPECIAL_LOCALES = { |
| new Locale("ja", "JP", "JP"), |
| new Locale("no"), |
| new Locale("no", "NO"), |
| new Locale("no", "NO", "NY"), |
| new Locale("sr", "CS"), |
| new Locale("th", "TH", "TH"), |
| }; |
| |
| private static Locale[] LOCALES = null; |
| |
| public static Locale[] getAvailableLocales() { |
| Locale[] all = getLocales(); |
| return Arrays.copyOf(all, all.length); |
| } |
| |
| public static Locale canonicalize(Locale locale) { |
| Locale result = locale; |
| String variant = locale.getVariant(); |
| String suffix = getIcuSuffix(); |
| if (variant.equals(suffix)) { |
| result = new Locale(locale.getLanguage(), locale.getCountry()); |
| } else if (variant.endsWith(suffix) |
| && variant.charAt(variant.length() - suffix.length() - 1) == '_') { |
| variant = variant.substring(0, variant.length() - suffix.length() - 1); |
| result = new Locale(locale.getLanguage(), locale.getCountry(), variant); |
| } |
| return result; |
| } |
| |
| public static boolean useDecimalFormat() { |
| loadConfiguration(); |
| return useDecimalFormat; |
| } |
| |
| private static final Locale THAI_NATIVE_DIGIT_LOCALE = new Locale("th", "TH", "TH"); |
| private static final char THAI_NATIVE_ZERO = '\u0E50'; |
| private static DecimalFormatSymbols THAI_NATIVE_DECIMAL_SYMBOLS = null; |
| |
| /* |
| * Returns a DecimalFormatSymbols if the given locale requires |
| * non-standard symbols, more specifically, native digits used |
| * by JDK Locale th_TH_TH. If the locale does not requre a special |
| * symbols, null is returned. |
| */ |
| public static synchronized DecimalFormatSymbols getDecimalFormatSymbolsForLocale(Locale loc) { |
| if (loc.equals(THAI_NATIVE_DIGIT_LOCALE)) { |
| if (THAI_NATIVE_DECIMAL_SYMBOLS == null) { |
| THAI_NATIVE_DECIMAL_SYMBOLS = new DecimalFormatSymbols(new ULocale("th_TH")); |
| THAI_NATIVE_DECIMAL_SYMBOLS.setDigit(THAI_NATIVE_ZERO); |
| } |
| return (DecimalFormatSymbols)THAI_NATIVE_DECIMAL_SYMBOLS.clone(); |
| } |
| return null; |
| } |
| |
| private static synchronized Locale[] getLocales() { |
| if (LOCALES != null) { |
| return LOCALES; |
| } |
| |
| Set<Locale> localeSet = new HashSet<Locale>(); |
| ULocale[] icuLocales = ICUResourceBundle.getAvailableULocales(); |
| |
| for (ULocale uloc : icuLocales) { |
| String language = uloc.getLanguage(); |
| String country = uloc.getCountry(); |
| String variant = uloc.getVariant(); |
| if (language.length() >= 3 && !enableIso3Languages()) { |
| continue; |
| } |
| addLocale(new Locale(language, country, variant), localeSet); |
| } |
| |
| for (Locale l : SPECIAL_LOCALES) { |
| addLocale(l, localeSet); |
| } |
| |
| LOCALES = localeSet.toArray(new Locale[0]); |
| return LOCALES; |
| } |
| |
| private static void addLocale(Locale loc, Set<Locale> locales) { |
| locales.add(loc); |
| |
| if (enableIcuVariants()) { |
| // Add ICU variant |
| String language = loc.getLanguage(); |
| String country = loc.getCountry(); |
| String variant = loc.getVariant(); |
| |
| StringBuilder var = new StringBuilder(variant); |
| if (var.length() != 0) { |
| var.append("_"); |
| } |
| var.append(getIcuSuffix()); |
| locales.add(new Locale(language, country, var.toString())); |
| } |
| } |
| |
| private static boolean enableIso3Languages() { |
| return enableIso3Lang; |
| } |
| |
| private static boolean enableIcuVariants() { |
| loadConfiguration(); |
| return enableVariants; |
| } |
| |
| private static String getIcuSuffix() { |
| loadConfiguration(); |
| return suffix; |
| } |
| |
| private static synchronized void loadConfiguration() { |
| if (configLoaded) { |
| return; |
| } |
| Properties spiConfigProps = new Properties(); |
| try { |
| InputStream is = ClassLoader.getSystemResourceAsStream(SPI_PROP_FILE); |
| spiConfigProps.load(is); |
| |
| String val = (String)spiConfigProps.get(SUFFIX_KEY); |
| if (val != null && val.length() > 0) { |
| suffix = val; |
| } |
| enableVariants = parseBooleanString((String)spiConfigProps.get(ENABLE_VARIANTS_KEY), enableVariants); |
| enableIso3Lang = parseBooleanString((String)spiConfigProps.get(ENABLE_ISO3_LANG_KEY), enableIso3Lang); |
| useDecimalFormat = parseBooleanString((String)spiConfigProps.get(USE_DECIMALFORMAT_KEY), useDecimalFormat); |
| } catch (IOException ioe) { |
| // Any IO errors, ignore |
| } |
| configLoaded = true; |
| } |
| |
| private static boolean parseBooleanString(String str, boolean defaultVal) { |
| if (str == null) { |
| return defaultVal; |
| } |
| if (str.equalsIgnoreCase("true")) { |
| return true; |
| } else if (str.equalsIgnoreCase("false")) { |
| return false; |
| } |
| return defaultVal; |
| } |
| } |