• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5  *******************************************************************************
6  * Copyright (C) 2009-2016, International Business Machines Corporation and
7  * others. All Rights Reserved.
8  *******************************************************************************
9  */
10 package ohos.global.icu.impl;
11 
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17 
18 import ohos.global.icu.text.CurrencyMetaInfo;
19 import ohos.global.icu.util.Currency.CurrencyUsage;
20 
21 /**
22  * ICU's currency meta info data.
23  * @hide exposed on OHOS
24  */
25 public class ICUCurrencyMetaInfo extends CurrencyMetaInfo {
26     private ICUResourceBundle regionInfo;
27     private ICUResourceBundle digitInfo;
28 
ICUCurrencyMetaInfo()29     public ICUCurrencyMetaInfo() {
30         ICUResourceBundle bundle = (ICUResourceBundle) ICUResourceBundle.getBundleInstance(
31             ICUData.ICU_CURR_BASE_NAME, "supplementalData",
32             ICUResourceBundle.ICU_DATA_CLASS_LOADER);
33         regionInfo = bundle.findTopLevel("CurrencyMap");
34         digitInfo = bundle.findTopLevel("CurrencyMeta");
35     }
36 
37     @Override
currencyInfo(CurrencyFilter filter)38     public List<CurrencyInfo> currencyInfo(CurrencyFilter filter) {
39         return collect(new InfoCollector(), filter);
40     }
41 
42     @Override
currencies(CurrencyFilter filter)43     public List<String> currencies(CurrencyFilter filter) {
44         return collect(new CurrencyCollector(), filter);
45    }
46 
47     @Override
regions(CurrencyFilter filter)48     public List<String> regions(CurrencyFilter filter) {
49         return collect(new RegionCollector(), filter);
50     }
51 
52     @Override
currencyDigits(String isoCode)53     public CurrencyDigits currencyDigits(String isoCode) {
54         return currencyDigits(isoCode, CurrencyUsage.STANDARD);
55     }
56 
57     @Override
currencyDigits(String isoCode, CurrencyUsage currencyPurpose)58     public CurrencyDigits currencyDigits(String isoCode, CurrencyUsage currencyPurpose) {
59         ICUResourceBundle b = digitInfo.findWithFallback(isoCode);
60         if (b == null) {
61             b = digitInfo.findWithFallback("DEFAULT");
62         }
63         int[] data = b.getIntVector();
64         if (currencyPurpose == CurrencyUsage.CASH) {
65             return new CurrencyDigits(data[2], data[3]);
66         } else if (currencyPurpose == CurrencyUsage.STANDARD) {
67             return new CurrencyDigits(data[0], data[1]);
68         } else {
69             return new CurrencyDigits(data[0], data[1]);
70         }
71     }
72 
collect(Collector<T> collector, CurrencyFilter filter)73     private <T> List<T> collect(Collector<T> collector, CurrencyFilter filter) {
74         // We rely on the fact that the data lists the regions in order, and the
75         // priorities in order within region.  This means we don't need
76         // to sort the results to ensure the ordering matches the spec.
77 
78         if (filter == null) {
79             filter = CurrencyFilter.all();
80         }
81         int needed = collector.collects();
82         if (filter.region != null) {
83             needed |= Region;
84         }
85         if (filter.currency != null) {
86             needed |= Currency;
87         }
88         if (filter.from != Long.MIN_VALUE || filter.to != Long.MAX_VALUE) {
89             needed |= Date;
90         }
91         if (filter.tenderOnly) {
92             needed |= Tender;
93         }
94 
95         if (needed != 0) {
96             if (filter.region != null) {
97                 ICUResourceBundle b = regionInfo.findWithFallback(filter.region);
98                 if (b != null) {
99                     collectRegion(collector, filter, needed, b);
100                 }
101             } else {
102                 for (int i = 0; i < regionInfo.getSize(); i++) {
103                     collectRegion(collector, filter, needed, regionInfo.at(i));
104                 }
105             }
106         }
107 
108         return collector.getList();
109     }
110 
collectRegion(Collector<T> collector, CurrencyFilter filter, int needed, ICUResourceBundle b)111     private <T> void collectRegion(Collector<T> collector, CurrencyFilter filter,
112             int needed, ICUResourceBundle b) {
113 
114         String region = b.getKey();
115         if (needed == Region) {
116             collector.collect(b.getKey(), null, 0, 0, -1, false);
117             return;
118         }
119 
120         for (int i = 0; i < b.getSize(); i++) {
121             ICUResourceBundle r = b.at(i);
122             if (r.getSize() == 0) {
123                 // AQ[0] is an empty array instead of a table, so the bundle is null.
124                 // There's no data here, so we skip this entirely.
125                 // We'd do a type test, but the ResourceArray type is private.
126                 continue;
127             }
128             String currency = null;
129             long from = Long.MIN_VALUE;
130             long to = Long.MAX_VALUE;
131             boolean tender = true;
132 
133             if ((needed & Currency) != 0) {
134                 ICUResourceBundle currBundle = r.at("id");
135                 currency = currBundle.getString();
136                 if (filter.currency != null && !filter.currency.equals(currency)) {
137                     continue;
138                 }
139             }
140 
141             if ((needed & Date) != 0) {
142                 from = getDate(r.at("from"), Long.MIN_VALUE, false);
143                 to = getDate(r.at("to"), Long.MAX_VALUE, true);
144                 // In the data, to is always > from.  This means that when we have a range
145                 // from == to, the comparisons below will always do the right thing, despite
146                 // the range being technically empty.  It really should be [from, from+1) but
147                 // this way we don't need to fiddle with it.
148                 if (filter.from > to) {
149                     continue;
150                 }
151                 if (filter.to < from) {
152                     continue;
153                 }
154             }
155             if ((needed & Tender) != 0) {
156                 ICUResourceBundle tenderBundle = r.at("tender");
157                 tender = tenderBundle == null || "true".equals(tenderBundle.getString());
158                 if (filter.tenderOnly && !tender) {
159                     continue;
160                 }
161             }
162 
163             // data lists elements in priority order, so 'i' suffices
164             collector.collect(region, currency, from, to, i, tender);
165         }
166     }
167 
168     private static final long MASK = 4294967295L;
getDate(ICUResourceBundle b, long defaultValue, boolean endOfDay)169     private long getDate(ICUResourceBundle b, long defaultValue, boolean endOfDay) {
170         if (b == null) {
171             return defaultValue;
172         }
173         int[] values = b.getIntVector();
174         return ((long) values[0] << 32) | ((values[1]) & MASK);
175     }
176 
177     // Utility, just because I don't like the n^2 behavior of using list.contains to build a
178     // list of unique items.  If we used java 6 we could use their class for this.
179     private static class UniqueList<T> {
180         private Set<T> seen = new HashSet<T>();
181         private List<T> list = new ArrayList<T>();
182 
create()183         private static <T> UniqueList<T> create() {
184             return new UniqueList<T>();
185         }
186 
add(T value)187         void add(T value) {
188             if (!seen.contains(value)) {
189                 list.add(value);
190                 seen.add(value);
191             }
192         }
193 
list()194         List<T> list() {
195             return Collections.unmodifiableList(list);
196         }
197     }
198 
199     private static class InfoCollector implements Collector<CurrencyInfo> {
200         // Data is already unique by region/priority, so we don't need to be concerned
201         // about duplicates.
202         private List<CurrencyInfo> result = new ArrayList<CurrencyInfo>();
203 
204         @Override
collect(String region, String currency, long from, long to, int priority, boolean tender)205         public void collect(String region, String currency, long from, long to, int priority, boolean tender) {
206             result.add(new CurrencyInfo(region, currency, from, to, priority, tender));
207         }
208 
209         @Override
getList()210         public List<CurrencyInfo> getList() {
211             return Collections.unmodifiableList(result);
212         }
213 
214         @Override
collects()215         public int collects() {
216             return Everything;
217         }
218     }
219 
220     private static class RegionCollector implements Collector<String> {
221         private final UniqueList<String> result = UniqueList.create();
222 
223         @Override
collect( String region, String currency, long from, long to, int priority, boolean tender)224         public void collect(
225                 String region, String currency, long from, long to, int priority, boolean tender) {
226             result.add(region);
227         }
228 
229         @Override
collects()230         public int collects() {
231             return Region;
232         }
233 
234         @Override
getList()235         public List<String> getList() {
236             return result.list();
237         }
238     }
239 
240     private static class CurrencyCollector implements Collector<String> {
241         private final UniqueList<String> result = UniqueList.create();
242 
243         @Override
collect( String region, String currency, long from, long to, int priority, boolean tender)244         public void collect(
245                 String region, String currency, long from, long to, int priority, boolean tender) {
246             result.add(currency);
247         }
248 
249         @Override
collects()250         public int collects() {
251             return Currency;
252         }
253 
254         @Override
getList()255         public List<String> getList() {
256             return result.list();
257         }
258     }
259 
260     private static final int Region = 1;
261     private static final int Currency = 2;
262     private static final int Date = 4;
263     private static final int Tender = 8;
264     private static final int Everything = Integer.MAX_VALUE;
265 
266     private static interface Collector<T> {
267         /**
268          * A bitmask of Region/Currency/Date indicating which features we collect.
269          * @return the bitmask
270          */
collects()271         int collects();
272 
273         /**
274          * Called with data passed by filter.  Values not collected by filter should be ignored.
275          * @param region the region code (null if ignored)
276          * @param currency the currency code (null if ignored)
277          * @param from start time (0 if ignored)
278          * @param to end time (0 if ignored)
279          * @param priority priority (-1 if ignored)
280          * @param tender true if currency is legal tender.
281          */
collect(String region, String currency, long from, long to, int priority, boolean tender)282         void collect(String region, String currency, long from, long to, int priority, boolean tender);
283 
284         /**
285          * Return the list of unique items in the order in which we encountered them for the
286          * first time.  The returned list is unmodifiable.
287          * @return the list
288          */
getList()289         List<T> getList();
290     }
291 }
292