From: Markus Scherer Date: Wed, 16 Dec 2015 04:30:48 +0000 (+0000) Subject: ICU-12030 move some code to QuantityFormatter so that PluralRules does not depend... X-Git-Tag: milestone-59-0-1~760 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cab887978018c72e904716940fcb152f4404ec7f;p=icu ICU-12030 move some code to QuantityFormatter so that PluralRules does not depend on NumberFormat and to be more parallel with C++ X-SVN-Rev: 38135 --- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java index 482f564af10..cb08f625465 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java @@ -1017,34 +1017,23 @@ public class MeasureFormat extends UFormat { ImmutableNumberFormat nf, StringBuilder appendTo, FieldPosition fieldPosition) { - if (measure.getUnit() instanceof Currency) { + Number n = measure.getNumber(); + MeasureUnit unit = measure.getUnit(); + if (unit instanceof Currency) { return appendTo.append( currencyFormat.format( - new CurrencyAmount(measure.getNumber(), (Currency) measure.getUnit()), + new CurrencyAmount(n, (Currency) unit), new StringBuffer(), fieldPosition)); } - Number n = measure.getNumber(); - MeasureUnit unit = measure.getUnit(); - UFieldPosition fpos = new UFieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField()); - StringBuffer formattedNumber = nf.format(n, new StringBuffer(), fpos); - String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits())); - - int pluralForm = StandardPlural.indexOrOtherIndexFromString(keyword); - SimplePatternFormatter formatter = getPluralFormatter(unit, formatWidth, pluralForm); - int[] offsets = new int[1]; - formatter.formatAndAppend(appendTo, offsets, formattedNumber); - if (offsets[0] != -1) { // there is a number (may not happen with, say, Arabic dual) - // Fix field position - if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { - fieldPosition.setBeginIndex(fpos.getBeginIndex() + offsets[0]); - fieldPosition.setEndIndex(fpos.getEndIndex() + offsets[0]); - } - } - return appendTo; + StringBuffer formattedNumber = new StringBuffer(); + StandardPlural pluralForm = QuantityFormatter.selectPlural( + n, nf.nf, rules, formattedNumber, fieldPosition); + SimplePatternFormatter formatter = getPluralFormatter(unit, formatWidth, pluralForm.ordinal()); + return QuantityFormatter.format(formatter, formattedNumber, appendTo, fieldPosition); } - + /** * Instances contain all MeasureFormat specific data for a particular locale. * This data is cached. It is never copied, but is shared via shared pointers. diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java index 4b3349247b8..495ab5597c9 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java @@ -1954,18 +1954,6 @@ public class PluralRules implements Serializable { return rules.select(number); } - /** - * @internal - * @deprecated This API is ICU internal only. - */ - @Deprecated - public String select(double number, NumberFormat numberFormat) { - if (numberFormat instanceof DecimalFormat) { - return select(((DecimalFormat) numberFormat).getFixedDecimal(number)); - } - return select(number); - } - /** * Given a number information, and keyword, return whether the keyword would match the number. * diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java b/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java index cd5ae87fb9d..99fd38480b0 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java @@ -6,8 +6,11 @@ */ package com.ibm.icu.text; +import java.text.FieldPosition; + import com.ibm.icu.impl.SimplePatternFormatter; import com.ibm.icu.impl.StandardPlural; +import com.ibm.icu.text.PluralRules.FixedDecimal; /** * QuantityFormatter represents an unknown quantity of something and formats a known quantity @@ -49,19 +52,24 @@ class QuantityFormatter { } /** - * Format formats a quantity with this object. - * @param quantity the quantity to be formatted - * @param numberFormat used to actually format the quantity. - * @param pluralRules uses the quantity and the numberFormat to determine what plural + * Format formats a number with this object. + * @param number the number to be formatted + * @param numberFormat used to actually format the number. + * @param pluralRules uses the number and the numberFormat to determine what plural * variant to use for fetching the formatting template. * @return the formatted string e.g '3 apples' */ - public String format(double quantity, NumberFormat numberFormat, PluralRules pluralRules) { - String formatStr = numberFormat.format(quantity); - String variant = pluralRules.select(quantity, numberFormat); - return getByVariant(variant).format(formatStr); + public String format(double number, NumberFormat numberFormat, PluralRules pluralRules) { + String formatStr = numberFormat.format(number); + StandardPlural p = selectPlural(number, numberFormat, pluralRules); + SimplePatternFormatter formatter = templates[p.ordinal()]; + if (formatter == null) { + formatter = templates[StandardPlural.OTHER_INDEX]; + assert formatter != null; + } + return formatter.format(formatStr); } - + /** * Gets the SimplePatternFormatter for a particular variant. * @param variant "zero", "one", "two", "few", "many", "other" @@ -74,4 +82,57 @@ class QuantityFormatter { return (template == null && idx != StandardPlural.OTHER_INDEX) ? templates[StandardPlural.OTHER_INDEX] : template; } + + // The following methods live here so that class PluralRules does not depend on number formatting, + // and the SimplePatternFormatter does not depend on FieldPosition. + + /** + * Selects the standard plural form for the number/formatter/rules. + */ + public static StandardPlural selectPlural(double number, NumberFormat numberFormat, PluralRules rules) { + String pluralKeyword; + if (numberFormat instanceof DecimalFormat) { + pluralKeyword = rules.select(((DecimalFormat) numberFormat).getFixedDecimal(number)); + } else { + pluralKeyword = rules.select(number); + } + return StandardPlural.orOtherFromString(pluralKeyword); + } + + /** + * Selects the standard plural form for the number/formatter/rules. + */ + public static StandardPlural selectPlural( + Number number, NumberFormat fmt, PluralRules rules, + StringBuffer formattedNumber, FieldPosition pos) { + UFieldPosition fpos = new UFieldPosition(pos.getFieldAttribute(), pos.getField()); + fmt.format(number, formattedNumber, fpos); + // TODO: Long, BigDecimal & BigInteger may not fit into doubleValue(). + FixedDecimal fd = new FixedDecimal( + number.doubleValue(), + fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits()); + String pluralKeyword = rules.select(fd); + pos.setBeginIndex(fpos.getBeginIndex()); + pos.setEndIndex(fpos.getEndIndex()); + return StandardPlural.orOtherFromString(pluralKeyword); + } + + /** + * Formats the pattern with the value and adjusts the FieldPosition. + */ + public static StringBuilder format(SimplePatternFormatter pattern, CharSequence value, + StringBuilder appendTo, FieldPosition pos) { + int[] offsets = new int[1]; + pattern.formatAndAppend(appendTo, offsets, value); + if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) { + if (offsets[0] >= 0) { + pos.setBeginIndex(pos.getBeginIndex() + offsets[0]); + pos.setEndIndex(pos.getEndIndex() + offsets[0]); + } else { + pos.setBeginIndex(0); + pos.setEndIndex(0); + } + } + return appendTo; + } }