Index: icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java
===================================================================
--- icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java (revision 39589)
+++ icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java (working copy)
@@ -18,559 +18,228 @@
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.ParsePosition;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Pattern;
-import com.ibm.icu.text.CompactDecimalDataCache.Data;
-import com.ibm.icu.text.PluralRules.FixedDecimal;
-import com.ibm.icu.util.Currency;
-import com.ibm.icu.util.CurrencyAmount;
-import com.ibm.icu.util.Output;
+import com.ibm.icu.impl.number.FormatQuantity4;
+import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.util.ULocale;
/**
- * The CompactDecimalFormat produces abbreviated numbers, suitable for display in environments will limited real estate.
- * For example, 'Hits: 1.2B' instead of 'Hits: 1,200,000,000'. The format will be appropriate for the given language,
- * such as "1,2 Mrd." for German.
- *
- * For numbers under 1000 trillion (under 10^15, such as 123,456,789,012,345), the result will be short for supported
- * languages. However, the result may sometimes exceed 7 characters, such as when there are combining marks or thin
- * characters. In such cases, the visual width in fonts should still be short.
- *
- * By default, there are 2 significant digits. After creation, if more than three significant digits are set (with
- * setMaximumSignificantDigits), or if a fixed number of digits are set (with setMaximumIntegerDigits or
- * setMaximumFractionDigits), then result may be wider.
- *
- * The "short" style is also capable of formatting currency amounts, such as "$1.2M" instead of "$1,200,000.00" (English) or
- * "5,3 Mio. €" instead of "5.300.000,00 €" (German). Localized data concerning longer formats is not available yet in
- * the Unicode CLDR. Because of this, attempting to format a currency amount using the "long" style will produce
- * an UnsupportedOperationException.
+ * The CompactDecimalFormat produces abbreviated numbers, suitable for display in environments will
+ * limited real estate. For example, 'Hits: 1.2B' instead of 'Hits: 1,200,000,000'. The format will
+ * be appropriate for the given language, such as "1,2 Mrd." for German.
*
- * At this time, negative numbers and parsing are not supported, and will produce an UnsupportedOperationException.
- * Resetting the pattern prefixes or suffixes is not supported; the method calls are ignored.
- *
- * Note that important methods, like setting the number of decimals, will be moved up from DecimalFormat to
- * NumberFormat.
+ *
For numbers under 1000 trillion (under 10^15, such as 123,456,789,012,345), the result will be
+ * short for supported languages. However, the result may sometimes exceed 7 characters, such as
+ * when there are combining marks or thin characters. In such cases, the visual width in fonts
+ * should still be short.
*
+ *
By default, there are 2 significant digits. After creation, if more than three significant
+ * digits are set (with setMaximumSignificantDigits), or if a fixed number of digits are set (with
+ * setMaximumIntegerDigits or setMaximumFractionDigits), then result may be wider.
+ *
+ *
The "short" style is also capable of formatting currency amounts, such as "$1.2M" instead of
+ * "$1,200,000.00" (English) or "5,3 Mio. €" instead of "5.300.000,00 €" (German). Localized data
+ * concerning longer formats is not available yet in the Unicode CLDR. Because of this, attempting
+ * to format a currency amount using the "long" style will produce an UnsupportedOperationException.
+ *
+ *
At this time, negative numbers and parsing are not supported, and will produce an
+ * UnsupportedOperationException. Resetting the pattern prefixes or suffixes is not supported; the
+ * method calls are ignored.
+ *
+ *
Note that important methods, like setting the number of decimals, will be moved up from
+ * DecimalFormat to NumberFormat.
+ *
* @author markdavis
* @stable ICU 49
*/
public class CompactDecimalFormat extends DecimalFormat {
- private static final long serialVersionUID = 4716293295276629682L;
-
-// private static final int POSITIVE_PREFIX = 0, POSITIVE_SUFFIX = 1, AFFIX_SIZE = 2;
- private static final CompactDecimalDataCache cache = new CompactDecimalDataCache();
-
- private final Map units;
- private final Map currencyUnits;
- private final long[] divisor;
- private final long[] currencyDivisor;
- private final Map pluralToCurrencyAffixes;
- private CompactStyle style;
-
- // null if created internally using explicit prefixes and suffixes.
- private final PluralRules pluralRules;
-
+ /**
+ * Style parameter for CompactDecimalFormat.
+ *
+ * @stable ICU 50
+ */
+ public enum CompactStyle {
/**
- * Style parameter for CompactDecimalFormat.
- * @stable ICU 50
- */
- public enum CompactStyle {
- /**
- * Short version, like "1.2T"
- * @stable ICU 50
- */
- SHORT,
- /**
- * Longer version, like "1.2 trillion", if available. May return same result as SHORT if not.
- * @stable ICU 50
- */
- LONG
- }
-
- /**
- * Create a CompactDecimalFormat appropriate for a locale. The result may
- * be affected by the number system in the locale, such as ar-u-nu-latn.
+ * Short version, like "1.2T"
*
- * @param locale the desired locale
- * @param style the compact style
* @stable ICU 50
*/
- public static CompactDecimalFormat getInstance(ULocale locale, CompactStyle style) {
- return new CompactDecimalFormat(locale, style);
- }
-
+ SHORT,
/**
- * Create a CompactDecimalFormat appropriate for a locale. The result may
- * be affected by the number system in the locale, such as ar-u-nu-latn.
+ * Longer version, like "1.2 trillion", if available. May return same result as SHORT if not.
*
- * @param locale the desired locale
- * @param style the compact style
* @stable ICU 50
*/
- public static CompactDecimalFormat getInstance(Locale locale, CompactStyle style) {
- return new CompactDecimalFormat(ULocale.forLocale(locale), style);
- }
+ LONG
+ }
- /**
- * The public mechanism is CompactDecimalFormat.getInstance().
- *
- * @param locale
- * the desired locale
- * @param style
- * the compact style
- */
- CompactDecimalFormat(ULocale locale, CompactStyle style) {
- this.pluralRules = PluralRules.forLocale(locale);
- DecimalFormat format = (DecimalFormat) NumberFormat.getInstance(locale);
- CompactDecimalDataCache.Data data = getData(locale, style);
- CompactDecimalDataCache.Data currencyData = getCurrencyData(locale);
- this.units = data.units;
- this.divisor = data.divisors;
- this.currencyUnits = currencyData.units;
- this.currencyDivisor = currencyData.divisors;
- this.style = style;
- pluralToCurrencyAffixes = null;
+ /**
+ * Create a CompactDecimalFormat appropriate for a locale. The result may be affected by the
+ * number system in the locale, such as ar-u-nu-latn.
+ *
+ * @param locale the desired locale
+ * @param style the compact style
+ * @stable ICU 50
+ */
+ public static CompactDecimalFormat getInstance(ULocale locale, CompactStyle style) {
+ return new CompactDecimalFormat(locale, style);
+ }
-// DecimalFormat currencyFormat = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
-// // TODO fix to use plural-dependent affixes
-// Unit currency = new Unit(currencyFormat.getPositivePrefix(), currencyFormat.getPositiveSuffix());
-// pluralToCurrencyAffixes = new HashMap();
-// for (String key : pluralRules.getKeywords()) {
-// pluralToCurrencyAffixes.put(key, currency);
-// }
-// // TODO fix to get right symbol for the count
+ /**
+ * Create a CompactDecimalFormat appropriate for a locale. The result may be affected by the
+ * number system in the locale, such as ar-u-nu-latn.
+ *
+ * @param locale the desired locale
+ * @param style the compact style
+ * @stable ICU 50
+ */
+ public static CompactDecimalFormat getInstance(Locale locale, CompactStyle style) {
+ return new CompactDecimalFormat(ULocale.forLocale(locale), style);
+ }
- finishInit(style, format.toPattern(), format.getDecimalFormatSymbols());
+ /**
+ * The public mechanism is CompactDecimalFormat.getInstance().
+ *
+ * @param locale the desired locale
+ * @param style the compact style
+ */
+ CompactDecimalFormat(ULocale locale, CompactStyle style) {
+ // Use the locale's default pattern
+ String pattern = getPattern(locale, 0);
+ symbols = DecimalFormatSymbols.getInstance(locale);
+ properties = new Properties();
+ properties.setCompactStyle(style);
+ exportedProperties = new Properties();
+ setPropertiesFromPattern(pattern, true);
+ if (style == CompactStyle.SHORT) {
+ // TODO: This was setGroupingUsed(false) in ICU 58. Is it okay that I changed it for ICU 59?
+ properties.setMinimumGroupingDigits(2);
}
+ refreshFormatter();
+ }
- /**
- * Create a short number "from scratch". Intended for internal use. The prefix, suffix, and divisor arrays are
- * parallel, and provide the information for each power of 10. When formatting a value, the correct power of 10 is
- * found, then the value is divided by the divisor, and the prefix and suffix are set (using
- * setPositivePrefix/Suffix).
- *
- * @param pattern
- * A number format pattern. Note that the prefix and suffix are discarded, and the decimals are
- * overridden by default.
- * @param formatSymbols
- * Decimal format symbols, typically from a locale.
- * @param style
- * compact style.
- * @param divisor
- * An array of prefix values, one for each power of 10 from 0 to 14
- * @param pluralAffixes
- * A map from plural categories to affixes.
- * @param currencyAffixes
- * A map from plural categories to currency affixes.
- * @param debugCreationErrors
- * A collection of strings for debugging. If null on input, then any errors found will be added to that
- * collection instead of throwing exceptions.
- * @internal
- * @deprecated This API is ICU internal only.
- */
- @Deprecated
- public CompactDecimalFormat(String pattern, DecimalFormatSymbols formatSymbols,
- CompactStyle style, PluralRules pluralRules,
- long[] divisor, Map pluralAffixes, Map currencyAffixes,
- Collection debugCreationErrors) {
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
+ }
- this.pluralRules = pluralRules;
- this.units = otherPluralVariant(pluralAffixes, divisor, debugCreationErrors);
- this.currencyUnits = otherPluralVariant(pluralAffixes, divisor, debugCreationErrors);
- if (!pluralRules.getKeywords().equals(this.units.keySet())) {
- debugCreationErrors.add("Missmatch in pluralCategories, should be: " + pluralRules.getKeywords() + ", was actually " + this.units.keySet());
- }
- this.divisor = divisor.clone();
- this.currencyDivisor = divisor.clone();
- if (currencyAffixes == null) {
- pluralToCurrencyAffixes = null;
- } else {
- pluralToCurrencyAffixes = new HashMap();
- for (Entry s : currencyAffixes.entrySet()) {
- String[] pair = s.getValue();
- pluralToCurrencyAffixes.put(s.getKey(), new Unit(pair[0], pair[1]));
- }
- }
- finishInit(style, pattern, formatSymbols);
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
+ FormatQuantity4 fq = new FormatQuantity4(number);
+ formatter.format(fq, toAppendTo, pos);
+ fq.populateUFieldPosition(pos);
+ return toAppendTo;
+ }
- private void finishInit(CompactStyle style, String pattern, DecimalFormatSymbols formatSymbols) {
- applyPattern(pattern);
- setDecimalFormatSymbols(formatSymbols);
- setMaximumSignificantDigits(2); // default significant digits
- setSignificantDigitsUsed(true);
- if (style == CompactStyle.SHORT) {
- setGroupingUsed(false);
- }
- setCurrency(null);
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 50
+ */
+ @Override
+ public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
+ if (!(obj instanceof Number)) throw new IllegalArgumentException();
+ Number number = (Number) obj;
+ FormatQuantity4 fq = new FormatQuantity4(number);
+ AttributedCharacterIterator result = formatter.formatToCharacterIterator(fq);
+ return result;
+ }
- /**
- * {@inheritDoc}
- * @stable ICU 49
- */
- @Override
- public boolean equals(Object obj) {
- if (obj == null)
- return false;
- if (!super.equals(obj))
- return false; // super does class check
- CompactDecimalFormat other = (CompactDecimalFormat) obj;
- return mapsAreEqual(units, other.units)
- && Arrays.equals(divisor, other.divisor)
- && (pluralToCurrencyAffixes == other.pluralToCurrencyAffixes
- || pluralToCurrencyAffixes != null && pluralToCurrencyAffixes.equals(other.pluralToCurrencyAffixes))
- && pluralRules.equals(other.pluralRules);
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
+ FormatQuantity4 fq = new FormatQuantity4(number);
+ formatter.format(fq, toAppendTo, pos);
+ fq.populateUFieldPosition(pos);
+ return toAppendTo;
+ }
- private boolean mapsAreEqual(
- Map lhs, Map rhs) {
- if (lhs.size() != rhs.size()) {
- return false;
- }
- // For each MapEntry in lhs, see if there is a matching one in rhs.
- for (Map.Entry entry : lhs.entrySet()) {
- DecimalFormat.Unit[] value = rhs.get(entry.getKey());
- if (value == null || !Arrays.equals(entry.getValue(), value)) {
- return false;
- }
- }
- return true;
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
+ FormatQuantity4 fq = new FormatQuantity4(number);
+ formatter.format(fq, toAppendTo, pos);
+ fq.populateUFieldPosition(pos);
+ return toAppendTo;
+ }
- /**
- * {@inheritDoc}
- * @stable ICU 49
- */
- @Override
- public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
- return format(number, null, toAppendTo, pos);
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
+ FormatQuantity4 fq = new FormatQuantity4(number);
+ formatter.format(fq, toAppendTo, pos);
+ fq.populateUFieldPosition(pos);
+ return toAppendTo;
+ }
- /**
- * {@inheritDoc}
- * @stable ICU 50
- */
- @Override
- public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
- if (!(obj instanceof Number)) {
- throw new IllegalArgumentException();
- }
- Number number = (Number) obj;
- Amount amount = toAmount(number.doubleValue(), null, null);
- return super.formatToCharacterIterator(amount.getQty(), amount.getUnit());
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public StringBuffer format(
+ com.ibm.icu.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
+ FormatQuantity4 fq = new FormatQuantity4(number.toBigDecimal());
+ formatter.format(fq, toAppendTo, pos);
+ fq.populateUFieldPosition(pos);
+ return toAppendTo;
+ }
- /**
- * {@inheritDoc}
- * @stable ICU 49
- */
- @Override
- public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
- return format((double) number, toAppendTo, pos);
- }
+// /**
+// * {@inheritDoc}
+// *
+// * @internal ICU 57 technology preview
+// * @deprecated This API might change or be removed in a future release.
+// */
+// @Override
+// @Deprecated
+// public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
+// // TODO(sffc)
+// throw new UnsupportedOperationException();
+// }
- /**
- * {@inheritDoc}
- * @stable ICU 49
- */
- @Override
- public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
- return format(number.doubleValue(), toAppendTo, pos);
- }
+ /**
+ * Parsing is currently unsupported, and throws an UnsupportedOperationException.
+ *
+ * @stable ICU 49
+ */
+ @Override
+ public Number parse(String text, ParsePosition parsePosition) {
+ throw new UnsupportedOperationException();
+ }
- /**
- * {@inheritDoc}
- * @stable ICU 49
- */
- @Override
- public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
- return format(number.doubleValue(), toAppendTo, pos);
- }
+ // DISALLOW Serialization, at least while draft
- /**
- * {@inheritDoc}
- * @stable ICU 49
- */
- @Override
- public StringBuffer format(com.ibm.icu.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
- return format(number.doubleValue(), toAppendTo, pos);
- }
- /**
- * {@inheritDoc}
- * @internal ICU 57 technology preview
- * @deprecated This API might change or be removed in a future release.
- */
- @Override
- @Deprecated
- public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
- return format(currAmt.getNumber().doubleValue(), currAmt.getCurrency(), toAppendTo, pos);
- }
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ throw new NotSerializableException();
+ }
- /**
- * Parsing is currently unsupported, and throws an UnsupportedOperationException.
- * @stable ICU 49
- */
- @Override
- public Number parse(String text, ParsePosition parsePosition) {
- throw new UnsupportedOperationException();
- }
-
- // DISALLOW Serialization, at least while draft
-
- private void writeObject(ObjectOutputStream out) throws IOException {
- throw new NotSerializableException();
- }
-
- private void readObject(ObjectInputStream in) throws IOException {
- throw new NotSerializableException();
- }
-
- /* INTERNALS */
- private StringBuffer format(double number, Currency curr, StringBuffer toAppendTo, FieldPosition pos) {
- if (curr != null && style == CompactStyle.LONG) {
- throw new UnsupportedOperationException("CompactDecimalFormat does not support LONG style for currency.");
- }
-
- // Compute the scaled amount, prefix, and suffix appropriate for the number's magnitude.
- Output currencyUnit = new Output();
- Amount amount = toAmount(number, curr, currencyUnit);
- Unit unit = amount.getUnit();
-
- // Note that currencyUnit is a remnant. In almost all cases, it will be null.
- StringBuffer prefix = new StringBuffer();
- StringBuffer suffix = new StringBuffer();
- if (currencyUnit.value != null) {
- currencyUnit.value.writePrefix(prefix);
- }
- unit.writePrefix(prefix);
- unit.writeSuffix(suffix);
- if (currencyUnit.value != null) {
- currencyUnit.value.writeSuffix(suffix);
- }
-
- if (curr == null) {
- // Prevent locking when not formatting a currency number.
- toAppendTo.append(escape(prefix.toString()));
- super.format(amount.getQty(), toAppendTo, pos);
- toAppendTo.append(escape(suffix.toString()));
-
- } else {
- // To perform the formatting, we set this DecimalFormat's pattern to have the correct prefix, suffix,
- // and currency, and then reset it back to what it was before.
- // This has to be synchronized since this information is held in the state of the DecimalFormat object.
- synchronized(this) {
-
- String originalPattern = this.toPattern();
- Currency originalCurrency = this.getCurrency();
- StringBuffer newPattern = new StringBuffer();
-
- // Write prefixes and suffixes to the pattern. Note that we have to apply it to both halves of a
- // positive/negative format (separated by ';')
- int semicolonPos = originalPattern.indexOf(';');
- newPattern.append(prefix);
- if (semicolonPos != -1) {
- newPattern.append(originalPattern, 0, semicolonPos);
- newPattern.append(suffix);
- newPattern.append(';');
- newPattern.append(prefix);
- }
- newPattern.append(originalPattern, semicolonPos + 1, originalPattern.length());
- newPattern.append(suffix);
-
- // Overwrite the pattern and currency.
- setCurrency(curr);
- applyPattern(newPattern.toString());
-
- // Actually perform the formatting.
- super.format(amount.getQty(), toAppendTo, pos);
-
- // Reset the pattern and currency.
- setCurrency(originalCurrency);
- applyPattern(originalPattern);
- }
- }
- return toAppendTo;
- }
-
- private static final Pattern UNESCAPE_QUOTE = Pattern.compile("((?= 0) {
- return UNESCAPE_QUOTE.matcher(string).replaceAll("$1");
- }
- return string;
- }
-
- private Amount toAmount(double number, Currency curr, Output currencyUnit) {
- // We do this here so that the prefix or suffix we choose is always consistent
- // with the rounding we do. This way, 999999 -> 1M instead of 1000K.
- boolean negative = isNumberNegative(number);
- number = adjustNumberAsInFormatting(number);
- int base = number <= 1.0d ? 0 : (int) Math.log10(number);
- if (base >= CompactDecimalDataCache.MAX_DIGITS) {
- base = CompactDecimalDataCache.MAX_DIGITS - 1;
- }
- if (curr != null) {
- number /= currencyDivisor[base];
- } else {
- number /= divisor[base];
- }
- String pluralVariant = getPluralForm(getFixedDecimal(number, toDigitList(number)));
- if (pluralToCurrencyAffixes != null && currencyUnit != null) {
- currencyUnit.value = pluralToCurrencyAffixes.get(pluralVariant);
- }
- if (negative) {
- number = -number;
- }
- if ( curr != null ) {
- return new Amount(number, CompactDecimalDataCache.getUnit(currencyUnits, pluralVariant, base));
- } else {
- return new Amount(number, CompactDecimalDataCache.getUnit(units, pluralVariant, base));
- }
- }
-
- private void recordError(Collection creationErrors, String errorMessage) {
- if (creationErrors == null) {
- throw new IllegalArgumentException(errorMessage);
- }
- creationErrors.add(errorMessage);
- }
-
- /**
- * Manufacture the unit list from arrays
- */
- private Map otherPluralVariant(Map pluralCategoryToPower10ToAffix,
- long[] divisor, Collection debugCreationErrors) {
-
- // check for bad divisors
- if (divisor.length < CompactDecimalDataCache.MAX_DIGITS) {
- recordError(debugCreationErrors, "Must have at least " + CompactDecimalDataCache.MAX_DIGITS + " prefix items.");
- }
- long oldDivisor = 0;
- for (int i = 0; i < divisor.length; ++i) {
-
- // divisor must be a power of 10, and must be less than or equal to 10^i
- int log = (int) Math.log10(divisor[i]);
- if (log > i) {
- recordError(debugCreationErrors, "Divisor[" + i + "] must be less than or equal to 10^" + i
- + ", but is: " + divisor[i]);
- }
- long roundTrip = (long) Math.pow(10.0d, log);
- if (roundTrip != divisor[i]) {
- recordError(debugCreationErrors, "Divisor[" + i + "] must be a power of 10, but is: " + divisor[i]);
- }
-
- if (divisor[i] < oldDivisor) {
- recordError(debugCreationErrors, "Bad divisor, the divisor for 10E" + i + "(" + divisor[i]
- + ") is less than the divisor for the divisor for 10E" + (i - 1) + "(" + oldDivisor + ")");
- }
- oldDivisor = divisor[i];
- }
-
- Map result = new HashMap();
- Map seen = new HashMap();
-
- String[][] defaultPower10ToAffix = pluralCategoryToPower10ToAffix.get("other");
-
- for (Entry pluralCategoryAndPower10ToAffix : pluralCategoryToPower10ToAffix.entrySet()) {
- String pluralCategory = pluralCategoryAndPower10ToAffix.getKey();
- String[][] power10ToAffix = pluralCategoryAndPower10ToAffix.getValue();
-
- // we can't have one of the arrays be of different length
- if (power10ToAffix.length != divisor.length) {
- recordError(debugCreationErrors, "Prefixes & suffixes must be present for all divisors " + pluralCategory);
- }
- DecimalFormat.Unit[] units = new DecimalFormat.Unit[power10ToAffix.length];
- for (int i = 0; i < power10ToAffix.length; i++) {
- String[] pair = power10ToAffix[i];
- if (pair == null) {
- pair = defaultPower10ToAffix[i];
- }
-
- // we can't have bad pair
- if (pair.length != 2 || pair[0] == null || pair[1] == null) {
- recordError(debugCreationErrors, "Prefix or suffix is null for " + pluralCategory + ", " + i + ", " + Arrays.asList(pair));
- continue;
- }
-
- // we can't have two different indexes with the same display
- int log = (int) Math.log10(divisor[i]);
- String key = pair[0] + "\uFFFF" + pair[1] + "\uFFFF" + (i - log);
- Integer old = seen.get(key);
- if (old == null) {
- seen.put(key, i);
- } else if (old != i) {
- recordError(debugCreationErrors, "Collision between values for " + i + " and " + old
- + " for [prefix/suffix/index-log(divisor)" + key.replace('\uFFFF', ';'));
- }
-
- units[i] = new Unit(pair[0], pair[1]);
- }
- result.put(pluralCategory, units);
- }
- return result;
- }
-
- private String getPluralForm(FixedDecimal fixedDecimal) {
- if (pluralRules == null) {
- return CompactDecimalDataCache.OTHER;
- }
- return pluralRules.select(fixedDecimal);
- }
-
- /**
- * Gets the data for a particular locale and style. If style is unrecognized,
- * we just return data for CompactStyle.SHORT.
- * @param locale The locale.
- * @param style The style.
- * @return The data which must not be modified.
- */
- private Data getData(ULocale locale, CompactStyle style) {
- CompactDecimalDataCache.DataBundle bundle = cache.get(locale);
- switch (style) {
- case SHORT:
- return bundle.shortData;
- case LONG:
- return bundle.longData;
- default:
- return bundle.shortData;
- }
- }
- /**
- * Gets the currency data for a particular locale.
- * Currently only short currency format is supported, since that is
- * the only form in CLDR.
- * @param locale The locale.
- * @return The data which must not be modified.
- */
- private Data getCurrencyData(ULocale locale) {
- CompactDecimalDataCache.DataBundle bundle = cache.get(locale);
- return bundle.shortCurrencyData;
- }
-
- private static class Amount {
- private final double qty;
- private final Unit unit;
-
- public Amount(double qty, Unit unit) {
- this.qty = qty;
- this.unit = unit;
- }
-
- public double getQty() {
- return qty;
- }
-
- public Unit getUnit() {
- return unit;
- }
- }
+ private void readObject(ObjectInputStream in) throws IOException {
+ throw new NotSerializableException();
+ }
}