]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/classes/localespi/src/com/ibm/icu/impl/javaspi/ICULocaleServiceProvider.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / localespi / src / com / ibm / icu / impl / javaspi / ICULocaleServiceProvider.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 2008-2012, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.impl.javaspi;
8
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.util.Arrays;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Locale;
16 import java.util.Map;
17 import java.util.Properties;
18 import java.util.Set;
19
20 import com.ibm.icu.impl.ICUResourceBundle;
21 import com.ibm.icu.util.ULocale;
22 import com.ibm.icu.util.ULocale.Builder;
23
24 public class ICULocaleServiceProvider {
25     private static final String SPI_PROP_FILE = "com/ibm/icu/impl/javaspi/ICULocaleServiceProviderConfig.properties";
26
27     private static final String SUFFIX_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.icuVariantSuffix";
28     private static final String ENABLE_VARIANTS_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIcuVariants";
29     private static final String ENABLE_ISO3_LANG_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.enableIso3Languages";
30     private static final String USE_DECIMALFORMAT_KEY = "com.ibm.icu.impl.javaspi.ICULocaleServiceProvider.useDecimalFormat";
31
32     private static boolean configLoaded = false;
33
34     private static String suffix = "ICU4J";
35     private static boolean enableVariants = true;
36     private static boolean enableIso3Lang = true;
37     private static boolean useDecimalFormat = false;
38
39     private static final Locale[] SPECIAL_LOCALES = {
40         new Locale("ja", "JP", "JP"),
41         new Locale("no"),
42         new Locale("no", "NO"),
43         new Locale("no", "NO", "NY"),
44         new Locale("sr", "CS"),
45         new Locale("th", "TH", "TH"),
46     };
47
48     private static Map<Locale, Locale> SPECIAL_LOCALES_MAP = null;
49
50     private static Locale[] LOCALES = null;
51
52     public static Locale[] getAvailableLocales() {
53         Locale[] all = getLocales();
54         return Arrays.copyOf(all, all.length);
55     }
56
57     public static ULocale toULocaleNoSpecialVariant(Locale locale) {
58         // If the given Locale has legacy ill-formed variant
59         // reserved by JDK, use the map to resolve the locale.
60         Locale spLoc = getSpecialLocalesMap().get(locale);
61         if (spLoc != null) {
62             return ULocale.forLocale(spLoc);
63         }
64
65         // The locale may have script field on Java 7+.
66         // So we once convert it to ULocale, then strip the ICU suffix off
67         // if necessary.
68         ULocale result = ULocale.forLocale(locale);
69         String variant = result.getVariant();
70         String suffix = getIcuSuffix();
71         String variantNoSuffix = null;
72         if (variant.equals(suffix)) {
73             variantNoSuffix = "";
74         } else if (variant.endsWith(suffix) && variant.charAt(variant.length() - suffix.length() - 1) == '_') {
75             variantNoSuffix = variant.substring(0, variant.length() - suffix.length() - 1);
76         }
77         if (variantNoSuffix == null) {
78             return result;
79         }
80
81         // Strip off ICU's special suffix - cannot use Builder because
82         // original locale may have ill-formed variant
83         StringBuilder id = new StringBuilder(result.getLanguage());
84         String script = result.getScript();
85         String country = result.getCountry();
86         if (script.length() > 0) {
87             id.append('_');
88             id.append(script);
89         }
90         if (country.length() > 0 || variantNoSuffix.length() > 0) {
91             id.append('_');
92             id.append(country);
93         }
94         if (variantNoSuffix.length() > 0) {
95             id.append('_');
96             id.append(variantNoSuffix);
97         }
98         String orgID = result.getName();
99         int kwdIdx = orgID.indexOf('@');
100         if (kwdIdx >= 0) {
101             id.append(orgID.substring(kwdIdx));
102         }
103         return new ULocale(id.toString());
104     }
105
106     public static boolean useDecimalFormat() {
107         loadConfiguration();
108         return useDecimalFormat;
109     }
110
111     private static synchronized Map<Locale, Locale> getSpecialLocalesMap() {
112         if (SPECIAL_LOCALES_MAP != null) {
113             return SPECIAL_LOCALES_MAP;
114         }
115
116         Map<Locale, Locale> splocs = new HashMap<Locale, Locale>();
117         for (Locale spLoc : SPECIAL_LOCALES) {
118             String var = spLoc.getVariant();
119             if (var.length() > 0) {
120                 splocs.put(new Locale(spLoc.getLanguage(), spLoc.getCountry(), var + "_" + getIcuSuffix()), spLoc);
121             }
122         }
123         SPECIAL_LOCALES_MAP = Collections.unmodifiableMap(splocs);
124         return SPECIAL_LOCALES_MAP;
125     }
126
127     private static synchronized Locale[] getLocales() {
128         if (LOCALES != null) {
129             return LOCALES;
130         }
131
132         Set<Locale> localeSet = new HashSet<Locale>();
133         ULocale[] icuLocales = ICUResourceBundle.getAvailableULocales();
134
135         for (ULocale uloc : icuLocales) {
136             String language = uloc.getLanguage();
137             if (language.length() >= 3 && !enableIso3Languages()) {
138                 continue;
139             }
140             addULocale(uloc, localeSet);
141
142             if (uloc.getScript().length() > 0 && uloc.getCountry().length() > 0) {
143                 // ICU's available locales do not contain language+country
144                 // locales if script is available. Need to add them too.
145                 Builder locBld = new Builder();
146                 try {
147                     locBld.setLocale(uloc);
148                     locBld.setScript(null);
149                     ULocale ulocWithoutScript = locBld.build();
150                     addULocale(ulocWithoutScript, localeSet);
151                 } catch (Exception e) {
152                     // ignore
153                 }
154             }
155         }
156
157         for (Locale l : SPECIAL_LOCALES) {
158             addLocale(l, localeSet);
159         }
160
161         LOCALES = localeSet.toArray(new Locale[0]);
162         return LOCALES;
163     }
164
165     private static void addLocale(Locale loc, Set<Locale> locales) {
166         locales.add(loc);
167
168         if (enableIcuVariants()) {
169             // Add ICU variant
170             String language = loc.getLanguage();
171             String country = loc.getCountry();
172             String variant = loc.getVariant();
173
174             StringBuilder var = new StringBuilder(variant);
175             if (var.length() != 0) {
176                 var.append("_");
177             }
178             var.append(getIcuSuffix());
179             locales.add(new Locale(language, country, var.toString()));
180         }
181     }
182
183     private static void addULocale(ULocale uloc, Set<Locale> locales) {
184         // special case - nn
185         // ULocale#toLocale on Java 6 maps "nn" to "no_NO_NY"
186         if (uloc.getLanguage().equals("nn") && uloc.getScript().length() == 0) {
187             Locale locNN = new Locale(uloc.getLanguage(), uloc.getCountry(), uloc.getVariant());
188             addLocale(locNN, locales);
189             return;
190         }
191
192         locales.add(uloc.toLocale());
193
194         if (enableIcuVariants()) {
195             // Add ICU variant
196             StringBuilder var = new StringBuilder(uloc.getVariant());
197             if (var.length() != 0) {
198                 var.append("_");
199             }
200             var.append(getIcuSuffix());
201
202             Builder locBld = new Builder();
203             try {
204                 locBld.setLocale(uloc);
205                 locBld.setVariant(var.toString());
206                 ULocale ulocWithVar = locBld.build();
207                 locales.add(ulocWithVar.toLocale());
208             } catch (Exception e) {
209                 // ignore
210             }
211         }
212     }
213
214     private static boolean enableIso3Languages() {
215         return enableIso3Lang;
216     }
217
218     private static boolean enableIcuVariants() {
219         loadConfiguration();
220         return enableVariants;
221     }
222
223     private static String getIcuSuffix() {
224         loadConfiguration();
225         return suffix;
226     }
227
228     private static synchronized void loadConfiguration() {
229         if (configLoaded) {
230             return;
231         }
232         Properties spiConfigProps = new Properties();
233         try {
234             InputStream is = ClassLoader.getSystemResourceAsStream(SPI_PROP_FILE);
235             spiConfigProps.load(is);
236
237             String val = (String)spiConfigProps.get(SUFFIX_KEY);
238             if (val != null && val.length() > 0) {
239                 suffix = val;
240             }
241             enableVariants = parseBooleanString((String)spiConfigProps.get(ENABLE_VARIANTS_KEY), enableVariants);
242             enableIso3Lang = parseBooleanString((String)spiConfigProps.get(ENABLE_ISO3_LANG_KEY), enableIso3Lang);
243             useDecimalFormat = parseBooleanString((String)spiConfigProps.get(USE_DECIMALFORMAT_KEY), useDecimalFormat);
244         } catch (IOException ioe) {
245             // Any IO errors, ignore
246         }
247         configLoaded = true;
248     }
249
250     private static boolean parseBooleanString(String str, boolean defaultVal) {
251         if (str == null) {
252             return defaultVal;
253         }
254         if (str.equalsIgnoreCase("true")) {
255             return true;
256         } else if (str.equalsIgnoreCase("false")) {
257             return false;
258         }
259         return defaultVal;
260     }
261 }