From 27d3ca72c38b17c3d12ca7475264b96739a8d6a3 Mon Sep 17 00:00:00 2001 From: Yoshito Umaoka Date: Thu, 28 Oct 2010 18:28:09 +0000 Subject: [PATCH] ICU-7954 Add a new API checking availability of currency in the specified date range. X-SVN-Rev: 28939 --- .../core/src/com/ibm/icu/util/Currency.java | 93 ++++++++++++++++--- .../ibm/icu/dev/test/util/CurrencyTest.java | 33 +++++++ 2 files changed, 111 insertions(+), 15 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java b/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java index 8db1dff7fee..4109811a3fd 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java @@ -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 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> ALL_CODES; + /* + * Returns an unmodifiable String list including all known currency codes + */ + private static synchronized List getAvailableCurrencyCodes() { + List 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>(all); + } + return all; + } + + /** + * Queries if the given ISO 4217 3-letter code is available on the specified date range. + *

+ * Note: For checking availability of a currency on a specific date, specify the date on both from and + * to. When both from and to 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 from is null, check the availability + * of the currency any date before to + * @param to + * The upper bound of the date range, inclusive. When to is null, check the availability of + * the currency any date after from + * @return true if the given ISO 4217 3-letter code is supported on the specified date range. + * @throws IllegalArgumentException when to is before from. + * + * @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 allActive = info.currencies(CurrencyFilter.onRange(from, to)); + return allActive.contains(code); + } + // -------- BEGIN ULocale boilerplate -------- /** diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java index a62a660e16a..763f0b40876 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java @@ -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"); + } + } }