2 *******************************************************************************
\r
3 * Copyright (C) 2001-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.util;
\r
9 import java.io.Serializable;
\r
10 import java.text.ParsePosition;
\r
11 import java.util.ArrayList;
\r
12 import java.util.Date;
\r
13 import java.util.Iterator;
\r
14 import java.util.List;
\r
15 import java.util.Locale;
\r
16 import java.util.Map;
\r
17 import java.util.Vector;
\r
19 import com.ibm.icu.impl.ICUCache;
\r
20 import com.ibm.icu.impl.ICUDebug;
\r
21 import com.ibm.icu.impl.ICUResourceBundle;
\r
22 import com.ibm.icu.impl.SimpleCache;
\r
23 import com.ibm.icu.impl.TextTrieMap;
\r
24 import com.ibm.icu.text.CurrencyDisplayNames;
\r
25 import com.ibm.icu.text.CurrencyMetaInfo;
\r
26 import com.ibm.icu.text.CurrencyMetaInfo.CurrencyDigits;
\r
27 import com.ibm.icu.text.CurrencyMetaInfo.CurrencyFilter;
\r
30 * A class encapsulating a currency, as defined by ISO 4217. A
\r
31 * <tt>Currency</tt> object can be created given a <tt>Locale</tt> or
\r
32 * given an ISO 4217 code. Once created, the <tt>Currency</tt> object
\r
33 * can return various data necessary to its proper display:
\r
35 * <ul><li>A display symbol, for a specific locale
\r
36 * <li>The number of fraction digits to display
\r
37 * <li>A rounding increment
\r
40 * The <tt>DecimalFormat</tt> class uses these data to display
\r
43 * <p>Note: This class deliberately resembles
\r
44 * <tt>java.util.Currency</tt> but it has a completely independent
\r
45 * implementation, and adds features not present in the JDK.
\r
49 public class Currency extends MeasureUnit implements Serializable {
\r
50 // using serialver from jdk1.4.2_05
\r
51 private static final long serialVersionUID = -5839973855554750484L;
\r
52 private static final boolean DEBUG = ICUDebug.enabled("currency");
\r
54 // Cache to save currency name trie
\r
55 private static ICUCache<ULocale, Vector<TextTrieMap<CurrencyStringInfo>>> CURRENCY_NAME_CACHE =
\r
56 new SimpleCache<ULocale, Vector<TextTrieMap<CurrencyStringInfo>>>();
\r
59 * ISO 4217 3-letter code.
\r
61 private String isoCode;
\r
64 * Selector for getName() indicating a symbolic name for a
\r
65 * currency, such as "$" for USD.
\r
68 public static final int SYMBOL_NAME = 0;
\r
71 * Selector for ucurr_getName indicating the long name for a
\r
72 * currency, such as "US Dollar" for USD.
\r
75 public static final int LONG_NAME = 1;
\r
78 * Selector for getName() indicating the plural long name for a
\r
79 * currency, such as "US dollar" for USD in "1 US dollar",
\r
80 * and "US dollars" for USD in "2 US dollars".
\r
83 public static final int PLURAL_LONG_NAME = 2;
\r
85 // begin registry stuff
\r
87 // shim for service code
\r
88 /* package */ static abstract class ServiceShim {
\r
89 abstract ULocale[] getAvailableULocales();
\r
90 abstract Locale[] getAvailableLocales();
\r
91 abstract Currency createInstance(ULocale l);
\r
92 abstract Object registerInstance(Currency c, ULocale l);
\r
93 abstract boolean unregister(Object f);
\r
96 private static ServiceShim shim;
\r
97 private static ServiceShim getShim() {
\r
98 // Note: this instantiation is safe on loose-memory-model configurations
\r
99 // despite lack of synchronization, since the shim instance has no state--
\r
100 // it's all in the class init. The worst problem is we might instantiate
\r
101 // two shim instances, but they'll share the same state so that's ok.
\r
102 if (shim == null) {
\r
104 Class<?> cls = Class.forName("com.ibm.icu.util.CurrencyServiceShim");
\r
105 shim = (ServiceShim)cls.newInstance();
\r
107 catch (Exception e) {
\r
109 e.printStackTrace();
\r
111 throw new RuntimeException(e.getMessage());
\r
118 * Returns a currency object for the default currency in the given
\r
120 * @param locale the locale
\r
121 * @return the currency object for this locale
\r
124 public static Currency getInstance(Locale locale) {
\r
125 return getInstance(ULocale.forLocale(locale));
\r
129 * Returns a currency object for the default currency in the given
\r
133 public static Currency getInstance(ULocale locale) {
\r
134 String currency = locale.getKeywordValue("currency");
\r
135 if (currency != null) {
\r
136 return getInstance(currency);
\r
139 if (shim == null) {
\r
140 return createCurrency(locale);
\r
143 return shim.createInstance(locale);
\r
147 * Returns an array of Strings which contain the currency
\r
148 * identifiers that are valid for the given locale on the
\r
149 * given date. If there are no such identifiers, returns null.
\r
150 * Returned identifiers are in preference order.
\r
151 * @param loc the locale for which to retrieve currency codes.
\r
152 * @param d the date for which to retrieve currency codes for the given locale.
\r
153 * @return The array of ISO currency codes.
\r
156 public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) {
\r
157 CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
\r
158 CurrencyFilter filter = CurrencyFilter.onDate(d).withRegion(loc.getCountry());
\r
159 List<String> list = info.currencies(filter);
\r
160 // Note: Prior to 4.4 the spec didn't say that we return null if there are no results, but
\r
161 // the test assumed it did. Kept the behavior and amended the spec.
\r
162 if (list.isEmpty()) {
\r
165 return list.toArray(new String[list.size()]);
\r
168 private static final String EUR_STR = "EUR";
\r
171 * Instantiate a currency from resource data.
\r
173 /* package */ static Currency createCurrency(ULocale loc) {
\r
174 String variant = loc.getVariant();
\r
175 if ("EURO".equals(variant)) {
\r
176 return new Currency(EUR_STR);
\r
179 String country = loc.getCountry();
\r
181 CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
\r
182 List<String> list = info.currencies(CurrencyFilter.onRegion(country));
\r
183 if (list.size() > 0) {
\r
184 String code = list.get(0);
\r
185 boolean isPreEuro = "PREEURO".equals(variant);
\r
186 if (isPreEuro && EUR_STR.equals(code)) {
\r
187 if (list.size() < 2) {
\r
190 code = list.get(1);
\r
192 return new Currency(code);
\r
198 * Returns a currency object given an ISO 4217 3-letter code.
\r
199 * @param theISOCode the iso code
\r
200 * @return the currency for this iso code
\r
201 * @throws NullPointerException if <code>theISOCode</code> is null.
\r
202 * @throws IllegalArgumentException if <code>theISOCode</code> is not a
\r
203 * 3-letter alpha code.
\r
206 public static Currency getInstance(String theISOCode) {
\r
207 if (theISOCode == null) {
\r
208 throw new NullPointerException("The input currency code is null.");
\r
210 boolean is3alpha = true;
\r
211 if (theISOCode.length() != 3) {
\r
214 for (int i = 0; i < 3; i++) {
\r
215 char ch = theISOCode.charAt(i);
\r
216 if (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z') {
\r
223 throw new IllegalArgumentException(
\r
224 "The input currency code is not 3-letter alphabetic code.");
\r
226 return new Currency(theISOCode.toUpperCase(Locale.US));
\r
230 * Registers a new currency for the provided locale. The returned object
\r
231 * is a key that can be used to unregister this currency object.
\r
232 * @param currency the currency to register
\r
233 * @param locale the ulocale under which to register the currency
\r
234 * @return a registry key that can be used to unregister this currency
\r
238 public static Object registerInstance(Currency currency, ULocale locale) {
\r
239 return getShim().registerInstance(currency, locale);
\r
243 * Unregister the currency associated with this key (obtained from
\r
244 * registerInstance).
\r
245 * @param registryKey the registry key returned from registerInstance
\r
246 * @see #registerInstance
\r
249 public static boolean unregister(Object registryKey) {
\r
250 if (registryKey == null) {
\r
251 throw new IllegalArgumentException("registryKey must not be null");
\r
253 if (shim == null) {
\r
256 return shim.unregister(registryKey);
\r
260 * Return an array of the locales for which a currency
\r
262 * @return an array of the available locales
\r
265 public static Locale[] getAvailableLocales() {
\r
266 if (shim == null) {
\r
267 return ICUResourceBundle.getAvailableLocales();
\r
269 return shim.getAvailableLocales();
\r
274 * Return an array of the ulocales for which a currency
\r
276 * @return an array of the available ulocales
\r
279 public static ULocale[] getAvailableULocales() {
\r
280 if (shim == null) {
\r
281 return ICUResourceBundle.getAvailableULocales();
\r
283 return shim.getAvailableULocales();
\r
287 // end registry stuff
\r
290 * Given a key and a locale, returns an array of values for the key for which data
\r
291 * exists. If commonlyUsed is true, these are the values that typically are used
\r
292 * with this locale, otherwise these are all values for which data exists.
\r
293 * This is a common service API.
\r
295 * The only supported key is "currency", other values return an empty array.
\r
297 * Currency information is based on the region of the locale. If the locale does not
\r
298 * indicate a region, {@link ULocale#addLikelySubtags(ULocale)} is used to infer a region,
\r
299 * except for the 'und' locale.
\r
301 * If commonlyUsed is true, only the currencies known to be in use as of the current date
\r
302 * are returned. When there are more than one, these are returned in preference order
\r
303 * (typically, this occurs when a country is transitioning to a new currency, and the
\r
304 * newer currency is preferred), see
\r
305 * <a href="http://unicode.org/reports/tr35/#Supplemental_Currency_Data">Unicode TR#35 Sec. C1</a>.
\r
306 * If commonlyUsed is false, all currencies ever used in any locale are returned, in no
\r
307 * particular order.
\r
309 * @param key key whose values to look up. the only recognized key is "currency"
\r
310 * @param locale the locale
\r
311 * @param commonlyUsed if true, return only values that are currently used in the locale.
\r
312 * Otherwise returns all values.
\r
313 * @return an array of values for the given key and the locale. If there is no data, the
\r
314 * array will be empty.
\r
317 public static final String[] getKeywordValuesForLocale(String key, ULocale locale,
\r
318 boolean commonlyUsed) {
\r
320 // The only keyword we recognize is 'currency'
\r
321 if (!"currency".equals(key)) {
\r
322 return EMPTY_STRING_ARRAY;
\r
325 CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
\r
326 if (!commonlyUsed) {
\r
327 // Behavior change from 4.3.3, no longer sort the currencies
\r
328 List<String> result = info.currencies(null);
\r
329 return result.toArray(new String[result.size()]);
\r
332 // Don't resolve region if the requested locale is 'und', it will resolve to US
\r
333 // which we don't want.
\r
334 String prefRegion = locale.getCountry();
\r
335 if (prefRegion.length() == 0) {
\r
336 if (UND.equals(locale)) {
\r
337 return EMPTY_STRING_ARRAY;
\r
339 ULocale loc = ULocale.addLikelySubtags(locale);
\r
340 prefRegion = loc.getCountry();
\r
343 CurrencyFilter filter = CurrencyFilter.now().withRegion(prefRegion);
\r
345 // currencies are in region's preferred order when we're filtering on region, which
\r
346 // matches our spec
\r
347 List<String> result = info.currencies(filter);
\r
349 // No fallback anymore (change from 4.3.3)
\r
350 if (result.size() == 0) {
\r
351 return EMPTY_STRING_ARRAY;
\r
354 return result.toArray(new String[result.size()]);
\r
357 private static final ULocale UND = new ULocale("und");
\r
358 private static final String[] EMPTY_STRING_ARRAY = new String[0];
\r
361 * Return a hashcode for this currency.
\r
364 public int hashCode() {
\r
365 return isoCode.hashCode();
\r
369 * Return true if rhs is a Currency instance,
\r
370 * is non-null, and has the same currency code.
\r
373 public boolean equals(Object rhs) {
\r
374 if (rhs == null) return false;
\r
375 if (rhs == this) return true;
\r
377 Currency c = (Currency) rhs;
\r
378 return isoCode.equals(c.isoCode);
\r
380 catch (ClassCastException e) {
\r
386 * Returns the ISO 4217 3-letter code for this currency object.
\r
389 public String getCurrencyCode() {
\r
394 * Convenience and compatibility override of getName that
\r
395 * requests the symbol name.
\r
399 public String getSymbol() {
\r
400 return getSymbol(ULocale.getDefault());
\r
404 * Convenience and compatibility override of getName that
\r
405 * requests the symbol name.
\r
406 * @param loc the Locale for the symbol
\r
410 public String getSymbol(Locale loc) {
\r
411 return getSymbol(ULocale.forLocale(loc));
\r
415 * Convenience and compatibility override of getName that
\r
416 * requests the symbol name.
\r
417 * @param uloc the ULocale for the symbol
\r
421 public String getSymbol(ULocale uloc) {
\r
422 return getName(uloc, SYMBOL_NAME, new boolean[1]);
\r
426 * Returns the display name for the given currency in the
\r
428 * This is a convenient method for
\r
429 * getName(ULocale, int, boolean[]);
\r
432 public String getName(Locale locale,
\r
434 boolean[] isChoiceFormat) {
\r
435 return getName(ULocale.forLocale(locale), nameStyle, isChoiceFormat);
\r
439 * Returns the display name for the given currency in the
\r
440 * given locale. For example, the display name for the USD
\r
441 * currency object in the en_US locale is "$".
\r
442 * @param locale locale in which to display currency
\r
443 * @param nameStyle selector for which kind of name to return.
\r
444 * The nameStyle should be either SYMBOL_NAME or
\r
445 * LONG_NAME. Otherwise, throw IllegalArgumentException.
\r
446 * @param isChoiceFormat fill-in; isChoiceFormat[0] is set to true
\r
447 * if the returned value is a ChoiceFormat pattern; otherwise it
\r
449 * @return display string for this currency. If the resource data
\r
450 * contains no entry for this currency, then the ISO 4217 code is
\r
451 * returned. If isChoiceFormat[0] is true, then the result is a
\r
452 * ChoiceFormat pattern. Otherwise it is a static string. <b>Note:</b>
\r
453 * as of ICU 4.4, choice formats are not used, and the value returned
\r
454 * in isChoiceFormat is always false.
\r
456 * @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME
\r
458 * @see #getName(ULocale, int, String, boolean[])
\r
461 public String getName(ULocale locale, int nameStyle, boolean[] isChoiceFormat) {
\r
462 if (!(nameStyle == SYMBOL_NAME || nameStyle == LONG_NAME)) {
\r
463 throw new IllegalArgumentException("bad name style: " + nameStyle);
\r
466 // We no longer support choice format data in names. Data should not contain
\r
467 // choice patterns.
\r
468 if (isChoiceFormat != null) {
\r
469 isChoiceFormat[0] = false;
\r
472 CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale);
\r
473 return nameStyle == SYMBOL_NAME ? names.getSymbol(isoCode) : names.getName(isoCode);
\r
477 * Returns the display name for the given currency in the given locale.
\r
478 * This is a convenience overload of getName(ULocale, int, String, boolean[]);
\r
481 public String getName(Locale locale, int nameStyle, String pluralCount,
\r
482 boolean[] isChoiceFormat) {
\r
483 return getName(ULocale.forLocale(locale), nameStyle, pluralCount, isChoiceFormat);
\r
487 * Returns the display name for the given currency in the
\r
488 * given locale. For example, the SYMBOL_NAME for the USD
\r
489 * currency object in the en_US locale is "$".
\r
490 * The PLURAL_LONG_NAME for the USD currency object when the currency
\r
491 * amount is plural is "US dollars", such as in "3.00 US dollars";
\r
492 * while the PLURAL_LONG_NAME for the USD currency object when the currency
\r
493 * amount is singular is "US dollar", such as in "1.00 US dollar".
\r
494 * @param locale locale in which to display currency
\r
495 * @param nameStyle selector for which kind of name to return
\r
496 * @param pluralCount plural count string for this locale
\r
497 * @param isChoiceFormat fill-in; isChoiceFormat[0] is set to true
\r
498 * if the returned value is a ChoiceFormat pattern; otherwise it
\r
500 * @return display string for this currency. If the resource data
\r
501 * contains no entry for this currency, then the ISO 4217 code is
\r
502 * returned. If isChoiceFormat[0] is true, then the result is a
\r
503 * ChoiceFormat pattern. Otherwise it is a static string. <b>Note:</b>
\r
504 * as of ICU 4.4, choice formats are not used, and the value returned
\r
505 * in isChoiceFormat is always false.
\r
506 * @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME,
\r
507 * LONG_NAME, or PLURAL_LONG_NAME.
\r
510 public String getName(ULocale locale, int nameStyle, String pluralCount,
\r
511 boolean[] isChoiceFormat) {
\r
512 if (nameStyle != PLURAL_LONG_NAME) {
\r
513 return getName(locale, nameStyle, isChoiceFormat);
\r
516 // We no longer support choice format
\r
517 if (isChoiceFormat != null) {
\r
518 isChoiceFormat[0] = false;
\r
521 CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale);
\r
522 return names.getPluralName(isoCode, pluralCount);
\r
526 * Attempt to parse the given string as a currency, either as a
\r
527 * display name in the given locale, or as a 3-letter ISO 4217
\r
528 * code. If multiple display names match, then the longest one is
\r
529 * selected. If both a display name and a 3-letter ISO code
\r
530 * match, then the display name is preferred, unless it's length
\r
533 * @param locale the locale of the display names to match
\r
534 * @param text the text to parse
\r
535 * @param type parse against currency type: LONG_NAME only or not
\r
536 * @param pos input-output position; on input, the position within
\r
537 * text to match; must have 0 <= pos.getIndex() < text.length();
\r
538 * on output, the position after the last matched character. If
\r
539 * the parse fails, the position in unchanged upon output.
\r
540 * @return the ISO 4217 code, as a string, of the best match, or
\r
541 * null if there is no match
\r
544 * @deprecated This API is ICU internal only.
\r
546 public static String parse(ULocale locale, String text, int type, ParsePosition pos) {
\r
547 Vector<TextTrieMap<CurrencyStringInfo>> currencyTrieVec = CURRENCY_NAME_CACHE.get(locale);
\r
548 if (currencyTrieVec == null) {
\r
549 TextTrieMap<CurrencyStringInfo> currencyNameTrie =
\r
550 new TextTrieMap<CurrencyStringInfo>(true);
\r
551 TextTrieMap<CurrencyStringInfo> currencySymbolTrie =
\r
552 new TextTrieMap<CurrencyStringInfo>(false);
\r
553 currencyTrieVec = new Vector<TextTrieMap<CurrencyStringInfo>>();
\r
554 currencyTrieVec.addElement(currencySymbolTrie);
\r
555 currencyTrieVec.addElement(currencyNameTrie);
\r
556 setupCurrencyTrieVec(locale, currencyTrieVec);
\r
557 CURRENCY_NAME_CACHE.put(locale, currencyTrieVec);
\r
561 String isoResult = null;
\r
563 // look for the names
\r
564 TextTrieMap<CurrencyStringInfo> currencyNameTrie = currencyTrieVec.elementAt(1);
\r
565 CurrencyNameResultHandler handler = new CurrencyNameResultHandler();
\r
566 currencyNameTrie.find(text, pos.getIndex(), handler);
\r
567 List<CurrencyStringInfo> list = handler.getMatchedCurrencyNames();
\r
568 if (list != null && list.size() != 0) {
\r
569 for (CurrencyStringInfo info : list) {
\r
570 String isoCode = info.getISOCode();
\r
571 String currencyString = info.getCurrencyString();
\r
572 if (currencyString.length() > maxLength) {
\r
573 maxLength = currencyString.length();
\r
574 isoResult = isoCode;
\r
579 if (type != Currency.LONG_NAME) { // not long name only
\r
580 TextTrieMap<CurrencyStringInfo> currencySymbolTrie = currencyTrieVec.elementAt(0);
\r
581 handler = new CurrencyNameResultHandler();
\r
582 currencySymbolTrie.find(text, pos.getIndex(), handler);
\r
583 list = handler.getMatchedCurrencyNames();
\r
584 if (list != null && list.size() != 0) {
\r
585 for (CurrencyStringInfo info : list) {
\r
586 String isoCode = info.getISOCode();
\r
587 String currencyString = info.getCurrencyString();
\r
588 if (currencyString.length() > maxLength) {
\r
589 maxLength = currencyString.length();
\r
590 isoResult = isoCode;
\r
596 int start = pos.getIndex();
\r
597 pos.setIndex(start + maxLength);
\r
601 private static void setupCurrencyTrieVec(ULocale locale,
\r
602 Vector<TextTrieMap<CurrencyStringInfo>> trieVec) {
\r
604 TextTrieMap<CurrencyStringInfo> symTrie = trieVec.elementAt(0);
\r
605 TextTrieMap<CurrencyStringInfo> trie = trieVec.elementAt(1);
\r
607 CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale);
\r
608 for (Map.Entry<String, String> e : names.symbolMap().entrySet()) {
\r
609 String symbol = e.getKey();
\r
610 String isoCode = e.getValue();
\r
611 symTrie.put(symbol, new CurrencyStringInfo(isoCode, symbol));
\r
613 for (Map.Entry<String, String> e : names.nameMap().entrySet()) {
\r
614 String name = e.getKey();
\r
615 String isoCode = e.getValue();
\r
616 trie.put(name, new CurrencyStringInfo(isoCode, name));
\r
620 private static final class CurrencyStringInfo {
\r
621 private String isoCode;
\r
622 private String currencyString;
\r
624 public CurrencyStringInfo(String isoCode, String currencyString) {
\r
625 this.isoCode = isoCode;
\r
626 this.currencyString = currencyString;
\r
629 private String getISOCode() {
\r
633 private String getCurrencyString() {
\r
634 return currencyString;
\r
638 private static class CurrencyNameResultHandler
\r
639 implements TextTrieMap.ResultHandler<CurrencyStringInfo> {
\r
640 private ArrayList<CurrencyStringInfo> resultList;
\r
642 public boolean handlePrefixMatch(int matchLength, Iterator<CurrencyStringInfo> values) {
\r
643 if (resultList == null) {
\r
644 resultList = new ArrayList<CurrencyStringInfo>();
\r
646 while (values.hasNext()) {
\r
647 CurrencyStringInfo item = values.next();
\r
648 if (item == null) {
\r
652 for (; i < resultList.size(); i++) {
\r
653 CurrencyStringInfo tmp = resultList.get(i);
\r
654 if (item.getISOCode() == tmp.getISOCode()) {
\r
655 if (matchLength > tmp.getCurrencyString().length()) {
\r
656 resultList.set(i, item);
\r
661 if (i == resultList.size()) {
\r
662 // not found in the current list
\r
663 resultList.add(item);
\r
669 List<CurrencyStringInfo> getMatchedCurrencyNames() {
\r
670 if (resultList == null || resultList.size() == 0) {
\r
678 * Returns the number of the number of fraction digits that should
\r
679 * be displayed for this currency.
\r
680 * @return a non-negative number of fraction digits to be
\r
684 public int getDefaultFractionDigits() {
\r
685 CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
\r
686 CurrencyDigits digits = info.currencyDigits(isoCode);
\r
687 return digits.fractionDigits;
\r
691 * Returns the rounding increment for this currency, or 0.0 if no
\r
692 * rounding is done by this currency.
\r
693 * @return the non-negative rounding increment, or 0.0 if none
\r
696 public double getRoundingIncrement() {
\r
697 CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
\r
698 CurrencyDigits digits = info.currencyDigits(isoCode);
\r
700 int data1 = digits.roundingIncrement;
\r
702 // If there is no rounding return 0.0 to indicate no rounding.
\r
703 // This is the high-runner case, by far.
\r
708 int data0 = digits.fractionDigits;
\r
710 // If the meta data is invalid, return 0.0 to indicate no rounding.
\r
711 if (data0 < 0 || data0 >= POW10.length) {
\r
715 // Return data[1] / 10^(data[0]). The only actual rounding data,
\r
716 // as of this writing, is CHF { 2, 25 }.
\r
717 return (double) data1 / POW10[data0];
\r
721 * Returns the ISO 4217 code for this currency.
\r
724 public String toString() {
\r
729 * Constructs a currency object for the given ISO 4217 3-letter
\r
730 * code. This constructor assumes that the code is valid.
\r
732 * @param theISOCode The iso code used to construct the currency.
\r
735 protected Currency(String theISOCode) {
\r
736 isoCode = theISOCode;
\r
740 private static final int[] POW10 = {
\r
741 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
\r
744 // -------- BEGIN ULocale boilerplate --------
\r
747 * Return the locale that was used to create this object, or null.
\r
748 * This may may differ from the locale requested at the time of
\r
749 * this object's creation. For example, if an object is created
\r
750 * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
\r
751 * drawn from <tt>en</tt> (the <i>actual</i> locale), and
\r
752 * <tt>en_US</tt> may be the most specific locale that exists (the
\r
753 * <i>valid</i> locale).
\r
755 * <p>Note: This method will be obsoleted. The implementation is
\r
756 * no longer locale-specific and so there is no longer a valid or
\r
757 * actual locale associated with the Currency object. Until
\r
758 * it is removed, this method will return the root locale.
\r
759 * @param type type of information requested, either {@link
\r
760 * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
\r
761 * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
\r
762 * @return the information specified by <i>type</i>, or null if
\r
763 * this object was not constructed from locale data.
\r
764 * @see com.ibm.icu.util.ULocale
\r
765 * @see com.ibm.icu.util.ULocale#VALID_LOCALE
\r
766 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
\r
767 * @obsolete ICU 3.2 to be removed
\r
768 * @deprecated This API is obsolete.
\r
770 public final ULocale getLocale(ULocale.Type type) {
\r
771 ULocale result = (type == ULocale.ACTUAL_LOCALE) ? actualLocale : validLocale;
\r
772 if (result == null) {
\r
773 return ULocale.ROOT;
\r
779 * Set information about the locales that were used to create this
\r
780 * object. If the object was not constructed from locale data,
\r
781 * both arguments should be set to null. Otherwise, neither
\r
782 * should be null. The actual locale must be at the same level or
\r
783 * less specific than the valid locale. This method is intended
\r
784 * for use by factories or other entities that create objects of
\r
786 * @param valid the most specific locale containing any resource
\r
788 * @param actual the locale containing data used to construct this
\r
790 * @see com.ibm.icu.util.ULocale
\r
791 * @see com.ibm.icu.util.ULocale#VALID_LOCALE
\r
792 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
\r
794 final void setLocale(ULocale valid, ULocale actual) {
\r
795 // Change the following to an assertion later
\r
796 if ((valid == null) != (actual == null)) {
\r
798 throw new IllegalArgumentException();
\r
801 // Another check we could do is that the actual locale is at
\r
802 // the same level or less specific than the valid locale.
\r
803 this.validLocale = valid;
\r
804 this.actualLocale = actual;
\r
808 * The most specific locale containing any resource data, or null.
\r
810 private ULocale validLocale;
\r
813 * The locale containing data used to construct this object, or null.
\r
815 private ULocale actualLocale;
\r
817 // -------- END ULocale boilerplate --------
\r