]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/impl/LocaleDisplayNamesImpl.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / impl / LocaleDisplayNamesImpl.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2009-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.impl;\r
8 \r
9 import java.util.Iterator;\r
10 import java.util.Locale;\r
11 \r
12 import com.ibm.icu.lang.UScript;\r
13 import com.ibm.icu.text.LocaleDisplayNames;\r
14 import com.ibm.icu.text.MessageFormat;\r
15 import com.ibm.icu.util.ULocale;\r
16 import com.ibm.icu.util.UResourceBundle;\r
17 \r
18 public class LocaleDisplayNamesImpl extends LocaleDisplayNames {\r
19     private final ULocale locale;\r
20     private final DialectHandling dialectHandling;\r
21     private final DataTable langData;\r
22     private final DataTable regionData;\r
23     private final Appender appender;\r
24     private final MessageFormat format;\r
25 \r
26     private static final Cache cache = new Cache();\r
27 \r
28     public static LocaleDisplayNames getInstance(ULocale locale, DialectHandling dialectHandling) {\r
29         synchronized (cache) {\r
30             return cache.get(locale, dialectHandling);\r
31         }\r
32     }\r
33 \r
34     public LocaleDisplayNamesImpl(ULocale locale, DialectHandling dialectHandling) {\r
35         this.dialectHandling = dialectHandling;\r
36         this.langData = LangDataTables.impl.get(locale);\r
37         this.regionData = RegionDataTables.impl.get(locale);\r
38         this.locale = ULocale.ROOT.equals(langData.getLocale()) ? regionData.getLocale() :\r
39             langData.getLocale();\r
40 \r
41         // Note, by going through DataTable, this uses table lookup rather than straight lookup.\r
42         // That should get us the same data, I think.  This way we don't have to explicitly\r
43         // load the bundle again.  Using direct lookup didn't seem to make an appreciable\r
44         // difference in performance.\r
45         String sep = langData.get("localeDisplayPattern", "separator");\r
46         if ("separator".equals(sep)) {\r
47             sep = ", ";\r
48         }\r
49         this.appender = new Appender(sep);\r
50 \r
51         String pattern = langData.get("localeDisplayPattern", "pattern");\r
52         if ("pattern".equals(pattern)) {\r
53             pattern = "{0} ({1})";\r
54         }\r
55         this.format = new MessageFormat(pattern);\r
56     }\r
57 \r
58     @Override\r
59     public ULocale getLocale() {\r
60         return locale;\r
61     }\r
62 \r
63     @Override\r
64     public DialectHandling getDialectHandling() {\r
65         return dialectHandling;\r
66     }\r
67 \r
68     @Override\r
69     public String localeDisplayName(ULocale locale) {\r
70         return localeDisplayNameInternal(locale);\r
71     }\r
72 \r
73     @Override\r
74     public String localeDisplayName(Locale locale) {\r
75         return localeDisplayNameInternal(ULocale.forLocale(locale));\r
76     }\r
77 \r
78     @Override\r
79     public String localeDisplayName(String localeId) {\r
80         return localeDisplayNameInternal(new ULocale(localeId));\r
81     }\r
82 \r
83     private String localeDisplayNameInternal(ULocale locale) {\r
84         // lang\r
85         // lang (script, country, variant, keyword=value, ...)\r
86         // script, country, variant, keyword=value, ...\r
87 \r
88         String resultName = null;\r
89 \r
90         String lang = locale.getLanguage();\r
91 \r
92         // Empty basename indicates root locale (keywords are ignored for this).\r
93         // Our data uses 'root' to access display names for the root locale in the\r
94         // "Languages" table.\r
95         if (locale.getBaseName().length() == 0) {\r
96             lang = "root";\r
97         }\r
98         String script = locale.getScript();\r
99         String country = locale.getCountry();\r
100         String variant = locale.getVariant();\r
101 \r
102         boolean hasScript = script.length() > 0;\r
103         boolean hasCountry = country.length() > 0;\r
104         boolean hasVariant = variant.length() > 0;\r
105 \r
106         // always have a value for lang\r
107         if (dialectHandling == DialectHandling.DIALECT_NAMES) {\r
108             do { // loop construct is so we can break early out of search\r
109                 if (hasScript && hasCountry) {\r
110                     String langScriptCountry = lang + '_' + script + '_' + country;\r
111                     String result = localeIdName(langScriptCountry);\r
112                     if (!result.equals(langScriptCountry)) {\r
113                         resultName = result;\r
114                         hasScript = false;\r
115                         hasCountry = false;\r
116                         break;\r
117                     }\r
118                 }\r
119                 if (hasScript) {\r
120                     String langScript = lang + '_' + script;\r
121                     String result = localeIdName(langScript);\r
122                     if (!result.equals(langScript)) {\r
123                         resultName = result;\r
124                         hasScript = false;\r
125                         break;\r
126                     }\r
127                 }\r
128                 if (hasCountry) {\r
129                     String langCountry = lang + '_' + country;\r
130                     String result = localeIdName(langCountry);\r
131                     if (!result.equals(langCountry)) {\r
132                         resultName = result;\r
133                         hasCountry = false;\r
134                         break;\r
135                     }\r
136                 }\r
137             } while (false);\r
138         }\r
139 \r
140         if (resultName == null) {\r
141             resultName = localeIdName(lang);\r
142         }\r
143 \r
144         StringBuilder buf = new StringBuilder();\r
145         if (hasScript) {\r
146             // first element, don't need appender\r
147             buf.append(scriptDisplayName(script));\r
148         }\r
149         if (hasCountry) {\r
150             appender.append(regionDisplayName(country), buf);\r
151         }\r
152         if (hasVariant) {\r
153             appender.append(variantDisplayName(variant), buf);\r
154         }\r
155 \r
156         Iterator<String> keys = locale.getKeywords();\r
157         if (keys != null) {\r
158             while (keys.hasNext()) {\r
159                 String key = keys.next();\r
160                 String value = locale.getKeywordValue(key);\r
161                 appender.append(keyDisplayName(key), buf)\r
162                     .append("=")\r
163                     .append(keyValueDisplayName(key, value));\r
164             }\r
165         }\r
166 \r
167         String resultRemainder = null;\r
168         if (buf.length() > 0) {\r
169             resultRemainder = buf.toString();\r
170         }\r
171 \r
172         if (resultRemainder != null) {\r
173             return format.format(new Object[] {resultName, resultRemainder});\r
174         }\r
175 \r
176         return resultName;\r
177     }\r
178 \r
179     private String localeIdName(String localeId) {\r
180         return langData.get("Languages", localeId);\r
181     }\r
182 \r
183     @Override\r
184     public String languageDisplayName(String lang) {\r
185         // Special case to eliminate non-languages, which pollute our data.\r
186         if (lang.equals("root") || lang.indexOf('_') != -1) {\r
187             return lang;\r
188         }\r
189         return langData.get("Languages", lang);\r
190     }\r
191 \r
192     @Override\r
193     public String scriptDisplayName(String script) {\r
194         return langData.get("Scripts", script);\r
195     }\r
196 \r
197     @Override\r
198     public String scriptDisplayName(int scriptCode) {\r
199         return scriptDisplayName(UScript.getShortName(scriptCode));\r
200     }\r
201 \r
202     @Override\r
203     public String regionDisplayName(String region) {\r
204         return regionData.get("Countries", region);\r
205     }\r
206 \r
207     @Override\r
208     public String variantDisplayName(String variant) {\r
209         return langData.get("Variants", variant);\r
210     }\r
211 \r
212     @Override\r
213     public String keyDisplayName(String key) {\r
214         return langData.get("Keys", key);\r
215     }\r
216 \r
217     @Override\r
218     public String keyValueDisplayName(String key, String value) {\r
219         return langData.get("Types", key, value);\r
220     }\r
221 \r
222     public static class DataTable {\r
223         ULocale getLocale() {\r
224             return ULocale.ROOT;\r
225         }\r
226 \r
227         String get(String tableName, String code) {\r
228             return get(tableName, null, code);\r
229         }\r
230 \r
231         String get(String tableName, String subTableName, String code) {\r
232             return code;\r
233         }\r
234     }\r
235 \r
236     static class ICUDataTable extends DataTable {\r
237         private final ICUResourceBundle bundle;\r
238 \r
239         public ICUDataTable(String path, ULocale locale) {\r
240             this.bundle = (ICUResourceBundle) UResourceBundle.getBundleInstance(\r
241                     path, locale.getBaseName());\r
242         }\r
243 \r
244         public ULocale getLocale() {\r
245             return bundle.getULocale();\r
246         }\r
247 \r
248         public String get(String tableName, String subTableName, String code) {\r
249             return ICUResourceTableAccess.getTableString(bundle, tableName, subTableName,\r
250                     code);\r
251         }\r
252     }\r
253 \r
254     static abstract class DataTables {\r
255         public abstract DataTable get(ULocale locale);\r
256         public static DataTables load(String className) {\r
257             try {\r
258                 return (DataTables) Class.forName(className).newInstance();\r
259             } catch (Throwable t) {\r
260                 final DataTable NO_OP = new DataTable();\r
261                 return new DataTables() {\r
262                     public DataTable get(ULocale locale) {\r
263                         return NO_OP;\r
264                     }\r
265                 };\r
266             }\r
267         }\r
268     }\r
269 \r
270     static abstract class ICUDataTables extends DataTables {\r
271         private final String path;\r
272 \r
273         protected ICUDataTables(String path) {\r
274             this.path = path;\r
275         }\r
276 \r
277         @Override\r
278         public DataTable get(ULocale locale) {\r
279             return new ICUDataTable(path, locale);\r
280         }\r
281     }\r
282 \r
283     static class LangDataTables {\r
284         static final DataTables impl = DataTables.load("com.ibm.icu.impl.ICULangDataTables");\r
285     }\r
286 \r
287     static class RegionDataTables {\r
288         static final DataTables impl = DataTables.load("com.ibm.icu.impl.ICURegionDataTables");\r
289     }\r
290 \r
291     public static enum DataTableType {\r
292         LANG, REGION;\r
293     }\r
294 \r
295     public static boolean haveData(DataTableType type) {\r
296         switch (type) {\r
297         case LANG: return LangDataTables.impl instanceof ICUDataTables;\r
298         case REGION: return RegionDataTables.impl instanceof ICUDataTables;\r
299         default:\r
300             throw new IllegalArgumentException("unknown type: " + type);\r
301         }\r
302     }\r
303 \r
304     static class Appender {\r
305         private final String sep;\r
306 \r
307         Appender(String sep) {\r
308             this.sep = sep;\r
309         }\r
310         StringBuilder append(String s, StringBuilder b) {\r
311             if (b.length() > 0) {\r
312                 b.append(sep);\r
313             }\r
314             b.append(s);\r
315             return b;\r
316         }\r
317     }\r
318 \r
319     private static class Cache {\r
320         private ULocale locale;\r
321         private DialectHandling dialectHandling;\r
322         private LocaleDisplayNames cache;\r
323         public LocaleDisplayNames get(ULocale locale, DialectHandling dialectHandling) {\r
324             if (!(dialectHandling == this.dialectHandling && locale.equals(this.locale))) {\r
325                 this.locale = locale;\r
326                 this.dialectHandling = dialectHandling;\r
327                 this.cache = new LocaleDisplayNamesImpl(locale, dialectHandling);\r
328             }\r
329             return cache;\r
330         }\r
331     }\r
332 }\r