xref: /aosp_15_r20/external/cldr/tools/cldr-code/src/main/java/org/unicode/cldr/test/BuildIcuCompactDecimalFormat.java (revision 912701f9769bb47905792267661f0baf2b85bed5)
1 package org.unicode.cldr.test;
2 
3 import com.ibm.icu.impl.number.DecimalFormatProperties;
4 import com.ibm.icu.impl.number.PatternStringParser;
5 import com.ibm.icu.text.CompactDecimalFormat;
6 import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
7 import com.ibm.icu.text.DecimalFormat;
8 import com.ibm.icu.text.DecimalFormat.PropertySetter;
9 import com.ibm.icu.text.PluralRules;
10 import com.ibm.icu.util.Currency;
11 import com.ibm.icu.util.ULocale;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.Locale;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.TreeMap;
18 import java.util.regex.Pattern;
19 import org.unicode.cldr.util.CLDRFile;
20 import org.unicode.cldr.util.ICUServiceBuilder;
21 import org.unicode.cldr.util.PatternCache;
22 import org.unicode.cldr.util.SupplementalDataInfo;
23 import org.unicode.cldr.util.XPathParts;
24 
25 @SuppressWarnings("deprecation")
26 public class BuildIcuCompactDecimalFormat {
27     static SupplementalDataInfo sdi = SupplementalDataInfo.getInstance();
28     static final int MINIMUM_ARRAY_LENGTH = 15;
29     static final Pattern PATTERN = PatternCache.get("([^0,]*)([0]+)([.]0+)?([^0]*)");
30     static final Pattern TYPE = PatternCache.get("1([0]*)");
31     private static final boolean DEBUG = false;
32 
33     public enum CurrencyStyle {
34         PLAIN,
35         CURRENCY,
36         LONG_CURRENCY,
37         ISO_CURRENCY,
38         UNIT
39     }
40 
41     /**
42      * JUST FOR DEVELOPMENT
43      *
44      * @param currencyStyle
45      * @param currencyCode
46      */
build( CLDRFile resolvedCldrFile, Set<String> debugCreationErrors, String[] debugOriginals, CompactStyle style, ULocale locale, CurrencyStyle currencyStyle, String currencyCodeOrUnit)47     public static final CompactDecimalFormat build(
48             CLDRFile resolvedCldrFile,
49             Set<String> debugCreationErrors,
50             String[] debugOriginals,
51             CompactStyle style,
52             ULocale locale,
53             CurrencyStyle currencyStyle,
54             String currencyCodeOrUnit) {
55 
56         // get the custom data from CLDR for use with the special setCompactCustomData
57 
58         final Map<String, Map<String, String>> customData =
59                 buildCustomData(resolvedCldrFile, style, currencyStyle);
60         if (DEBUG) {
61             System.out.println("\nCustom Data:");
62             customData.forEach((k, v) -> System.out.println("\t" + k + "\t" + v));
63         }
64 
65         // get the common CLDR data used for number/date/time formats
66 
67         ICUServiceBuilder builder = new ICUServiceBuilder().setCldrFile(resolvedCldrFile);
68 
69         DecimalFormat decimalFormat =
70                 currencyStyle == CurrencyStyle.PLAIN
71                         ? builder.getNumberFormat(1)
72                         : builder.getCurrencyFormat(currencyCodeOrUnit);
73         final String pattern = decimalFormat.toPattern();
74         if (DEBUG) {
75             System.out.println("Pattern:\t" + pattern);
76         }
77 
78         final PluralRules rules =
79                 SupplementalDataInfo.getInstance().getPlurals(locale.toString()).getPluralRules();
80 
81         // create a compact decimal format, and reset its data
82 
83         CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(locale, style);
84         cdf.setDecimalFormatSymbols(builder.getDecimalFormatSymbols("latn"));
85 
86         cdf.setProperties(
87                 new PropertySetter() {
88                     @Override
89                     public void set(DecimalFormatProperties props) {
90                         props.setCompactCustomData(customData);
91                         PatternStringParser.parseToExistingProperties(
92                                 pattern, props, PatternStringParser.IGNORE_ROUNDING_ALWAYS);
93                         props.setPluralRules(rules);
94                     }
95                 });
96 
97         if (DEBUG) {
98             System.out.println("CompactDecimalFormat:\t" + cdf.toString().replace("}, ", "},\n\t"));
99         }
100         return cdf;
101     }
102 
buildCustomData( CLDRFile resolvedCldrFile, CompactStyle style, CurrencyStyle currencyStyle)103     public static Map<String, Map<String, String>> buildCustomData(
104             CLDRFile resolvedCldrFile, CompactStyle style, CurrencyStyle currencyStyle) {
105 
106         final Map<String, Map<String, String>> customData = new TreeMap<>();
107 
108         String prefix =
109                 currencyStyle == CurrencyStyle.PLAIN
110                         ? "//ldml/numbers/decimalFormats[@numberSystem=\"latn\"]/decimalFormatLength"
111                         : "//ldml/numbers/currencyFormats[@numberSystem=\"latn\"]/currencyFormatLength";
112 
113         Iterator<String> it = resolvedCldrFile.iterator(prefix);
114 
115         String styleString = style.toString().toLowerCase(Locale.ENGLISH);
116         while (it.hasNext()) {
117             String path = it.next();
118             if (path.endsWith("/alias")) {
119                 continue;
120             }
121             XPathParts parts = XPathParts.getFrozenInstance(path);
122             String stype = parts.getAttributeValue(3, "type");
123             if (!styleString.equals(stype)) {
124                 continue;
125             }
126             String type = parts.getAttributeValue(-1, "type");
127             String key = parts.getAttributeValue(-1, "count");
128             String pattern = resolvedCldrFile.getStringValue(path);
129             if (pattern.contentEquals("0")) {
130                 continue;
131             }
132 
133             /*
134                    <pattern type="1000" count="one">0K</pattern>
135             */
136 
137             add(customData, type, key, pattern);
138         }
139         return customData;
140     }
141 
add(Map<A, Map<B, C>> customData, A a, B b, C c)142     private static <A, B, C> void add(Map<A, Map<B, C>> customData, A a, B b, C c) {
143         Map<B, C> inner = customData.get(a);
144         if (inner == null) {
145             customData.put(a, inner = new HashMap<>());
146         }
147         inner.put(b, c);
148     }
149 
150     static class MyCurrencySymbolDisplay {
151         CLDRFile cldrFile;
152 
MyCurrencySymbolDisplay(CLDRFile cldrFile)153         public MyCurrencySymbolDisplay(CLDRFile cldrFile) {
154             this.cldrFile = cldrFile;
155         }
156 
getName(Currency currency, int count)157         public String getName(Currency currency, int count) {
158             final String currencyCode = currency.getCurrencyCode();
159             if (count > 1) {
160                 return currencyCode;
161             }
162             String prefix = "//ldml/numbers/currencies/currency[@type=\"" + currencyCode + "\"]/";
163             String currencySymbol = cldrFile.getWinningValue(prefix + "symbol");
164             return currencySymbol != null ? currencySymbol : currencyCode;
165         }
166     }
167 }
168