• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2017 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 package ohos.global.icu.number;
5 
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Map;
9 import java.util.Set;
10 
11 import ohos.global.icu.impl.StandardPlural;
12 import ohos.global.icu.impl.number.CompactData;
13 import ohos.global.icu.impl.number.CompactData.CompactType;
14 import ohos.global.icu.impl.number.DecimalFormatProperties;
15 import ohos.global.icu.impl.number.DecimalQuantity;
16 import ohos.global.icu.impl.number.MicroProps;
17 import ohos.global.icu.impl.number.MicroPropsGenerator;
18 import ohos.global.icu.impl.number.MutablePatternModifier;
19 import ohos.global.icu.impl.number.MutablePatternModifier.ImmutablePatternModifier;
20 import ohos.global.icu.impl.number.PatternStringParser;
21 import ohos.global.icu.impl.number.PatternStringParser.ParsedPatternInfo;
22 import ohos.global.icu.text.CompactDecimalFormat.CompactStyle;
23 import ohos.global.icu.text.NumberFormat;
24 import ohos.global.icu.text.PluralRules;
25 import ohos.global.icu.util.ULocale;
26 
27 /**
28  * A class that defines the scientific notation style to be used when formatting numbers in
29  * NumberFormatter.
30  *
31  * <p>
32  * This class exposes no public functionality. To create a CompactNotation, use one of the factory
33  * methods in {@link Notation}.
34  *
35  * @see NumberFormatter
36  * @hide exposed on OHOS
37  */
38 public class CompactNotation extends Notation {
39 
40     final CompactStyle compactStyle;
41     final Map<String, Map<String, String>> compactCustomData;
42 
43     /**
44      * Create a compact notation with custom data.
45      * @deprecated This API is ICU internal only.
46      * @see DecimalFormatProperties#setCompactCustomData
47      * @hide draft / provisional / internal are hidden on OHOS
48      */
49     @Deprecated
forCustomData(Map<String, Map<String, String>> compactCustomData)50     public static CompactNotation forCustomData(Map<String, Map<String, String>> compactCustomData) {
51         return new CompactNotation(compactCustomData);
52     }
53 
CompactNotation(CompactStyle compactStyle)54     /* package-private */ CompactNotation(CompactStyle compactStyle) {
55         compactCustomData = null;
56         this.compactStyle = compactStyle;
57     }
58 
CompactNotation(Map<String, Map<String, String>> compactCustomData)59     /* package-private */ CompactNotation(Map<String, Map<String, String>> compactCustomData) {
60         compactStyle = null;
61         this.compactCustomData = compactCustomData;
62     }
63 
withLocaleData( ULocale locale, String nsName, CompactType compactType, PluralRules rules, MutablePatternModifier buildReference, boolean safe, MicroPropsGenerator parent)64     /* package-private */ MicroPropsGenerator withLocaleData(
65             ULocale locale,
66             String nsName,
67             CompactType compactType,
68             PluralRules rules,
69             MutablePatternModifier buildReference,
70             boolean safe,
71             MicroPropsGenerator parent) {
72         // TODO: Add a data cache? It would be keyed by locale, nsName, compact type, and compact style.
73         return new CompactHandler(this, locale, nsName, compactType, rules, buildReference, safe, parent);
74     }
75 
76     private static class CompactHandler implements MicroPropsGenerator {
77 
78         final PluralRules rules;
79         final MicroPropsGenerator parent;
80         final Map<String, ImmutablePatternModifier> precomputedMods;
81         final MutablePatternModifier unsafePatternModifier;
82         final CompactData data;
83 
CompactHandler( CompactNotation notation, ULocale locale, String nsName, CompactType compactType, PluralRules rules, MutablePatternModifier buildReference, boolean safe, MicroPropsGenerator parent)84         private CompactHandler(
85                 CompactNotation notation,
86                 ULocale locale,
87                 String nsName,
88                 CompactType compactType,
89                 PluralRules rules,
90                 MutablePatternModifier buildReference,
91                 boolean safe,
92                 MicroPropsGenerator parent) {
93             this.rules = rules;
94             this.parent = parent;
95             this.data = new CompactData();
96             if (notation.compactStyle != null) {
97                 data.populate(locale, nsName, notation.compactStyle, compactType);
98             } else {
99                 data.populate(notation.compactCustomData);
100             }
101             if (safe) {
102                 // Safe code path
103                 precomputedMods = new HashMap<>();
104                 precomputeAllModifiers(buildReference);
105                 unsafePatternModifier = null;
106             } else {
107                 // Unsafe code path
108                 precomputedMods = null;
109                 unsafePatternModifier = buildReference;
110             }
111         }
112 
113         /** Used by the safe code path */
precomputeAllModifiers(MutablePatternModifier buildReference)114         private void precomputeAllModifiers(MutablePatternModifier buildReference) {
115             Set<String> allPatterns = new HashSet<>();
116             data.getUniquePatterns(allPatterns);
117 
118             for (String patternString : allPatterns) {
119                 ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
120                 buildReference.setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
121                 precomputedMods.put(patternString, buildReference.createImmutable());
122             }
123         }
124 
125         @Override
processQuantity(DecimalQuantity quantity)126         public MicroProps processQuantity(DecimalQuantity quantity) {
127             MicroProps micros = parent.processQuantity(quantity);
128             assert micros.rounder != null;
129 
130             // Treat zero, NaN, and infinity as if they had magnitude 0
131             int magnitude;
132             int multiplier = 0;
133             if (quantity.isZeroish()) {
134                 magnitude = 0;
135                 micros.rounder.apply(quantity);
136             } else {
137                 multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data);
138                 magnitude = quantity.isZeroish() ? 0 : quantity.getMagnitude();
139                 magnitude -= multiplier;
140             }
141 
142             StandardPlural plural = quantity.getStandardPlural(rules);
143             String patternString = data.getPattern(magnitude, plural);
144             if (patternString == null) {
145                 // Use the default (non-compact) modifier.
146                 // No need to take any action.
147             } else if (precomputedMods != null) {
148                 // Safe code path.
149                 // Java uses a hash set here for O(1) lookup. C++ uses a linear search.
150                 ImmutablePatternModifier mod = precomputedMods.get(patternString);
151                 mod.applyToMicros(micros, quantity);
152             } else {
153                 // Unsafe code path.
154                 // Overwrite the PatternInfo in the existing modMiddle.
155                 ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
156                 unsafePatternModifier.setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
157                 unsafePatternModifier.setNumberProperties(quantity.signum(), null);
158                 micros.modMiddle = unsafePatternModifier;
159             }
160 
161             // Change the exponent only after we select appropriate plural form
162             // for formatting purposes so that we preserve expected formatted
163             // string behavior.
164             quantity.adjustExponent(-1 * multiplier);
165 
166             // We already performed rounding. Do not perform it again.
167             micros.rounder = null;
168 
169             return micros;
170         }
171     }
172 }