| /* |
| ******************************************************************************* |
| * Copyright (C) 2009-2015, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| package com.ibm.icu.text; |
| |
| import java.lang.reflect.Field; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.List; |
| |
| import com.ibm.icu.impl.Grego; |
| import com.ibm.icu.util.Currency.CurrencyUsage; |
| |
| /** |
| * Provides information about currencies that is not specific to a locale. |
| * |
| * A note about currency dates. The CLDR data provides data to the day, |
| * inclusive. The date information used by CurrencyInfo and CurrencyFilter |
| * is represented by milliseconds, which is overly precise. These times are |
| * in GMT, so queries involving dates should use GMT times, but more generally |
| * you should avoid relying on time of day in queries. |
| * |
| * This class is not intended for public subclassing. |
| * |
| * @stable ICU 4.4 |
| */ |
| public class CurrencyMetaInfo { |
| private static final CurrencyMetaInfo impl; |
| private static final boolean hasData; |
| |
| /** |
| * Returns the unique instance of the currency meta info. |
| * @return the meta info |
| * @stable ICU 4.4 |
| */ |
| public static CurrencyMetaInfo getInstance() { |
| return impl; |
| } |
| |
| /** |
| * Returns the unique instance of the currency meta info, or null if |
| * noSubstitute is true and there is no data to support this API. |
| * @param noSubstitute true if no substitute data should be used |
| * @return the meta info, or null |
| * @stable ICU 49 |
| */ |
| public static CurrencyMetaInfo getInstance(boolean noSubstitute) { |
| return hasData ? impl : null; |
| } |
| |
| /** |
| * Returns true if there is data for the currency meta info. |
| * @return true if there is actual data |
| * @internal |
| * @deprecated This API is ICU internal only. |
| */ |
| @Deprecated |
| public static boolean hasData() { |
| return hasData; |
| } |
| |
| /** |
| * Subclass constructor. |
| * @internal |
| * @deprecated This API is ICU internal only. |
| */ |
| @Deprecated |
| protected CurrencyMetaInfo() { |
| } |
| |
| /** |
| * A filter used to select which currency info is returned. |
| * @stable ICU 4.4 |
| */ |
| public static final class CurrencyFilter { |
| /** |
| * The region to filter on. If null, accepts any region. |
| * @stable ICU 4.4 |
| */ |
| public final String region; |
| |
| /** |
| * The currency to filter on. If null, accepts any currency. |
| * @stable ICU 4.4 |
| */ |
| public final String currency; |
| |
| /** |
| * The from date to filter on (as milliseconds). Accepts any currency on or after this date. |
| * @stable ICU 4.4 |
| */ |
| public final long from; |
| |
| /** |
| * The to date to filter on (as milliseconds). Accepts any currency on or before this date. |
| * @stable ICU 4.4 |
| */ |
| public final long to; |
| |
| /** |
| * true if we are filtering only for currencies used as legal tender. |
| * @internal |
| * @deprecated This API is ICU internal only. |
| */ |
| @Deprecated |
| public final boolean tenderOnly; |
| |
| private CurrencyFilter(String region, String currency, long from, long to, boolean tenderOnly) { |
| this.region = region; |
| this.currency = currency; |
| this.from = from; |
| this.to = to; |
| this.tenderOnly = tenderOnly; |
| |
| } |
| |
| private static final CurrencyFilter ALL = new CurrencyFilter( |
| null, null, Long.MIN_VALUE, Long.MAX_VALUE, false); |
| |
| /** |
| * Returns a filter that accepts all currency data. |
| * @return a filter |
| * @stable ICU 4.4 |
| */ |
| public static CurrencyFilter all() { |
| return ALL; |
| } |
| |
| /** |
| * Returns a filter that accepts all currencies in use as of the current date. |
| * @return a filter |
| * @see #withDate(Date) |
| * @stable ICU 4.4 |
| */ |
| public static CurrencyFilter now() { |
| return ALL.withDate(new Date()); |
| } |
| |
| /** |
| * Returns a filter that accepts all currencies ever used in the given region. |
| * @param region the region code |
| * @return a filter |
| * @see #withRegion(String) |
| * @stable ICU 4.4 |
| */ |
| public static CurrencyFilter onRegion(String region) { |
| return ALL.withRegion(region); |
| } |
| |
| /** |
| * Returns a filter that accepts the given currency. |
| * @param currency the currency code |
| * @return a filter |
| * @see #withCurrency(String) |
| * @stable ICU 4.4 |
| */ |
| public static CurrencyFilter onCurrency(String currency) { |
| return ALL.withCurrency(currency); |
| } |
| |
| /** |
| * Returns a filter that accepts all currencies in use on the given date. |
| * @param date the date |
| * @return a filter |
| * @see #withDate(Date) |
| * @stable ICU 4.4 |
| */ |
| public static CurrencyFilter onDate(Date date) { |
| return ALL.withDate(date); |
| } |
| |
| /** |
| * Returns a filter that accepts all currencies that were in use at some point between |
| * the given dates, or if dates are equal, currencies in use on that date. |
| * @param from date on or after a currency must have been in use |
| * @param to date on or before which a currency must have been in use, |
| * or if equal to from, the date on which a currency must have been in use |
| * @return a filter |
| * @see #withDateRange(Date, Date) |
| * @stable ICU 49 |
| */ |
| public static CurrencyFilter onDateRange(Date from, Date to) { |
| return ALL.withDateRange(from, to); |
| } |
| |
| /** |
| * Returns a filter that accepts all currencies in use on the given date. |
| * @param date the date as milliseconds after Jan 1, 1970 |
| * @stable ICU 51 |
| */ |
| public static CurrencyFilter onDate(long date) { |
| return ALL.withDate(date); |
| } |
| |
| /** |
| * Returns a filter that accepts all currencies that were in use at some |
| * point between the given dates, or if dates are equal, currencies in |
| * use on that date. |
| * @param from The date on or after a currency must have been in use. |
| * Measured in milliseconds since Jan 1, 1970 GMT. |
| * @param to The date on or before which a currency must have been in use. |
| * Measured in milliseconds since Jan 1, 1970 GMT. |
| * @stable ICU 51 |
| */ |
| public static CurrencyFilter onDateRange(long from, long to) { |
| return ALL.withDateRange(from, to); |
| } |
| |
| /** |
| * Returns a CurrencyFilter for finding currencies that were either once used, |
| * are used, or will be used as tender. |
| * @stable ICU 51 |
| */ |
| public static CurrencyFilter onTender() { |
| return ALL.withTender(); |
| } |
| |
| /** |
| * Returns a copy of this filter, with the specified region. Region can be null to |
| * indicate no filter on region. |
| * @param region the region code |
| * @return the filter |
| * @see #onRegion(String) |
| * @stable ICU 4.4 |
| */ |
| public CurrencyFilter withRegion(String region) { |
| return new CurrencyFilter(region, this.currency, this.from, this.to, this.tenderOnly); |
| } |
| |
| /** |
| * Returns a copy of this filter, with the specified currency. Currency can be null to |
| * indicate no filter on currency. |
| * @param currency the currency code |
| * @return the filter |
| * @see #onCurrency(String) |
| * @stable ICU 4.4 |
| */ |
| public CurrencyFilter withCurrency(String currency) { |
| return new CurrencyFilter(this.region, currency, this.from, this.to, this.tenderOnly); |
| } |
| |
| /** |
| * Returns a copy of this filter, with from and to set to the given date. |
| * @param date the date on which the currency must have been in use |
| * @return the filter |
| * @see #onDate(Date) |
| * @stable ICU 4.4 |
| */ |
| public CurrencyFilter withDate(Date date) { |
| return new CurrencyFilter(this.region, this.currency, date.getTime(), date.getTime(), this.tenderOnly); |
| } |
| |
| /** |
| * Returns a copy of this filter, with from and to set to the given dates. |
| * @param from date on or after which the currency must have been in use |
| * @param to date on or before which the currency must have been in use |
| * @return the filter |
| * @see #onDateRange(Date, Date) |
| * @stable ICU 49 |
| */ |
| public CurrencyFilter withDateRange(Date from, Date to) { |
| long fromLong = from == null ? Long.MIN_VALUE : from.getTime(); |
| long toLong = to == null ? Long.MAX_VALUE : to.getTime(); |
| return new CurrencyFilter(this.region, this.currency, fromLong, toLong, this.tenderOnly); |
| } |
| |
| /** |
| * Returns a copy of this filter that accepts all currencies in use on |
| * the given date. |
| * @param date the date as milliseconds after Jan 1, 1970 |
| * @stable ICU 51 |
| */ |
| public CurrencyFilter withDate(long date) { |
| return new CurrencyFilter(this.region, this.currency, date, date, this.tenderOnly); |
| } |
| |
| /** |
| * Returns a copy of this filter that accepts all currencies that were |
| * in use at some point between the given dates, or if dates are equal, |
| * currencies in use on that date. |
| * @param from The date on or after a currency must have been in use. |
| * Measured in milliseconds since Jan 1, 1970 GMT. |
| * @param to The date on or before which a currency must have been in use. |
| * Measured in milliseconds since Jan 1, 1970 GMT. |
| * @stable ICU 51 |
| */ |
| public CurrencyFilter withDateRange(long from, long to) { |
| return new CurrencyFilter(this.region, this.currency, from, to, this.tenderOnly); |
| } |
| |
| /** |
| * Returns a copy of this filter that filters for currencies that were |
| * either once used, are used, or will be used as tender. |
| * @stable ICU 51 |
| */ |
| public CurrencyFilter withTender() { |
| return new CurrencyFilter(this.region, this.currency, this.from, this.to, true); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * @stable ICU 4.4 |
| */ |
| @Override |
| public boolean equals(Object rhs) { |
| return rhs instanceof CurrencyFilter && |
| equals((CurrencyFilter) rhs); |
| } |
| |
| /** |
| * Type-safe override of {@link #equals(Object)}. |
| * @param rhs the currency filter to compare to |
| * @return true if the filters are equal |
| * @stable ICU 4.4 |
| */ |
| public boolean equals(CurrencyFilter rhs) { |
| return this == rhs || (rhs != null && |
| equals(this.region, rhs.region) && |
| equals(this.currency, rhs.currency) && |
| this.from == rhs.from && |
| this.to == rhs.to && |
| this.tenderOnly == rhs.tenderOnly); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * @stable ICU 4.4 |
| */ |
| @Override |
| public int hashCode() { |
| int hc = 0; |
| if (region != null) { |
| hc = region.hashCode(); |
| } |
| if (currency != null) { |
| hc = hc * 31 + currency.hashCode(); |
| } |
| hc = hc * 31 + (int) from; |
| hc = hc * 31 + (int) (from >>> 32); |
| hc = hc * 31 + (int) to; |
| hc = hc * 31 + (int) (to >>> 32); |
| hc = hc * 31 + (tenderOnly ? 1 : 0); |
| return hc; |
| } |
| |
| /** |
| * Returns a string representing the filter, for debugging. |
| * @return A string representing the filter. |
| * @stable ICU 4.4 |
| */ |
| @Override |
| public String toString() { |
| return debugString(this); |
| } |
| |
| private static boolean equals(String lhs, String rhs) { |
| return lhs == rhs || (lhs != null && lhs.equals(rhs)); |
| } |
| } |
| |
| /** |
| * Represents the raw information about fraction digits and rounding increment. |
| * @stable ICU 4.4 |
| */ |
| public static final class CurrencyDigits { |
| /** |
| * Number of fraction digits used to display this currency. |
| * @stable ICU 49 |
| */ |
| public final int fractionDigits; |
| /** |
| * Rounding increment used when displaying this currency. |
| * @stable ICU 49 |
| */ |
| public final int roundingIncrement; |
| |
| /** |
| * Constructor for CurrencyDigits. |
| * @param fractionDigits the fraction digits |
| * @param roundingIncrement the rounding increment |
| * @stable ICU 4.4 |
| */ |
| public CurrencyDigits(int fractionDigits, int roundingIncrement) { |
| this.fractionDigits = fractionDigits; |
| this.roundingIncrement = roundingIncrement; |
| } |
| |
| /** |
| * Returns a string representing the currency digits, for debugging. |
| * @return A string representing the currency digits. |
| * @stable ICU 4.4 |
| */ |
| @Override |
| public String toString() { |
| return debugString(this); |
| } |
| } |
| |
| /** |
| * Represents a complete currency info record listing the region, currency, from and to dates, |
| * and priority. |
| * Use {@link CurrencyMetaInfo#currencyInfo(CurrencyFilter)} |
| * for a list of info objects matching the filter. |
| * @stable ICU 4.4 |
| */ |
| public static final class CurrencyInfo { |
| /** |
| * Region code where currency is used. |
| * @stable ICU 4.4 |
| */ |
| public final String region; |
| |
| /** |
| * The three-letter ISO currency code. |
| * @stable ICU 4.4 |
| */ |
| public final String code; |
| |
| /** |
| * Date on which the currency was first officially used in the region. |
| * This is midnight at the start of the first day on which the currency was used, GMT. |
| * If there is no date, this is Long.MIN_VALUE; |
| * @stable ICU 4.4 |
| */ |
| public final long from; |
| |
| /** |
| * Date at which the currency stopped being officially used in the region. |
| * This is one millisecond before midnight at the end of the last day on which the currency was used, GMT. |
| * If there is no date, this is Long.MAX_VALUE. |
| * |
| * @stable ICU 4.4 |
| */ |
| public final long to; |
| |
| /** |
| * Preference order of currencies being used at the same time in the region. Lower |
| * values are preferred (generally, this is a transition from an older to a newer |
| * currency). Priorities within a single country are unique. |
| * @stable ICU 49 |
| */ |
| public final int priority; |
| |
| |
| private final boolean tender; |
| |
| /** |
| * @deprecated ICU 51 Use {@link CurrencyMetaInfo#currencyInfo(CurrencyFilter)} instead. |
| */ |
| @Deprecated |
| public CurrencyInfo(String region, String code, long from, long to, int priority) { |
| this(region, code, from, to, priority, true); |
| } |
| |
| /** |
| * Constructs a currency info. |
| * |
| * @internal |
| * @deprecated This API is ICU internal only. |
| */ |
| @Deprecated |
| public CurrencyInfo(String region, String code, long from, long to, int priority, boolean tender) { |
| this.region = region; |
| this.code = code; |
| this.from = from; |
| this.to = to; |
| this.priority = priority; |
| this.tender = tender; |
| } |
| |
| /** |
| * Returns a string representation of this object, useful for debugging. |
| * @return A string representation of this object. |
| * @stable ICU 4.4 |
| */ |
| @Override |
| public String toString() { |
| return debugString(this); |
| } |
| |
| /** |
| * Determine whether or not this currency was once used, is used, |
| * or will be used as tender in this region. |
| * @stable ICU 51 |
| */ |
| public boolean isTender() { |
| return tender; |
| } |
| } |
| |
| ///CLOVER:OFF |
| /** |
| * Returns the list of CurrencyInfos matching the provided filter. Results |
| * are ordered by country code, then by highest to lowest priority (0 is highest). |
| * The returned list is unmodifiable. |
| * @param filter the filter to control which currency info to return |
| * @return the matching information |
| * @stable ICU 4.4 |
| */ |
| public List<CurrencyInfo> currencyInfo(CurrencyFilter filter) { |
| return Collections.emptyList(); |
| } |
| |
| /** |
| * Returns the list of currency codes matching the provided filter. |
| * Results are ordered as in {@link #currencyInfo(CurrencyFilter)}. |
| * The returned list is unmodifiable. |
| * @param filter the filter to control which currencies to return. If filter is null, |
| * returns all currencies for which information is available. |
| * @return the matching currency codes |
| * @stable ICU 4.4 |
| */ |
| public List<String> currencies(CurrencyFilter filter) { |
| return Collections.emptyList(); |
| } |
| |
| /** |
| * Returns the list of region codes matching the provided filter. |
| * Results are ordered as in {@link #currencyInfo(CurrencyFilter)}. |
| * The returned list is unmodifiable. |
| * @param filter the filter to control which regions to return. If filter is null, |
| * returns all regions for which information is available. |
| * @return the matching region codes |
| * @stable ICU 4.4 |
| */ |
| public List<String> regions(CurrencyFilter filter) { |
| return Collections.emptyList(); |
| } |
| ///CLOVER:ON |
| |
| /** |
| * Returns the CurrencyDigits for the currency code. |
| * This is equivalent to currencyDigits(isoCode, CurrencyUsage.STANDARD); |
| * @param isoCode the currency code |
| * @return the CurrencyDigits |
| * @stable ICU 4.4 |
| */ |
| public CurrencyDigits currencyDigits(String isoCode) { |
| return currencyDigits(isoCode, CurrencyUsage.STANDARD); |
| } |
| |
| /** |
| * Returns the CurrencyDigits for the currency code with Context Usage. |
| * @param isoCode the currency code |
| * @param currencyUsage the currency usage |
| * @return the CurrencyDigits |
| * @stable ICU 54 |
| */ |
| public CurrencyDigits currencyDigits(String isoCode, CurrencyUsage currencyUsage) { |
| return defaultDigits; |
| } |
| |
| /** |
| * @internal |
| * @deprecated This API is ICU internal only. |
| */ |
| @Deprecated |
| protected static final CurrencyDigits defaultDigits = new CurrencyDigits(2, 0); |
| |
| static { |
| CurrencyMetaInfo temp = null; |
| boolean tempHasData = false; |
| try { |
| Class<?> clzz = Class.forName("com.ibm.icu.impl.ICUCurrencyMetaInfo"); |
| temp = (CurrencyMetaInfo) clzz.newInstance(); |
| tempHasData = true; |
| } catch (Throwable t) { |
| temp = new CurrencyMetaInfo(); |
| } |
| impl = temp; |
| hasData = tempHasData; |
| } |
| |
| private static String dateString(long date) { |
| if (date == Long.MAX_VALUE || date == Long.MIN_VALUE) { |
| return null; |
| } |
| return Grego.timeToString(date); |
| } |
| |
| private static String debugString(Object o) { |
| StringBuilder sb = new StringBuilder(); |
| try { |
| for (Field f : o.getClass().getFields()) { |
| Object v = f.get(o); |
| if (v != null) { |
| String s; |
| if (v instanceof Date) { |
| s = dateString(((Date)v).getTime()); |
| } else if (v instanceof Long) { |
| s = dateString(((Long)v).longValue()); |
| } else { |
| s = String.valueOf(v); |
| } |
| if (s == null) { |
| continue; |
| } |
| if (sb.length() > 0) { |
| sb.append(","); |
| } |
| sb.append(f.getName()) |
| .append("='") |
| .append(s) |
| .append("'"); |
| } |
| } |
| } catch (Throwable t) { |
| } |
| sb.insert(0, o.getClass().getSimpleName() + "("); |
| sb.append(")"); |
| return sb.toString(); |
| } |
| } |