1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2013-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package android.icu.text; 11 12 import java.text.FieldPosition; 13 14 import android.icu.impl.SimpleFormatterImpl; 15 import android.icu.impl.StandardPlural; 16 import android.icu.text.PluralRules.FixedDecimal; 17 18 /** 19 * QuantityFormatter represents an unknown quantity of something and formats a known quantity 20 * in terms of that something. For example, a QuantityFormatter that represents X apples may 21 * format 1 as "1 apple" and 3 as "3 apples" 22 * <p> 23 * QuanitityFormatter appears here instead of in android.icu.impl because it depends on 24 * PluralRules and DecimalFormat. It is package-protected as it is not meant for public use. 25 */ 26 class QuantityFormatter { 27 private final SimpleFormatter[] templates = 28 new SimpleFormatter[StandardPlural.COUNT]; 29 30 public QuantityFormatter() {} 31 32 /** 33 * Adds a template if there is none yet for the plural form. 34 * 35 * @param variant the plural variant, e.g "zero", "one", "two", "few", "many", "other" 36 * @param template the text for that plural variant with "{0}" as the quantity. For 37 * example, in English, the template for the "one" variant may be "{0} apple" while the 38 * template for the "other" variant may be "{0} apples" 39 * @throws IllegalArgumentException if variant is not recognized or 40 * if template has more than just the {0} placeholder. 41 */ 42 public void addIfAbsent(CharSequence variant, String template) { 43 int idx = StandardPlural.indexFromString(variant); 44 if (templates[idx] != null) { 45 return; 46 } 47 templates[idx] = SimpleFormatter.compileMinMaxArguments(template, 0, 1); 48 } 49 50 /** 51 * @return true if this object has at least the "other" variant 52 */ 53 public boolean isValid() { 54 return templates[StandardPlural.OTHER_INDEX] != null; 55 } 56 57 /** 58 * Format formats a number with this object. 59 * @param number the number to be formatted 60 * @param numberFormat used to actually format the number. 61 * @param pluralRules uses the number and the numberFormat to determine what plural 62 * variant to use for fetching the formatting template. 63 * @return the formatted string e.g '3 apples' 64 */ 65 public String format(double number, NumberFormat numberFormat, PluralRules pluralRules) { 66 String formatStr = numberFormat.format(number); 67 StandardPlural p = selectPlural(number, numberFormat, pluralRules); 68 SimpleFormatter formatter = templates[p.ordinal()]; 69 if (formatter == null) { 70 formatter = templates[StandardPlural.OTHER_INDEX]; 71 assert formatter != null; 72 } 73 return formatter.format(formatStr); 74 } 75 76 /** 77 * Gets the SimpleFormatter for a particular variant. 78 * @param variant "zero", "one", "two", "few", "many", "other" 79 * @return the SimpleFormatter 80 */ 81 public SimpleFormatter getByVariant(CharSequence variant) { 82 assert isValid(); 83 int idx = StandardPlural.indexOrOtherIndexFromString(variant); 84 SimpleFormatter template = templates[idx]; 85 return (template == null && idx != StandardPlural.OTHER_INDEX) ? 86 templates[StandardPlural.OTHER_INDEX] : template; 87 } 88 89 // The following methods live here so that class PluralRules does not depend on number formatting, 90 // and the SimpleFormatter does not depend on FieldPosition. 91 92 /** 93 * Selects the standard plural form for the number/formatter/rules. 94 */ 95 public static StandardPlural selectPlural(double number, NumberFormat numberFormat, PluralRules rules) { 96 String pluralKeyword; 97 if (numberFormat instanceof DecimalFormat) { 98 pluralKeyword = rules.select(((DecimalFormat) numberFormat).getFixedDecimal(number)); 99 } else { 100 pluralKeyword = rules.select(number); 101 } 102 return StandardPlural.orOtherFromString(pluralKeyword); 103 } 104 105 /** 106 * Selects the standard plural form for the number/formatter/rules. 107 */ 108 public static StandardPlural selectPlural( 109 Number number, NumberFormat fmt, PluralRules rules, 110 StringBuffer formattedNumber, FieldPosition pos) { 111 UFieldPosition fpos = new UFieldPosition(pos.getFieldAttribute(), pos.getField()); 112 fmt.format(number, formattedNumber, fpos); 113 // TODO: Long, BigDecimal & BigInteger may not fit into doubleValue(). 114 FixedDecimal fd = new FixedDecimal( 115 number.doubleValue(), 116 fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits()); 117 String pluralKeyword = rules.select(fd); 118 pos.setBeginIndex(fpos.getBeginIndex()); 119 pos.setEndIndex(fpos.getEndIndex()); 120 return StandardPlural.orOtherFromString(pluralKeyword); 121 } 122 123 /** 124 * Formats the pattern with the value and adjusts the FieldPosition. 125 */ 126 public static StringBuilder format(String compiledPattern, CharSequence value, 127 StringBuilder appendTo, FieldPosition pos) { 128 int[] offsets = new int[1]; 129 SimpleFormatterImpl.formatAndAppend(compiledPattern, appendTo, offsets, value); 130 if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) { 131 if (offsets[0] >= 0) { 132 pos.setBeginIndex(pos.getBeginIndex() + offsets[0]); 133 pos.setEndIndex(pos.getEndIndex() + offsets[0]); 134 } else { 135 pos.setBeginIndex(0); 136 pos.setEndIndex(0); 137 } 138 } 139 return appendTo; 140 } 141 } 142