2 *******************************************************************************
\r
3 * Copyright (C) 2009-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.impl;
\r
9 import java.lang.ref.SoftReference;
\r
10 import java.util.Collections;
\r
11 import java.util.HashMap;
\r
12 import java.util.HashSet;
\r
13 import java.util.Map;
\r
14 import java.util.Set;
\r
15 import java.util.TreeMap;
\r
17 import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo;
\r
18 import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfoProvider;
\r
19 import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo;
\r
20 import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo;
\r
21 import com.ibm.icu.util.ULocale;
\r
22 import com.ibm.icu.util.UResourceBundle;
\r
24 public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvider {
\r
25 public ICUCurrencyDisplayInfoProvider() {
\r
28 public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) {
\r
29 ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
\r
30 ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
\r
31 if (!withFallback) {
\r
32 int status = rb.getLoadingStatus();
\r
33 if (status == ICUResourceBundle.FROM_DEFAULT || status == ICUResourceBundle.FROM_ROOT) {
\r
34 return CurrencyData.DefaultInfo.getWithFallback(false);
\r
37 return new ICUCurrencyDisplayInfo(rb, withFallback);
\r
40 public boolean hasData() {
\r
44 static class ICUCurrencyDisplayInfo extends CurrencyDisplayInfo {
\r
45 private final boolean fallback;
\r
46 private final ICUResourceBundle rb;
\r
47 private final ICUResourceBundle currencies;
\r
48 private final ICUResourceBundle plurals;
\r
49 private SoftReference<Map<String, String>> _symbolMapRef;
\r
50 private SoftReference<Map<String, String>> _nameMapRef;
\r
52 public ICUCurrencyDisplayInfo(ICUResourceBundle rb, boolean fallback) {
\r
53 this.fallback = fallback;
\r
55 this.currencies = rb.findTopLevel("Currencies");
\r
56 this.plurals = rb.findTopLevel("CurrencyPlurals");
\r
60 public ULocale getLocale() {
\r
61 return rb.getULocale();
\r
65 public String getName(String isoCode) {
\r
66 return getName(isoCode, false);
\r
70 public String getSymbol(String isoCode) {
\r
71 return getName(isoCode, true);
\r
74 private String getName(String isoCode, boolean symbolName) {
\r
75 if (currencies != null) {
\r
76 ICUResourceBundle result = currencies.findWithFallback(isoCode);
\r
77 if (result != null) {
\r
79 int status = result.getLoadingStatus();
\r
80 if (status == ICUResourceBundle.FROM_DEFAULT ||
\r
81 status == ICUResourceBundle.FROM_ROOT) {
\r
85 return result.getString(symbolName ? 0 : 1);
\r
89 return fallback ? isoCode : null;
\r
93 public String getPluralName(String isoCode, String pluralKey ) {
\r
94 // See http://unicode.org/reports/tr35/#Currencies, especially the fallback rule.
\r
95 if (plurals != null) {
\r
96 ICUResourceBundle pluralsBundle = plurals.findWithFallback(isoCode);
\r
97 if (pluralsBundle != null) {
\r
98 ICUResourceBundle pluralBundle = pluralsBundle.findWithFallback(pluralKey);
\r
99 if (pluralBundle == null) {
\r
103 pluralBundle = pluralsBundle.findWithFallback("other");
\r
104 if (pluralBundle == null) {
\r
105 return getName(isoCode);
\r
108 return pluralBundle.getString();
\r
112 return fallback ? getName(isoCode) : null;
\r
116 public Map<String, String> symbolMap() {
\r
117 Map<String, String> map = _symbolMapRef == null ? null : _symbolMapRef.get();
\r
119 map = _createSymbolMap();
\r
120 // atomic and idempotent
\r
121 _symbolMapRef = new SoftReference<Map<String, String>>(map);
\r
127 public Map<String, String> nameMap() {
\r
128 Map<String, String> map = _nameMapRef == null ? null : _nameMapRef.get();
\r
130 map = _createNameMap();
\r
131 // atomic and idempotent
\r
132 _nameMapRef = new SoftReference<Map<String, String>>(map);
\r
138 public Map<String, String> getUnitPatterns() {
\r
139 Map<String, String> result = new HashMap<String, String>();
\r
141 ULocale locale = rb.getULocale();
\r
142 for (;locale != null; locale = locale.getFallback()) {
\r
143 ICUResourceBundle r = (ICUResourceBundle) UResourceBundle.getBundleInstance(
\r
144 ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
\r
148 ICUResourceBundle cr = r.findWithFallback("CurrencyUnitPatterns");
\r
152 for (int index = 0, size = cr.getSize(); index < size; ++index) {
\r
153 ICUResourceBundle b = (ICUResourceBundle) cr.get(index);
\r
154 String key = b.getKey();
\r
155 if (result.containsKey(key)) {
\r
158 result.put(key, b.getString());
\r
162 // Default result is the empty map. Callers who require a pattern will have to
\r
163 // supply a default.
\r
164 return Collections.unmodifiableMap(result);
\r
168 public CurrencyFormatInfo getFormatInfo(String isoCode) {
\r
169 ICUResourceBundle crb = currencies.findWithFallback(isoCode);
\r
170 if (crb != null && crb.getSize() > 2) {
\r
173 String pattern = crb.getString(0);
\r
174 char separator = crb.getString(1).charAt(0);
\r
175 char groupingSeparator = crb.getString(2).charAt(0);
\r
176 return new CurrencyFormatInfo(pattern, separator, groupingSeparator);
\r
183 public CurrencySpacingInfo getSpacingInfo() {
\r
184 ICUResourceBundle srb = rb.findWithFallback("currencySpacing");
\r
186 ICUResourceBundle brb = srb.findWithFallback("beforeCurrency");
\r
187 ICUResourceBundle arb = srb.findWithFallback("afterCurrency");
\r
188 if (brb != null && brb != null) {
\r
189 String beforeCurrencyMatch = brb.findWithFallback("currencyMatch").getString();
\r
190 String beforeContextMatch = brb.findWithFallback("surroundingMatch").getString();
\r
191 String beforeInsert = brb.findWithFallback("insertBetween").getString();
\r
192 String afterCurrencyMatch = arb.findWithFallback("currencyMatch").getString();
\r
193 String afterContextMatch = arb.findWithFallback("surroundingMatch").getString();
\r
194 String afterInsert = arb.findWithFallback("insertBetween").getString();
\r
196 return new CurrencySpacingInfo(
\r
197 beforeCurrencyMatch, beforeContextMatch, beforeInsert,
\r
198 afterCurrencyMatch, afterContextMatch, afterInsert);
\r
201 return fallback ? CurrencySpacingInfo.DEFAULT : null;
\r
204 private Map<String, String> _createSymbolMap() {
\r
205 Map<String, String> result = new HashMap<String, String>();
\r
207 for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) {
\r
208 ICUResourceBundle bundle = (ICUResourceBundle)
\r
209 UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
\r
210 ICUResourceBundle curr = bundle.findTopLevel("Currencies");
\r
211 if (curr == null) {
\r
214 for (int i = 0; i < curr.getSize(); ++i) {
\r
215 ICUResourceBundle item = curr.at(i);
\r
216 String isoCode = item.getKey();
\r
217 if (!result.containsKey(isoCode)) {
\r
218 // put the code itself
\r
219 result.put(isoCode, isoCode);
\r
220 // 0 == symbol element
\r
221 String symbol = item.getString(0);
\r
222 result.put(symbol, isoCode);
\r
227 return Collections.unmodifiableMap(result);
\r
230 private Map<String, String> _createNameMap() {
\r
231 // ignore case variants
\r
232 Map<String, String> result = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
\r
234 Set<String> visited = new HashSet<String>();
\r
235 Map<String, Set<String>> visitedPlurals = new HashMap<String, Set<String>>();
\r
236 for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) {
\r
237 ICUResourceBundle bundle = (ICUResourceBundle)
\r
238 UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
\r
239 ICUResourceBundle curr = bundle.findTopLevel("Currencies");
\r
240 if (curr != null) {
\r
241 for (int i = 0; i < curr.getSize(); ++i) {
\r
242 ICUResourceBundle item = curr.at(i);
\r
243 String isoCode = item.getKey();
\r
244 if (!visited.contains(isoCode)) {
\r
245 visited.add(isoCode);
\r
246 // 1 == name element
\r
247 String name = item.getString(1);
\r
248 result.put(name, isoCode);
\r
253 ICUResourceBundle plurals = bundle.findTopLevel("CurrencyPlurals");
\r
254 if (plurals != null) {
\r
255 for (int i = 0; i < plurals.getSize(); ++i) {
\r
256 ICUResourceBundle item = plurals.at(i);
\r
257 String isoCode = item.getKey();
\r
258 Set<String> pluralSet = visitedPlurals.get(isoCode);
\r
259 if (pluralSet == null) {
\r
260 pluralSet = new HashSet<String>();
\r
261 visitedPlurals.put(isoCode, pluralSet);
\r
263 for (int j = 0; j < item.getSize(); ++j) {
\r
264 ICUResourceBundle plural = item.at(j);
\r
265 String pluralType = plural.getKey();
\r
266 if (!pluralSet.contains(pluralType)) {
\r
267 String pluralName = plural.getString();
\r
268 result.put(pluralName, isoCode);
\r
269 pluralSet.add(pluralType);
\r
276 return Collections.unmodifiableMap(result);
\r