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 android.icu.impl.number; 5 6 import java.util.EnumMap; 7 import java.util.Map; 8 9 import android.icu.impl.CurrencyData; 10 import android.icu.impl.ICUData; 11 import android.icu.impl.ICUResourceBundle; 12 import android.icu.impl.SimpleFormatterImpl; 13 import android.icu.impl.StandardPlural; 14 import android.icu.impl.UResource; 15 import android.icu.number.NumberFormatter.UnitWidth; 16 import android.icu.text.NumberFormat; 17 import android.icu.text.PluralRules; 18 import android.icu.util.Currency; 19 import android.icu.util.ICUException; 20 import android.icu.util.MeasureUnit; 21 import android.icu.util.ULocale; 22 import android.icu.util.UResourceBundle; 23 24 /** 25 * @hide Only a subset of ICU is exposed in Android 26 */ 27 public class LongNameHandler implements MicroPropsGenerator { 28 29 ////////////////////////// 30 /// BEGIN DATA LOADING /// 31 ////////////////////////// 32 33 private static final class PluralTableSink extends UResource.Sink { 34 35 Map<StandardPlural, String> output; 36 37 public PluralTableSink(Map<StandardPlural, String> output) { 38 this.output = output; 39 } 40 41 @Override 42 public void put(UResource.Key key, UResource.Value value, boolean noFallback) { 43 UResource.Table pluralsTable = value.getTable(); 44 for (int i = 0; pluralsTable.getKeyAndValue(i, key, value); ++i) { 45 if (key.contentEquals("dnam") || key.contentEquals("per")) { 46 continue; 47 } 48 StandardPlural plural = StandardPlural.fromString(key); 49 if (output.containsKey(plural)) { 50 continue; 51 } 52 String formatString = value.getString(); 53 output.put(plural, formatString); 54 } 55 } 56 } 57 58 private static void getMeasureData(ULocale locale, MeasureUnit unit, UnitWidth width, 59 Map<StandardPlural, String> output) { 60 PluralTableSink sink = new PluralTableSink(output); 61 ICUResourceBundle resource; 62 resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale); 63 StringBuilder key = new StringBuilder(); 64 key.append("units"); 65 if (width == UnitWidth.NARROW) { 66 key.append("Narrow"); 67 } else if (width == UnitWidth.SHORT) { 68 key.append("Short"); 69 } 70 key.append("/"); 71 key.append(unit.getType()); 72 key.append("/"); 73 key.append(unit.getSubtype()); 74 resource.getAllItemsWithFallback(key.toString(), sink); 75 } 76 77 private static void getCurrencyLongNameData(ULocale locale, Currency currency, Map<StandardPlural, String> output) { 78 // In ICU4J, this method gets a CurrencyData from CurrencyData.provider. 79 // TODO(ICU4J): Implement this without going through CurrencyData, like in ICU4C? 80 Map<String, String> data = CurrencyData.provider.getInstance(locale, true).getUnitPatterns(); 81 for (Map.Entry<String, String> e : data.entrySet()) { 82 String pluralKeyword = e.getKey(); 83 StandardPlural plural = StandardPlural.fromString(e.getKey()); 84 String longName = currency.getName(locale, Currency.PLURAL_LONG_NAME, pluralKeyword, null); 85 String simpleFormat = e.getValue(); 86 // Example pattern from data: "{0} {1}" 87 // Example output after find-and-replace: "{0} US dollars" 88 simpleFormat = simpleFormat.replace("{1}", longName); 89 // String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 1, 1); 90 // SimpleModifier mod = new SimpleModifier(compiled, Field.CURRENCY, false); 91 output.put(plural, simpleFormat); 92 } 93 } 94 95 //////////////////////// 96 /// END DATA LOADING /// 97 //////////////////////// 98 99 private final Map<StandardPlural, SimpleModifier> modifiers; 100 private final PluralRules rules; 101 private final MicroPropsGenerator parent; 102 103 private LongNameHandler(Map<StandardPlural, SimpleModifier> modifiers, PluralRules rules, 104 MicroPropsGenerator parent) { 105 this.modifiers = modifiers; 106 this.rules = rules; 107 this.parent = parent; 108 } 109 110 public static LongNameHandler forCurrencyLongNames(ULocale locale, Currency currency, PluralRules rules, 111 MicroPropsGenerator parent) { 112 Map<StandardPlural, String> simpleFormats = new EnumMap<StandardPlural, String>(StandardPlural.class); 113 getCurrencyLongNameData(locale, currency, simpleFormats); 114 // TODO(ICU4J): Reduce the number of object creations here? 115 Map<StandardPlural, SimpleModifier> modifiers = new EnumMap<StandardPlural, SimpleModifier>( 116 StandardPlural.class); 117 simpleFormatsToModifiers(simpleFormats, null, modifiers); 118 return new LongNameHandler(modifiers, rules, parent); 119 } 120 121 public static LongNameHandler forMeasureUnit(ULocale locale, MeasureUnit unit, UnitWidth width, PluralRules rules, 122 MicroPropsGenerator parent) { 123 Map<StandardPlural, String> simpleFormats = new EnumMap<StandardPlural, String>(StandardPlural.class); 124 getMeasureData(locale, unit, width, simpleFormats); 125 // TODO: What field to use for units? 126 // TODO(ICU4J): Reduce the number of object creations here? 127 Map<StandardPlural, SimpleModifier> modifiers = new EnumMap<StandardPlural, SimpleModifier>( 128 StandardPlural.class); 129 simpleFormatsToModifiers(simpleFormats, null, modifiers); 130 return new LongNameHandler(modifiers, rules, parent); 131 } 132 133 private static void simpleFormatsToModifiers(Map<StandardPlural, String> simpleFormats, NumberFormat.Field field, 134 Map<StandardPlural, SimpleModifier> output) { 135 StringBuilder sb = new StringBuilder(); 136 for (StandardPlural plural : StandardPlural.VALUES) { 137 String simpleFormat = simpleFormats.get(plural); 138 if (simpleFormat == null) { 139 simpleFormat = simpleFormats.get(StandardPlural.OTHER); 140 } 141 if (simpleFormat == null) { 142 // There should always be data in the "other" plural variant. 143 throw new ICUException("Could not find data in 'other' plural variant with field " + field); 144 } 145 String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 1, 1); 146 output.put(plural, new SimpleModifier(compiled, null, false)); 147 } 148 } 149 150 @Override 151 public MicroProps processQuantity(DecimalQuantity quantity) { 152 MicroProps micros = parent.processQuantity(quantity); 153 // TODO: Avoid the copy here? 154 DecimalQuantity copy = quantity.createCopy(); 155 micros.rounding.apply(copy); 156 micros.modOuter = modifiers.get(copy.getStandardPlural(rules)); 157 return micros; 158 } 159 } 160