Left: | ||
Right: |
|
OLD | NEW |
---|---|
(Empty) | |
1 // © 2017 and later: Unicode, Inc. and others. | |
2 // License & terms of use: http://www.unicode.org/copyright.html#License | |
3 package com.ibm.icu.impl.number; | |
4 | |
5 import java.text.ParseException; | |
6 import java.util.HashMap; | |
7 import java.util.Locale; | |
8 import java.util.Map; | |
9 | |
10 import com.ibm.icu.impl.number.Format.BeforeTargetAfterFormat; | |
11 import com.ibm.icu.impl.number.Format.SingularFormat; | |
12 import com.ibm.icu.impl.number.Format.TargetFormat; | |
13 import com.ibm.icu.impl.number.formatters.BigDecimalMultiplier; | |
14 import com.ibm.icu.impl.number.formatters.CompactDecimalFormat; | |
15 import com.ibm.icu.impl.number.formatters.CurrencyFormat; | |
16 import com.ibm.icu.impl.number.formatters.MagnitudeMultiplier; | |
17 import com.ibm.icu.impl.number.formatters.MeasureFormat; | |
18 import com.ibm.icu.impl.number.formatters.PaddingFormat; | |
19 import com.ibm.icu.impl.number.formatters.PositiveDecimalFormat; | |
20 import com.ibm.icu.impl.number.formatters.PositiveNegativeAffixFormat; | |
21 import com.ibm.icu.impl.number.formatters.ScientificFormat; | |
22 import com.ibm.icu.text.DecimalFormatSymbols; | |
23 import com.ibm.icu.text.PluralRules; | |
24 import com.ibm.icu.util.ULocale; | |
25 | |
26 public class Endpoint { | |
27 // public static Format from(DecimalFormatSymbols symbols, Properties propert ies) | |
28 // throws ParseException { | |
29 // Format format = new PositiveIntegerFormat(symbols, properties); | |
30 // // TODO: integer-only format | |
31 // format = new PositiveDecimalFormat((SelfContainedFormat) format, symbols , properties); | |
32 // if (properties.useCompactDecimalFormat()) { | |
33 // format = CompactDecimalFormat.getInstance((SingularFormat) format, sym bols, properties); | |
34 // } else { | |
35 // format = | |
36 // PositiveNegativeAffixFormat.getInstance((SingularFormat) format, s ymbols, properties); | |
37 // } | |
38 // if (properties.useRoundingInterval()) { | |
39 // format = new IntervalRoundingFormat((SingularFormat) format, propertie s); | |
40 // } else if (properties.useSignificantDigits()) { | |
41 // format = new SignificantDigitsFormat((SingularFormat) format, properti es); | |
42 // } else if (properties.useFractionFormat()) { | |
43 // format = new RoundingFormat((SingularFormat) format, properties); | |
44 // } | |
45 // return format; | |
46 // } | |
47 | |
48 public static Format fromBTA(Properties properties) throws ParseException { | |
49 return fromBTA(properties, getSymbols()); | |
50 } | |
51 | |
52 public static SingularFormat fromBTA(Properties properties, Locale locale) thr ows ParseException { | |
53 return fromBTA(properties, getSymbols(locale)); | |
54 } | |
55 | |
56 public static SingularFormat fromBTA(Properties properties, ULocale uLocale) t hrows ParseException { | |
57 return fromBTA(properties, getSymbols(uLocale)); | |
58 } | |
59 | |
60 public static SingularFormat fromBTA(String pattern) throws ParseException { | |
61 return fromBTA(getProperties(pattern), getSymbols()); | |
62 } | |
63 | |
64 public static SingularFormat fromBTA(String pattern, Locale locale) throws Par seException { | |
65 return fromBTA(getProperties(pattern), getSymbols(locale)); | |
66 } | |
67 | |
68 public static SingularFormat fromBTA(String pattern, ULocale uLocale) throws P arseException { | |
69 return fromBTA(getProperties(pattern), getSymbols(uLocale)); | |
70 } | |
71 | |
72 public static SingularFormat fromBTA(String pattern, DecimalFormatSymbols symb ols) throws ParseException { | |
73 return fromBTA(getProperties(pattern), symbols); | |
74 } | |
75 | |
76 public static SingularFormat fromBTA(Properties properties, DecimalFormatSymbo ls symbols) | |
sffc
2017/01/21 11:13:24
This is the first of the two main entrypoints into
| |
77 throws ParseException { | |
78 // TODO: This fast track results in an improvement of about 10ns during form atting. See if | |
79 // there is a way to implement it more elegantly. | |
80 boolean canUseFastTrack = true; | |
81 PluralRules rules = PluralRules.forLocale(symbols.getULocale()); | |
82 BeforeTargetAfterFormat format = new Format.BeforeTargetAfterFormat(rules); | |
83 TargetFormat target = new PositiveDecimalFormat(symbols, properties); | |
84 format.setTargetFormat(target); | |
85 // TODO: integer-only format? | |
86 if (MagnitudeMultiplier.useMagnitudeMultiplier(properties)) { | |
87 canUseFastTrack = false; | |
88 format.addBeforeFormat(MagnitudeMultiplier.getInstance(properties)); | |
89 } | |
90 if (BigDecimalMultiplier.useMultiplier(properties)) { | |
91 canUseFastTrack = false; | |
92 format.addBeforeFormat(BigDecimalMultiplier.getInstance(properties)); | |
93 } | |
94 if (MeasureFormat.useMeasureFormat(properties)) { | |
95 canUseFastTrack = false; | |
96 format.addBeforeFormat(MeasureFormat.getInstance(symbols, properties)); | |
97 } | |
98 if (CompactDecimalFormat.useCompactDecimalFormat(properties)) { | |
99 canUseFastTrack = false; | |
100 format.addBeforeFormat(CompactDecimalFormat.getInstance(symbols, propertie s)); | |
101 } else if (CurrencyFormat.useCurrency(properties)) { | |
102 canUseFastTrack = false; | |
103 format.addBeforeFormat(CurrencyFormat.getCurrencyModifier(symbols, propert ies)); | |
104 format.addBeforeFormat(CurrencyFormat.getCurrencyRounder(symbols, properti es)); | |
105 } else if (ScientificFormat.useScientificNotation(properties)) { | |
106 // TODO: Is it possible to combine significant digits with currency? | |
107 canUseFastTrack = false; | |
108 format.addBeforeFormat(PositiveNegativeAffixFormat.getInstance(symbols, pr operties)); | |
109 format.addBeforeFormat(ScientificFormat.getInstance(symbols, properties)); | |
110 } else { | |
111 format.addBeforeFormat(PositiveNegativeAffixFormat.getInstance(symbols, pr operties)); | |
112 format.addBeforeFormat(Rounder.getDefaultRounder(properties)); | |
113 } | |
114 if (PaddingFormat.usePadding(properties)) { | |
115 canUseFastTrack = false; | |
116 format.addAfterFormat(PaddingFormat.getInstance(properties)); | |
117 } | |
118 if (canUseFastTrack) { | |
119 return new Format.PositiveNegativeRounderTargetFormat( | |
120 PositiveNegativeAffixFormat.getInstance(symbols, properties), | |
121 Rounder.getDefaultRounder(properties), | |
122 target); | |
123 } else { | |
124 return format; | |
125 } | |
126 } | |
127 | |
128 public static String staticFormat(FormatQuantity input, Properties properties) | |
129 throws ParseException { | |
130 return staticFormat(input, properties, getSymbols()); | |
131 } | |
132 | |
133 public static String staticFormat(FormatQuantity input, Properties properties, Locale locale) | |
134 throws ParseException { | |
135 return staticFormat(input, properties, getSymbols(locale)); | |
136 } | |
137 | |
138 public static String staticFormat(FormatQuantity input, Properties properties, ULocale uLocale) | |
139 throws ParseException { | |
140 return staticFormat(input, properties, getSymbols(uLocale)); | |
141 } | |
142 | |
143 public static String staticFormat(FormatQuantity input, String pattern) throws ParseException { | |
144 return staticFormat(input, getProperties(pattern), getSymbols()); | |
145 } | |
146 | |
147 public static String staticFormat(FormatQuantity input, String pattern, Locale locale) | |
148 throws ParseException { | |
149 return staticFormat(input, getProperties(pattern), getSymbols(locale)); | |
150 } | |
151 | |
152 public static String staticFormat(FormatQuantity input, String pattern, ULocal e uLocale) | |
153 throws ParseException { | |
154 return staticFormat(input, getProperties(pattern), getSymbols(uLocale)); | |
155 } | |
156 | |
157 public static String staticFormat( | |
158 FormatQuantity input, String pattern, DecimalFormatSymbols symbols) throws ParseException { | |
159 return staticFormat(input, getProperties(pattern), symbols); | |
160 } | |
161 | |
162 public static String staticFormat( | |
163 FormatQuantity input, Properties properties, DecimalFormatSymbols symbols) | |
sffc
2017/01/21 11:13:24
This is the other entrypoint into my code. It tri
| |
164 throws ParseException { | |
165 PluralRules rules = null; | |
166 ModifierHolder mods = Format.threadLocalModifierHolder.get().clear(); | |
167 DoubleSidedStringBuilder sb = Format.threadLocalStringBuilder.get().clear(); | |
168 int length = 0; | |
169 | |
170 // Pre-processing | |
171 if (!input.isNaN()) { | |
172 if (MagnitudeMultiplier.useMagnitudeMultiplier(properties)) { | |
173 MagnitudeMultiplier.getInstance(properties).before(input, mods, rules); | |
174 } | |
175 if (BigDecimalMultiplier.useMultiplier(properties)) { | |
176 BigDecimalMultiplier.getInstance(properties).before(input, mods, rules); | |
177 } | |
178 if (MeasureFormat.useMeasureFormat(properties)) { | |
179 rules = (rules != null) ? rules : getPluralRules(symbols.getULocale()); | |
180 MeasureFormat.getInstance(symbols, properties).before(input, mods, rules ); | |
181 } | |
182 if (CompactDecimalFormat.useCompactDecimalFormat(properties)) { | |
183 rules = (rules != null) ? rules : getPluralRules(symbols.getULocale()); | |
184 CompactDecimalFormat.apply(input, mods, rules, symbols, properties); | |
185 } else if (CurrencyFormat.useCurrency(properties)) { | |
186 rules = (rules != null) ? rules : getPluralRules(symbols.getULocale()); | |
187 CurrencyFormat.getCurrencyModifier(symbols, properties).before(input, mo ds, rules); | |
188 CurrencyFormat.getCurrencyRounder(symbols, properties).before(input, mod s, rules); | |
189 } else if (ScientificFormat.useScientificNotation(properties)) { | |
190 // TODO: Is it possible to combine significant digits with currency? | |
191 PositiveNegativeAffixFormat.getInstance(symbols, properties).before(inpu t, mods, rules); | |
192 ScientificFormat.getInstance(symbols, properties).before(input, mods, ru les); | |
193 } else { | |
194 PositiveNegativeAffixFormat.apply(input, mods, symbols, properties); | |
195 Rounder.getDefaultRounder(properties).before(input, mods, rules); | |
196 } | |
197 } | |
198 | |
199 // Primary format step | |
200 length += new PositiveDecimalFormat(symbols, properties).target(input, sb, 0 ); | |
201 | |
202 // Post-processing | |
203 if (PaddingFormat.usePadding(properties)) { | |
204 length += PaddingFormat.getInstance(properties).after(mods, sb, 0, length) ; | |
205 } | |
206 length += mods.applyAll(sb, 0, length); | |
207 | |
208 return sb.toString(); | |
209 } | |
210 | |
211 private static final ThreadLocal<Map<ULocale, DecimalFormatSymbols>> threadLoc alSymbolsCache = | |
sffc
2017/01/21 11:13:24
You'll see a lot of ThreadLocal stuff in my code.
| |
212 new ThreadLocal<Map<ULocale, DecimalFormatSymbols>>() { | |
213 @Override | |
214 protected Map<ULocale, DecimalFormatSymbols> initialValue() { | |
215 return new HashMap<ULocale, DecimalFormatSymbols>(); | |
216 } | |
217 }; | |
218 | |
219 private static DecimalFormatSymbols getSymbols() { | |
220 ULocale uLocale = ULocale.getDefault(); | |
221 return getSymbols(uLocale); | |
222 } | |
223 | |
224 private static DecimalFormatSymbols getSymbols(Locale locale) { | |
225 ULocale uLocale = ULocale.forLocale(locale); | |
226 return getSymbols(uLocale); | |
227 } | |
228 | |
229 private static DecimalFormatSymbols getSymbols(ULocale uLocale) { | |
230 if (uLocale == null) uLocale = ULocale.getDefault(); | |
231 DecimalFormatSymbols symbols = threadLocalSymbolsCache.get().get(uLocale); | |
232 if (symbols == null) { | |
233 symbols = DecimalFormatSymbols.getInstance(uLocale); | |
234 threadLocalSymbolsCache.get().put(uLocale, symbols); | |
235 } | |
236 return symbols; | |
237 } | |
238 | |
239 private static final ThreadLocal<Map<String, Properties>> threadLocalPropertie sCache = | |
sffc
2017/01/21 11:13:24
This is new: a cache from pattern strings to prope
| |
240 new ThreadLocal<Map<String, Properties>>() { | |
241 @Override | |
242 protected Map<String, Properties> initialValue() { | |
243 return new HashMap<String, Properties>(); | |
244 } | |
245 }; | |
246 | |
247 private static Properties getProperties(String pattern) throws ParseException { | |
248 if (pattern == null) pattern = "#"; | |
249 Properties properties = threadLocalPropertiesCache.get().get(pattern); | |
250 if (properties == null) { | |
251 properties = PatternString.parseToProperties(pattern); | |
252 threadLocalPropertiesCache.get().put(pattern.intern(), properties); | |
253 } | |
254 return properties; | |
255 } | |
256 | |
257 private static final ThreadLocal<Map<ULocale, PluralRules>> threadLocalRulesCa che = | |
258 new ThreadLocal<Map<ULocale, PluralRules>>() { | |
259 @Override | |
260 protected Map<ULocale, PluralRules> initialValue() { | |
261 return new HashMap<ULocale, PluralRules>(); | |
262 } | |
263 }; | |
264 | |
265 private static PluralRules getPluralRules(ULocale uLocale) { | |
266 if (uLocale == null) uLocale = ULocale.getDefault(); | |
267 PluralRules rules = threadLocalRulesCache.get().get(uLocale); | |
268 if (rules == null) { | |
269 rules = PluralRules.forLocale(uLocale); | |
270 threadLocalRulesCache.get().put(uLocale, rules); | |
271 } | |
272 return rules; | |
273 } | |
274 } | |
OLD | NEW |