ICU-7954 Add a new API checking availability of currency in the specified date range.

X-SVN-Rev: 28939
This commit is contained in:
Yoshito Umaoka 2010-10-28 18:28:09 +00:00
parent c104085f55
commit 27d3ca72c3
2 changed files with 111 additions and 15 deletions

View File

@ -7,8 +7,10 @@
package com.ibm.icu.util;
import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@ -206,25 +208,27 @@ public class Currency extends MeasureUnit implements Serializable {
if (theISOCode == null) {
throw new NullPointerException("The input currency code is null.");
}
boolean is3alpha = true;
if (theISOCode.length() != 3) {
is3alpha = false;
} else {
for (int i = 0; i < 3; i++) {
char ch = theISOCode.charAt(i);
if (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z') {
is3alpha = false;
break;
}
}
}
if (!is3alpha) {
if (!isAlpha3Code(theISOCode)) {
throw new IllegalArgumentException(
"The input currency code is not 3-letter alphabetic code.");
}
return new Currency(theISOCode.toUpperCase(Locale.US));
}
private static boolean isAlpha3Code(String code) {
if (code.length() != 3) {
return false;
} else {
for (int i = 0; i < 3; i++) {
char ch = code.charAt(i);
if (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z') {
return false;
}
}
}
return true;
}
/**
* Registers a new currency for the provided locale. The returned object
* is a key that can be used to unregister this currency object.
@ -324,8 +328,7 @@ public class Currency extends MeasureUnit implements Serializable {
CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
if (!commonlyUsed) {
// Behavior change from 4.3.3, no longer sort the currencies
List<String> result = info.currencies(null);
return result.toArray(new String[result.size()]);
return getAvailableCurrencyCodes().toArray(new String[0]);
}
// Don't resolve region if the requested locale is 'und', it will resolve to US
@ -740,6 +743,66 @@ public class Currency extends MeasureUnit implements Serializable {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
};
private static SoftReference<List<String>> ALL_CODES;
/*
* Returns an unmodifiable String list including all known currency codes
*/
private static synchronized List<String> getAvailableCurrencyCodes() {
List<String> all = (ALL_CODES == null) ? null : ALL_CODES.get();
if (all == null) {
CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
all = Collections.unmodifiableList(info.currencies(null));
ALL_CODES = new SoftReference<List<String>>(all);
}
return all;
}
/**
* Queries if the given ISO 4217 3-letter code is available on the specified date range.
* <p>
* Note: For checking availability of a currency on a specific date, specify the date on both <code>from</code> and
* <code>to</code>. When both <code>from</code> and <code>to</code> are null, this method checks if the specified
* currency is available all time.
*
* @param code
* The ISO 4217 3-letter code.
* @param from
* The lower bound of the date range, inclusive. When <code>from</code> is null, check the availability
* of the currency any date before <code>to</code>
* @param to
* The upper bound of the date range, inclusive. When <code>to</code> is null, check the availability of
* the currency any date after <code>from</code>
* @return true if the given ISO 4217 3-letter code is supported on the specified date range.
* @throws IllegalArgumentException when <code>to</code> is before <code>from</code>.
*
* @draft ICU 4.6
* @provisional This API might change or be removed in a future release.
*/
public static boolean isAvailable(String code, Date from, Date to) {
if (!isAlpha3Code(code)) {
return false;
}
if (from != null && to != null && from.after(to)) {
throw new IllegalArgumentException("To is before from");
}
code = code.toUpperCase(Locale.ENGLISH);
boolean isKnown = getAvailableCurrencyCodes().contains(code);
if (isKnown == false) {
return false;
} else if (from == null && to == null) {
return true;
}
// When asActiveOnly is true, check if the currency is currently
// active or not.
CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
List<String> allActive = info.currencies(CurrencyFilter.onRange(from, to));
return allActive.contains(code);
}
// -------- BEGIN ULocale boilerplate --------
/**

View File

@ -327,4 +327,37 @@ public class CurrencyTest extends TestFmwk {
assertEquals(loc.toString(), ALLSET, returnedSet);
}
}
public void TestIsAvailable() {
Date d1995 = new Date(788918400000L); // 1995-01-01 00:00 GMT
Date d2000 = new Date(946684800000L); // 2000-01-01 00:00 GMT
Date d2005 = new Date(1104537600000L); // 2005-01-01 00:00 GMT
assertTrue("USD all time", Currency.isAvailable("USD", null, null));
assertTrue("USD before 1995", Currency.isAvailable("USD", null, d1995));
assertTrue("USD 1995-2005", Currency.isAvailable("USD", d1995, d2005));
assertTrue("USD after 2005", Currency.isAvailable("USD", d2005, null));
assertTrue("USD on 2005-01-01", Currency.isAvailable("USD", d2005, d2005));
assertTrue("usd all time", Currency.isAvailable("usd", null, null));
assertTrue("DEM all time", Currency.isAvailable("DEM", null, null));
assertTrue("DEM before 1995", Currency.isAvailable("DEM", null, d1995));
assertTrue("DEM 1995-2000", Currency.isAvailable("DEM", d1995, d2000));
assertTrue("DEM 1995-2005", Currency.isAvailable("DEM", d1995, d2005));
assertFalse("DEM after 2005", Currency.isAvailable("DEM", d2005, null));
assertTrue("DEM on 2000-01-01", Currency.isAvailable("DEM", d2000, d2000));
assertFalse("DEM on 2005-01-01", Currency.isAvailable("DEM", d2005, d2005));
assertFalse("XXX unknown code", Currency.isAvailable("XXX", null, null));
assertFalse("USDOLLAR invalid code", Currency.isAvailable("USDOLLAR", null, null));
// illegal argument combination
try {
Currency.isAvailable("USD", d2005, d1995);
errln("Expected IllegalArgumentException, because lower range is after upper range");
} catch (IllegalArgumentException e) {
logln("IllegalArgumentException, because lower range is after upper range");
}
}
}