Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.greenpepper.shaded.com.ibm.icu.impl.ICUCurrencyMetaInfo Maven / Gradle / Ivy
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
*******************************************************************************
* Copyright (C) 2009-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.greenpepper.shaded.com.ibm.icu.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.greenpepper.shaded.com.ibm.icu.text.CurrencyMetaInfo;
import com.greenpepper.shaded.com.ibm.icu.util.Currency.CurrencyUsage;
/**
* ICU's currency meta info data.
*/
public class ICUCurrencyMetaInfo extends CurrencyMetaInfo {
private ICUResourceBundle regionInfo;
private ICUResourceBundle digitInfo;
public ICUCurrencyMetaInfo() {
ICUResourceBundle bundle = (ICUResourceBundle) ICUResourceBundle.getBundleInstance(
ICUData.ICU_CURR_BASE_NAME, "supplementalData",
ICUResourceBundle.ICU_DATA_CLASS_LOADER);
regionInfo = bundle.findTopLevel("CurrencyMap");
digitInfo = bundle.findTopLevel("CurrencyMeta");
}
@Override
public List currencyInfo(CurrencyFilter filter) {
return collect(new InfoCollector(), filter);
}
@Override
public List currencies(CurrencyFilter filter) {
return collect(new CurrencyCollector(), filter);
}
@Override
public List regions(CurrencyFilter filter) {
return collect(new RegionCollector(), filter);
}
@Override
public CurrencyDigits currencyDigits(String isoCode) {
return currencyDigits(isoCode, CurrencyUsage.STANDARD);
}
@Override
public CurrencyDigits currencyDigits(String isoCode, CurrencyUsage currencyPurpose) {
ICUResourceBundle b = digitInfo.findWithFallback(isoCode);
if (b == null) {
b = digitInfo.findWithFallback("DEFAULT");
}
int[] data = b.getIntVector();
if (currencyPurpose == CurrencyUsage.CASH) {
return new CurrencyDigits(data[2], data[3]);
} else if (currencyPurpose == CurrencyUsage.STANDARD) {
return new CurrencyDigits(data[0], data[1]);
} else {
return new CurrencyDigits(data[0], data[1]);
}
}
private List collect(Collector collector, CurrencyFilter filter) {
// We rely on the fact that the data lists the regions in order, and the
// priorities in order within region. This means we don't need
// to sort the results to ensure the ordering matches the spec.
if (filter == null) {
filter = CurrencyFilter.all();
}
int needed = collector.collects();
if (filter.region != null) {
needed |= Region;
}
if (filter.currency != null) {
needed |= Currency;
}
if (filter.from != Long.MIN_VALUE || filter.to != Long.MAX_VALUE) {
needed |= Date;
}
if (filter.tenderOnly) {
needed |= Tender;
}
if (needed != 0) {
if (filter.region != null) {
ICUResourceBundle b = regionInfo.findWithFallback(filter.region);
if (b != null) {
collectRegion(collector, filter, needed, b);
}
} else {
for (int i = 0; i < regionInfo.getSize(); i++) {
collectRegion(collector, filter, needed, regionInfo.at(i));
}
}
}
return collector.getList();
}
private void collectRegion(Collector collector, CurrencyFilter filter,
int needed, ICUResourceBundle b) {
String region = b.getKey();
if (needed == Region) {
collector.collect(b.getKey(), null, 0, 0, -1, false);
return;
}
for (int i = 0; i < b.getSize(); i++) {
ICUResourceBundle r = b.at(i);
if (r.getSize() == 0) {
// AQ[0] is an empty array instead of a table, so the bundle is null.
// There's no data here, so we skip this entirely.
// We'd do a type test, but the ResourceArray type is private.
continue;
}
String currency = null;
long from = Long.MIN_VALUE;
long to = Long.MAX_VALUE;
boolean tender = true;
if ((needed & Currency) != 0) {
ICUResourceBundle currBundle = r.at("id");
currency = currBundle.getString();
if (filter.currency != null && !filter.currency.equals(currency)) {
continue;
}
}
if ((needed & Date) != 0) {
from = getDate(r.at("from"), Long.MIN_VALUE, false);
to = getDate(r.at("to"), Long.MAX_VALUE, true);
// In the data, to is always > from. This means that when we have a range
// from == to, the comparisons below will always do the right thing, despite
// the range being technically empty. It really should be [from, from+1) but
// this way we don't need to fiddle with it.
if (filter.from > to) {
continue;
}
if (filter.to < from) {
continue;
}
}
if ((needed & Tender) != 0) {
ICUResourceBundle tenderBundle = r.at("tender");
tender = tenderBundle == null || "true".equals(tenderBundle.getString());
if (filter.tenderOnly && !tender) {
continue;
}
}
// data lists elements in priority order, so 'i' suffices
collector.collect(region, currency, from, to, i, tender);
}
}
private static final long MASK = 4294967295L;
private long getDate(ICUResourceBundle b, long defaultValue, boolean endOfDay) {
if (b == null) {
return defaultValue;
}
int[] values = b.getIntVector();
return ((long) values[0] << 32) | ((values[1]) & MASK);
}
// Utility, just because I don't like the n^2 behavior of using list.contains to build a
// list of unique items. If we used java 6 we could use their class for this.
private static class UniqueList {
private Set seen = new HashSet();
private List list = new ArrayList();
private static UniqueList create() {
return new UniqueList();
}
void add(T value) {
if (!seen.contains(value)) {
list.add(value);
seen.add(value);
}
}
List list() {
return Collections.unmodifiableList(list);
}
}
private static class InfoCollector implements Collector {
// Data is already unique by region/priority, so we don't need to be concerned
// about duplicates.
private List result = new ArrayList();
@Override
public void collect(String region, String currency, long from, long to, int priority, boolean tender) {
result.add(new CurrencyInfo(region, currency, from, to, priority, tender));
}
@Override
public List getList() {
return Collections.unmodifiableList(result);
}
@Override
public int collects() {
return Everything;
}
}
private static class RegionCollector implements Collector {
private final UniqueList result = UniqueList.create();
@Override
public void collect(
String region, String currency, long from, long to, int priority, boolean tender) {
result.add(region);
}
@Override
public int collects() {
return Region;
}
@Override
public List getList() {
return result.list();
}
}
private static class CurrencyCollector implements Collector {
private final UniqueList result = UniqueList.create();
@Override
public void collect(
String region, String currency, long from, long to, int priority, boolean tender) {
result.add(currency);
}
@Override
public int collects() {
return Currency;
}
@Override
public List getList() {
return result.list();
}
}
private static final int Region = 1;
private static final int Currency = 2;
private static final int Date = 4;
private static final int Tender = 8;
private static final int Everything = Integer.MAX_VALUE;
private static interface Collector {
/**
* A bitmask of Region/Currency/Date indicating which features we collect.
* @return the bitmask
*/
int collects();
/**
* Called with data passed by filter. Values not collected by filter should be ignored.
* @param region the region code (null if ignored)
* @param currency the currency code (null if ignored)
* @param from start time (0 if ignored)
* @param to end time (0 if ignored)
* @param priority priority (-1 if ignored)
* @param tender true if currency is legal tender.
*/
void collect(String region, String currency, long from, long to, int priority, boolean tender);
/**
* Return the list of unique items in the order in which we encountered them for the
* first time. The returned list is unmodifiable.
* @return the list
*/
List getList();
}
}