105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert/* GENERATED SOURCE. DO NOT MODIFY. */ 205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert// © 2017 and later: Unicode, Inc. and others. 305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 405fa7802d0874812c234a29745586677ee5837eaFredrik Roubertpackage android.icu.impl.number; 505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 605fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.impl.StandardPlural; 705fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.impl.number.AffixUtils.SymbolProvider; 805fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.number.NumberFormatter.SignDisplay; 905fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.number.NumberFormatter.UnitWidth; 1005fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.text.DecimalFormatSymbols; 1105fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.text.PluralRules; 1205fa7802d0874812c234a29745586677ee5837eaFredrik Roubertimport android.icu.util.Currency; 1305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 1405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert/** 1505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in 1605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * {@link Modifier#apply}. 1705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 1805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * <p> 1905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * In addition to being a Modifier, this class contains the business logic for substituting the correct locale symbols 2005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * into the affixes of the decimal format pattern. 2105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 2205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * <p> 2305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * In order to use this class, create a new instance and call the following four setters: {@link #setPatternInfo}, 2405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * {@link #setPatternAttributes}, {@link #setSymbols}, and {@link #setNumberProperties}. After calling these four 2505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * setters, the instance will be ready for use as a Modifier. 2605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 2705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * <p> 2805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * This is a MUTABLE, NON-THREAD-SAFE class designed for performance. Do NOT save references to this or attempt to use 2905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * it from multiple threads! Instead, you can obtain a safe, immutable decimal format pattern modifier by calling 3005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * {@link MutablePatternModifier#createImmutable}, in effect treating this instance as a builder for the immutable 3105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * variant. 3205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @hide Only a subset of ICU is exposed in Android 3305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 3405fa7802d0874812c234a29745586677ee5837eaFredrik Roubertpublic class MutablePatternModifier implements Modifier, SymbolProvider, CharSequence, MicroPropsGenerator { 3505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 3605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Modifier details 3705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert final boolean isStrong; 3805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 3905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Pattern details 4005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert AffixPatternProvider patternInfo; 4105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert SignDisplay signDisplay; 4205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert boolean perMilleReplacesPercent; 4305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 4405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Symbol details 4505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert DecimalFormatSymbols symbols; 4605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert UnitWidth unitWidth; 4705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert Currency currency; 4805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert PluralRules rules; 4905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 5005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Number details 5105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert boolean isNegative; 5205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert StandardPlural plural; 5305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 5405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // QuantityChain details 5505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert MicroPropsGenerator parent; 5605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 5705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Transient CharSequence fields 5805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert boolean inCharSequenceMode; 5905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int flags; 6005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int length; 6105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert boolean prependSign; 6205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert boolean plusReplacesMinusSign; 6305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 6405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 6505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param isStrong 6605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Whether the modifier should be considered strong. For more information, see 6705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * {@link Modifier#isStrong()}. Most of the time, decimal format pattern modifiers should be considered 6805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * as non-strong. 6905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 7005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public MutablePatternModifier(boolean isStrong) { 7105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.isStrong = isStrong; 7205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 7305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 7405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 7505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Sets a reference to the parsed decimal format pattern, usually obtained from 7605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is 7705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * accepted. 7805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 7905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public void setPatternInfo(AffixPatternProvider patternInfo) { 8005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.patternInfo = patternInfo; 8105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 8205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 8305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 8405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Sets attributes that imply changes to the literal interpretation of the pattern string affixes. 8505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 8605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param signDisplay 8705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Whether to force a plus sign on positive numbers. 8805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param perMille 8905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Whether to substitute the percent sign in the pattern with a permille sign. 9005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 9105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public void setPatternAttributes(SignDisplay signDisplay, boolean perMille) { 9205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.signDisplay = signDisplay; 9305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.perMilleReplacesPercent = perMille; 9405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 9505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 9605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 9705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Sets locale-specific details that affect the symbols substituted into the pattern string affixes. 9805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 9905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param symbols 10005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * The desired instance of DecimalFormatSymbols. 10105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param currency 10205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * The currency to be used when substituting currency values into the affixes. 10305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param unitWidth 10405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * The width used to render currencies. 10505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param rules 10605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the 10705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * convenience method {@link #needsPlurals()}. 10805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 10905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public void setSymbols(DecimalFormatSymbols symbols, Currency currency, UnitWidth unitWidth, PluralRules rules) { 11005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert (rules != null) == needsPlurals(); 11105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.symbols = symbols; 11205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.currency = currency; 11305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.unitWidth = unitWidth; 11405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.rules = rules; 11505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 11605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 11705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 11805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Sets attributes of the current number being processed. 11905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 12005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param isNegative 12105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Whether the number is negative. 12205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param plural 12305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * The plural form of the number, required only if the pattern contains the triple currency sign, "¤¤¤" 12405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * (and as indicated by {@link #needsPlurals()}). 12505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 12605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public void setNumberProperties(boolean isNegative, StandardPlural plural) { 12705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert (plural != null) == needsPlurals(); 12805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.isNegative = isNegative; 12905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.plural = plural; 13005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 13105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 13205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 13305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize. 13405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤"). 13505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 13605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public boolean needsPlurals() { 13705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return patternInfo.containsSymbolType(AffixUtils.TYPE_CURRENCY_TRIPLE); 13805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 13905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 14005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 14105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable 14205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * and can be saved for future use. The number properties in the current instance are mutated; all other properties 14305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * are left untouched. 14405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 14505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * <p> 14605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * The resulting modifier cannot be used in a QuantityChain. 14705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 14805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @return An immutable that supports both positive and negative numbers. 14905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 15005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public ImmutablePatternModifier createImmutable() { 15105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return createImmutableAndChain(null); 15205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 15305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 15405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 15505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable 15605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * and can be saved for future use. The number properties in the current instance are mutated; all other properties 15705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * are left untouched. 15805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 15905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param parent 16005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * The QuantityChain to which to chain this immutable. 16105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @return An immutable that supports both positive and negative numbers. 16205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 16305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public ImmutablePatternModifier createImmutableAndChain(MicroPropsGenerator parent) { 16405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert NumberStringBuilder a = new NumberStringBuilder(); 16505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert NumberStringBuilder b = new NumberStringBuilder(); 16605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (needsPlurals()) { 16705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Slower path when we require the plural keyword. 16805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert ParameterizedModifier pm = new ParameterizedModifier(); 16905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert for (StandardPlural plural : StandardPlural.VALUES) { 17005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setNumberProperties(false, plural); 17105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert pm.setModifier(false, plural, createConstantModifier(a, b)); 17205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setNumberProperties(true, plural); 17305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert pm.setModifier(true, plural, createConstantModifier(a, b)); 17405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 17505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert pm.freeze(); 17605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return new ImmutablePatternModifier(pm, rules, parent); 17705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 17805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Faster path when plural keyword is not needed. 17905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setNumberProperties(false, null); 18005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert Modifier positive = createConstantModifier(a, b); 18105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setNumberProperties(true, null); 18205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert Modifier negative = createConstantModifier(a, b); 18305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert ParameterizedModifier pm = new ParameterizedModifier(positive, negative); 18405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return new ImmutablePatternModifier(pm, null, parent); 18505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 18605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 18705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 18805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 18905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support 19005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * if required. 19105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * 19205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param a 19305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * A working NumberStringBuilder object; passed from the outside to prevent the need to create many new 19405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * instances if this method is called in a loop. 19505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @param b 19605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Another working NumberStringBuilder object. 19705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * @return The constant modifier object. 19805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 19905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert private ConstantMultiFieldModifier createConstantModifier(NumberStringBuilder a, NumberStringBuilder b) { 20005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert insertPrefix(a.clear(), 0); 20105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert insertSuffix(b.clear(), 0); 20205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (patternInfo.hasCurrencySign()) { 20305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return new CurrencySpacingEnabledModifier(a, b, isStrong, symbols); 20405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 20505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return new ConstantMultiFieldModifier(a, b, isStrong); 20605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 20705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 20805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 20905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public static class ImmutablePatternModifier implements MicroPropsGenerator { 21005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert final ParameterizedModifier pm; 21105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert final PluralRules rules; 21205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert final MicroPropsGenerator parent; 21305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 21405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert ImmutablePatternModifier(ParameterizedModifier pm, PluralRules rules, MicroPropsGenerator parent) { 21505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.pm = pm; 21605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.rules = rules; 21705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.parent = parent; 21805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 21905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 22005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 22105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public MicroProps processQuantity(DecimalQuantity quantity) { 22205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert MicroProps micros = parent.processQuantity(quantity); 22305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert applyToMicros(micros, quantity); 22405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return micros; 22505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 22605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 22705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public void applyToMicros(MicroProps micros, DecimalQuantity quantity) { 22805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (rules == null) { 22905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert micros.modMiddle = pm.getModifier(quantity.isNegative()); 23005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 23105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // TODO: Fix this. Avoid the copy. 23205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert DecimalQuantity copy = quantity.createCopy(); 23305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert copy.roundToInfinity(); 23405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert StandardPlural plural = copy.getStandardPlural(rules); 23505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert micros.modMiddle = pm.getModifier(quantity.isNegative(), plural); 23605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 23705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 23805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 23905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 24005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** Used by the unsafe code path. */ 24105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public MicroPropsGenerator addToChain(MicroPropsGenerator parent) { 24205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert this.parent = parent; 24305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return this; 24405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 24505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 24605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 24705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public MicroProps processQuantity(DecimalQuantity fq) { 24805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert MicroProps micros = parent.processQuantity(fq); 24905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (needsPlurals()) { 25005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // TODO: Fix this. Avoid the copy. 25105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert DecimalQuantity copy = fq.createCopy(); 25205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert micros.rounding.apply(copy); 25305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setNumberProperties(fq.isNegative(), copy.getStandardPlural(rules)); 25405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 25505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert setNumberProperties(fq.isNegative(), null); 25605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 25705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert micros.modMiddle = this; 25805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return micros; 25905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 26005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 26105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 26205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) { 26305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int prefixLen = insertPrefix(output, leftIndex); 26405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int suffixLen = insertSuffix(output, rightIndex + prefixLen); 26505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert CurrencySpacingEnabledModifier.applyCurrencySpacing(output, leftIndex, prefixLen, rightIndex + prefixLen, 26605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert suffixLen, symbols); 26705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return prefixLen + suffixLen; 26805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 26905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 27005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 27105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public int getPrefixLength() { 27205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Enter and exit CharSequence Mode to get the length. 27305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert enterCharSequenceMode(true); 27405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int result = AffixUtils.unescapedCodePointCount(this, this); // prefix length 27505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert exitCharSequenceMode(); 27605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return result; 27705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 27805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 27905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 28005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public int getCodePointCount() { 28105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Enter and exit CharSequence Mode to get the length. 28205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert enterCharSequenceMode(true); 28305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int result = AffixUtils.unescapedCodePointCount(this, this); // prefix length 28405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert exitCharSequenceMode(); 28505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert enterCharSequenceMode(false); 28605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert result += AffixUtils.unescapedCodePointCount(this, this); // suffix length 28705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert exitCharSequenceMode(); 28805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return result; 28905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 29005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 29105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 29205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public boolean isStrong() { 29305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return isStrong; 29405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 29505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 29605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert private int insertPrefix(NumberStringBuilder sb, int position) { 29705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert enterCharSequenceMode(true); 29805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int length = AffixUtils.unescape(this, sb, position, this); 29905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert exitCharSequenceMode(); 30005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return length; 30105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 30205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 30305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert private int insertSuffix(NumberStringBuilder sb, int position) { 30405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert enterCharSequenceMode(false); 30505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert int length = AffixUtils.unescape(this, sb, position, this); 30605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert exitCharSequenceMode(); 30705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return length; 30805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 30905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 31005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** 31105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert * Returns the string that substitutes a given symbol type in a pattern. 31205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert */ 31305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 31405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public CharSequence getSymbol(int type) { 31505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert switch (type) { 31605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_MINUS_SIGN: 31705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return symbols.getMinusSignString(); 31805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_PLUS_SIGN: 31905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return symbols.getPlusSignString(); 32005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_PERCENT: 32105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return symbols.getPercentString(); 32205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_PERMILLE: 32305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return symbols.getPerMillString(); 32405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_CURRENCY_SINGLE: 32505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // UnitWidth ISO, HIDDEN, or NARROW overrides the singular currency symbol. 32605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (unitWidth == UnitWidth.ISO_CODE) { 32705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return currency.getCurrencyCode(); 32805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else if (unitWidth == UnitWidth.HIDDEN) { 32905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return ""; 33005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else if (unitWidth == UnitWidth.NARROW) { 33105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return currency.getName(symbols.getULocale(), Currency.NARROW_SYMBOL_NAME, null); 33205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 33305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, null); 33405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 33505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_CURRENCY_DOUBLE: 33605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return currency.getCurrencyCode(); 33705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_CURRENCY_TRIPLE: 33805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // NOTE: This is the code path only for patterns containing "¤¤¤". 33905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Plural currencies set via the API are formatted in LongNameHandler. 34005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // This code path is used by DecimalFormat via CurrencyPluralInfo. 34105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert plural != null; 34205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME, plural.getKeyword(), null); 34305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_CURRENCY_QUAD: 34405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return "\uFFFD"; 34505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert case AffixUtils.TYPE_CURRENCY_QUINT: 34605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return currency.getName(symbols.getULocale(), Currency.NARROW_SYMBOL_NAME, null); 34705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert default: 34805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert throw new AssertionError(); 34905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 35005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 35105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 35205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert /** This method contains the heart of the logic for rendering LDML affix strings. */ 35305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert private void enterCharSequenceMode(boolean isPrefix) { 35405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert !inCharSequenceMode; 35505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert inCharSequenceMode = true; 35605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 35705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Should the output render '+' where '-' would normally appear in the pattern? 35805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert plusReplacesMinusSign = !isNegative 35905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert && (signDisplay == SignDisplay.ALWAYS || signDisplay == SignDisplay.ACCOUNTING_ALWAYS) 36005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert && patternInfo.positiveHasPlusSign() == false; 36105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 36205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Should we use the affix from the negative subpattern? (If not, we will use the positive subpattern.) 36305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert boolean useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() 36405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert && (isNegative || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); 36505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 36605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Resolve the flags for the affix pattern. 36705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert flags = 0; 36805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (useNegativeAffixPattern) { 36905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert flags |= AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN; 37005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 37105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (isPrefix) { 37205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert flags |= AffixPatternProvider.Flags.PREFIX; 37305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 37405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (plural != null) { 37505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert plural.ordinal() == (AffixPatternProvider.Flags.PLURAL_MASK & plural.ordinal()); 37605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert flags |= plural.ordinal(); 37705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 37805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 37905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Should we prepend a sign to the pattern? 38005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (!isPrefix || useNegativeAffixPattern) { 38105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert prependSign = false; 38205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else if (isNegative) { 38305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert prependSign = signDisplay != SignDisplay.NEVER; 38405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 38505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert prependSign = plusReplacesMinusSign; 38605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 38705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 38805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Finally, compute the length of the affix pattern. 38905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert length = patternInfo.length(flags) + (prependSign ? 1 : 0); 39005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 39105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 39205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert private void exitCharSequenceMode() { 39305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert inCharSequenceMode; 39405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert inCharSequenceMode = false; 39505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 39605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 39705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 39805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public int length() { 39905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert inCharSequenceMode; 40005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return length; 40105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 40205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 40305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 40405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public char charAt(int index) { 40505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert assert inCharSequenceMode; 40605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert char candidate; 40705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (prependSign && index == 0) { 40805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert candidate = '-'; 40905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else if (prependSign) { 41005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert candidate = patternInfo.charAt(flags, index - 1); 41105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } else { 41205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert candidate = patternInfo.charAt(flags, index); 41305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 41405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (plusReplacesMinusSign && candidate == '-') { 41505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return '+'; 41605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 41705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (perMilleReplacesPercent && candidate == '%') { 41805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return '‰'; 41905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 42005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert return candidate; 42105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 42205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert 42305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert @Override 42405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert public CharSequence subSequence(int start, int end) { 42505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert // Never called by AffixUtils 42605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert throw new AssertionError(); 42705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert } 42805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert} 429