Home | History | Annotate | Download | only in text
      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