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
This commit is contained in:
Markus Scherer 2015-12-16 04:30:48 +00:00
parent 8c6d77a375
commit cab8879780
3 changed files with 80 additions and 42 deletions

View file

@ -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.

View file

@ -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.
*

View file

@ -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;
}
}