/* GENERATED SOURCE. DO NOT MODIFY. */ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* * Copyright (C) 1996-2016, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* */ package android.icu.text; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.text.FieldPosition; import java.text.Format; import java.text.ParseException; import java.text.ParsePosition; import java.util.Collections; import java.util.Locale; import java.util.MissingResourceException; import java.util.Set; import android.icu.impl.ICUData; import android.icu.impl.ICUResourceBundle; import android.icu.number.NumberFormatter; import android.icu.util.Currency; import android.icu.util.Currency.CurrencyUsage; import android.icu.util.CurrencyAmount; import android.icu.util.ULocale; import android.icu.util.ULocale.Category; import android.icu.util.UResourceBundle; /** * [icu enhancement] ICU's replacement for {@link java.text.NumberFormat}. Methods, fields, and other functionality specific to ICU are labeled '[icu]'. * *
* IMPORTANT: New users are strongly encouraged to see if * {@link NumberFormatter} fits their use case. Although not deprecated, this * class, NumberFormat, is only provided for java.text.NumberFormat compatibility. *
NumberFormat
is the abstract base class for all number
* formats. This class provides the interface for formatting and parsing
* numbers. NumberFormat
also provides methods for determining
* which locales have number formats, and what their names are.
*
* NumberFormat
helps you to format and parse numbers for any locale.
* Your code can be completely independent of the locale conventions for
* decimal points, thousands-separators, or even the particular decimal
* digits used, or whether the number format is even decimal.
*
* * To format a number for the current Locale, use one of the factory * class methods: *
** If you are formatting multiple numbers, it is * more efficient to get the format and use it multiple times so that * the system doesn't have to fetch the information about the local * language and country conventions multiple times. ** myString = NumberFormat.getInstance().format(myNumber); **
** To format a number for a different Locale, specify it in the * call to* NumberFormat nf = NumberFormat.getInstance(); * for (int i = 0; i < a.length; ++i) { * output.println(nf.format(myNumber[i]) + "; "); * } **
getInstance
.
* ** You can also use a* NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH); **
NumberFormat
to parse numbers:
* ** Use* myNumber = nf.parse(myString); **
getInstance
or getNumberInstance
to get the
* normal number format. Use getIntegerInstance
to get an
* integer number format. Use getCurrencyInstance
to get the
* currency number format. And use getPercentInstance
to get a
* format for displaying percentages. Some factory methods are found within
* subclasses of NumberFormat. With this format, a fraction like
* 0.53 is displayed as 53%.
*
* * Starting from ICU 4.2, you can use getInstance() by passing in a 'style' * as parameter to get the correct instance. * For example, * use getInstance(...NUMBERSTYLE) to get the normal number format, * getInstance(...PERCENTSTYLE) to get a format for displaying percentage, * getInstance(...SCIENTIFICSTYLE) to get a format for displaying scientific number, * getInstance(...INTEGERSTYLE) to get an integer number format, * getInstance(...CURRENCYSTYLE) to get the currency number format, * in which the currency is represented by its symbol, for example, "$3.00". * getInstance(...ISOCURRENCYSTYLE) to get the currency number format, * in which the currency is represented by its ISO code, for example "USD3.00". * getInstance(...PLURALCURRENCYSTYLE) to get the currency number format, * in which the currency is represented by its full name in plural format, * for example, "3.00 US dollars" or "1.00 US dollar". * * *
* You can also control the display of numbers with such methods as
* setMinimumFractionDigits
.
* If you want even more control over the format or parsing,
* or want to give your users more control,
* you can try casting the NumberFormat
you get from the factory methods
* to a DecimalFormat
. This will work for the vast majority
* of locales; just remember to put it in a try
block in case you
* encounter an unusual one.
*
*
* NumberFormat is designed such that some controls * work for formatting and others work for parsing. The following is * the detailed description for each these control methods, *
* setParseIntegerOnly : only affects parsing, e.g. * if true, "3456.78" -> 3456 (and leaves the parse position just after '6') * if false, "3456.78" -> 3456.78 (and leaves the parse position just after '8') * This is independent of formatting. If you want to not show a decimal point * where there might be no digits after the decimal point, use * setDecimalSeparatorAlwaysShown on DecimalFormat. *
* You can also use forms of the parse
and format
* methods with ParsePosition
and FieldPosition
to
* allow you to:
*
FieldPosition
in your format call, with
* field
= INTEGER_FIELD
. On output,
* getEndIndex
will be set to the offset between the
* last character of the integer and the decimal. Add
* (desiredSpaceCount - getEndIndex) spaces at the front of the string.
*
* getEndIndex
.
* Then move the pen by
* (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
* It also works where there is no decimal, but possibly additional
* characters at the end, e.g., with parentheses in negative
* numbers: "(12)" for -12.
* * Number formats are generally not synchronized. It is recommended to create * separate format instances for each thread. If multiple threads access a format * concurrently, it must be synchronized externally. * *
DecimalFormat is the concrete implementation of NumberFormat, and the * NumberFormat API is essentially an abstraction from DecimalFormat's API. * Refer to DecimalFormat for more information about this API.
* * see DecimalFormat * see java.text.ChoiceFormat * @author Mark Davis * @author Helena Shih * @author Alan Liu */ public abstract class NumberFormat extends UFormat { /** * [icu] Constant to specify normal number style of format. */ public static final int NUMBERSTYLE = 0; /** * [icu] Constant to specify general currency style of format. Defaults to * STANDARDCURRENCYSTYLE, using currency symbol, for example "$3.00", with * non-accounting style for negative values (e.g. minus sign). * The specific style may be specified using the -cf- locale key. */ public static final int CURRENCYSTYLE = 1; /** * [icu] Constant to specify a style of format to display percent. */ public static final int PERCENTSTYLE = 2; /** * [icu] Constant to specify a style of format to display scientific number. */ public static final int SCIENTIFICSTYLE = 3; /** * [icu] Constant to specify a integer number style format. */ public static final int INTEGERSTYLE = 4; /** * [icu] Constant to specify currency style of format which uses currency * ISO code to represent currency, for example: "USD3.00". */ public static final int ISOCURRENCYSTYLE = 5; /** * [icu] Constant to specify currency style of format which uses currency * long name with plural format to represent currency, for example, * "3.00 US Dollars". */ public static final int PLURALCURRENCYSTYLE = 6; /** * [icu] Constant to specify currency style of format which uses currency symbol * to represent currency for accounting, for example: "($3.00), instead of * "-$3.00" ({@link #CURRENCYSTYLE}). * Overrides any style specified using -cf- key in locale. */ public static final int ACCOUNTINGCURRENCYSTYLE = 7; /** * [icu] Constant to specify currency cash style of format which uses currency * ISO code to represent currency, for example: "NT$3" instead of "NT$3.23". */ public static final int CASHCURRENCYSTYLE = 8; /** * [icu] Constant to specify currency style of format which uses currency symbol * to represent currency, for example "$3.00", using non-accounting style for * negative values (e.g. minus sign). * Overrides any style specified using -cf- key in locale. */ public static final int STANDARDCURRENCYSTYLE = 9; /** * Field constant used to construct a FieldPosition object. Signifies that * the position of the integer part of a formatted number should be returned. * @see java.text.FieldPosition */ public static final int INTEGER_FIELD = 0; /** * Field constant used to construct a FieldPosition object. Signifies that * the position of the fraction part of a formatted number should be returned. * @see java.text.FieldPosition */ public static final int FRACTION_FIELD = 1; /** * Formats a number and appends the resulting text to the given string buffer. * [icu] Note: recognizesBigInteger
* and BigDecimal
objects.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
@Override
public StringBuffer format(Object number,
StringBuffer toAppendTo,
FieldPosition pos) {
// NOTE: Number type expansion happens both here
// and in DecimalQuantity_DualStorageBCD.java
if (number instanceof Long) {
return format(((Long)number).longValue(), toAppendTo, pos);
} else if (number instanceof BigInteger) {
return format((BigInteger) number, toAppendTo, pos);
} else if (number instanceof java.math.BigDecimal) {
return format((java.math.BigDecimal) number, toAppendTo, pos);
} else if (number instanceof android.icu.math.BigDecimal) {
return format((android.icu.math.BigDecimal) number, toAppendTo, pos);
} else if (number instanceof CurrencyAmount) {
return format((CurrencyAmount)number, toAppendTo, pos);
} else if (number instanceof Number) {
return format(((Number)number).doubleValue(), toAppendTo, pos);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Number");
}
}
/**
* Parses text from a string to produce a number.
* @param source the String to parse
* @param parsePosition the position at which to start the parse
* @return the parsed number, or null
* @see java.text.NumberFormat#parseObject(String, ParsePosition)
*/
@Override
public final Object parseObject(String source,
ParsePosition parsePosition) {
return parse(source, parsePosition);
}
/**
* Specialization of format.
* @see java.text.Format#format(Object)
*/
public final String format(double number) {
return format(number,new StringBuffer(),
new FieldPosition(0)).toString();
}
/**
* Specialization of format.
* @see java.text.Format#format(Object)
*/
public final String format(long number) {
StringBuffer buf = new StringBuffer(19);
FieldPosition pos = new FieldPosition(0);
format(number, buf, pos);
return buf.toString();
}
/**
* [icu] Convenience method to format a BigInteger.
*/
public final String format(BigInteger number) {
return format(number, new StringBuffer(),
new FieldPosition(0)).toString();
}
/**
* Convenience method to format a BigDecimal.
*/
public final String format(java.math.BigDecimal number) {
return format(number, new StringBuffer(),
new FieldPosition(0)).toString();
}
/**
* [icu] Convenience method to format an ICU BigDecimal.
*/
public final String format(android.icu.math.BigDecimal number) {
return format(number, new StringBuffer(),
new FieldPosition(0)).toString();
}
/**
* [icu] Convenience method to format a CurrencyAmount.
*/
public final String format(CurrencyAmount currAmt) {
return format(currAmt, new StringBuffer(),
new FieldPosition(0)).toString();
}
/**
* Specialization of format.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
public abstract StringBuffer format(double number,
StringBuffer toAppendTo,
FieldPosition pos);
/**
* Specialization of format.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
public abstract StringBuffer format(long number,
StringBuffer toAppendTo,
FieldPosition pos);
/**
* [icu] Formats a BigInteger. Specialization of format.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
public abstract StringBuffer format(BigInteger number,
StringBuffer toAppendTo,
FieldPosition pos);
/**
* [icu] Formats a BigDecimal. Specialization of format.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
public abstract StringBuffer format(java.math.BigDecimal number,
StringBuffer toAppendTo,
FieldPosition pos);
/**
* [icu] Formats an ICU BigDecimal. Specialization of format.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
public abstract StringBuffer format(android.icu.math.BigDecimal number,
StringBuffer toAppendTo,
FieldPosition pos);
/**
* [icu] Formats a CurrencyAmount. Specialization of format.
* @see java.text.Format#format(Object, StringBuffer, FieldPosition)
*/
public StringBuffer format(CurrencyAmount currAmt,
StringBuffer toAppendTo,
FieldPosition pos) {
// Default implementation -- subclasses may override
synchronized(this) {
Currency save = getCurrency(), curr = currAmt.getCurrency();
boolean same = curr.equals(save);
if (!same) setCurrency(curr);
format(currAmt.getNumber(), toAppendTo, pos);
if (!same) setCurrency(save);
}
return toAppendTo;
}
/**
* Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
* Long.MAX_VALUE] and with no decimals); otherwise, returns another type,
* such as a BigDecimal, BigInteger, or Double. The return type is not
* guaranteed other than for the Long case.
*
* If IntegerOnly is set, will stop at a decimal * point (or equivalent; e.g., for rational numbers "1 2/3", will stop * after the 1). * *
Does not throw an exception; if no object can be parsed, index is * unchanged! * *
For more detail on parsing, see the "Parsing" header in the class * documentation of {@link DecimalFormat}. * * @see #isParseIntegerOnly * @see DecimalFormat#setParseBigDecimal * @see java.text.Format#parseObject(String, ParsePosition) */ public abstract Number parse(String text, ParsePosition parsePosition); /** * Parses text from the beginning of the given string to produce a number. * The method might not use the entire text of the given string. * * @param text A String whose beginning should be parsed. * @return A Number parsed from the string. * @throws ParseException if the beginning of the specified string * cannot be parsed. * @see #format */ //Bug 4375399 [Richard/GCL] public Number parse(String text) throws ParseException { ParsePosition parsePosition = new ParsePosition(0); Number result = parse(text, parsePosition); if (parsePosition.getIndex() == 0) { throw new ParseException("Unparseable number: \"" + text + '"', parsePosition.getErrorIndex()); } return result; } /** * Parses text from the given string as a CurrencyAmount. Unlike * the parse() method, this method will attempt to parse a generic * currency name, searching for a match of this object's locale's * currency display names, or for a 3-letter ISO currency code. * This method will fail if this format is not a currency format, * that is, if it does not contain the currency pattern symbol * (U+00A4) in its prefix or suffix. * * @param text the text to parse * @param pos input-output position; on input, the position within * text to match; must have 0 <= pos.getIndex() < text.length(); * on output, the position after the last matched character. If * the parse fails, the position in unchanged upon output. * @return a CurrencyAmount, or null upon failure */ public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) { ///CLOVER:OFF // Default implementation only -- subclasses should override Number n = parse(text.toString(), pos); return n == null ? null : new CurrencyAmount(n, getEffectiveCurrency()); ///CLOVER:ON } /** * Returns true if this format will parse numbers as integers only. * For example in the English locale, with ParseIntegerOnly true, the * string "1234." would be parsed as the integer value 1234 and parsing * would stop at the "." character. The decimal separator accepted * by the parse operation is locale-dependent and determined by the * subclass. * * @return true if this will parse integers only */ public boolean isParseIntegerOnly() { return parseIntegerOnly; } /** * Sets whether to ignore the fraction part of a number when parsing * (defaults to false). If a string contains a decimal point, parsing will stop before the decimal * point. Note that determining whether a character is a decimal point depends on the locale. * *
For example, in en-US, parsing the string "123.45" will return the number 123 and * parse position 3. * * @param value true if this should parse integers only * @see #isParseIntegerOnly */ public void setParseIntegerOnly(boolean value) { parseIntegerOnly = value; } /** * [icu] Sets whether strict parsing is in effect. When this is true, the string * is required to be a stronger match to the pattern than when lenient parsing is in * effect. More specifically, the following conditions cause a parse failure relative * to lenient mode (examples use the pattern "#,##0.#"):
FORMAT
locale.
* The default format is one of the styles provided by the other
* factory methods: getNumberInstance, getIntegerInstance,
* getCurrencyInstance or getPercentInstance.
* Exactly which one is locale-dependent.
* @see Category#FORMAT
*/
//Bug 4408066 [Richard/GCL]
public final static NumberFormat getInstance() {
return getInstance(ULocale.getDefault(Category.FORMAT), NUMBERSTYLE);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* FORMAT
locale.
* @param style number format style
* @see Category#FORMAT
*/
public final static NumberFormat getInstance(int style) {
return getInstance(ULocale.getDefault(Category.FORMAT), style);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* FORMAT
locale.
* @see Category#FORMAT
*/
public final static NumberFormat getNumberInstance() {
return getInstance(ULocale.getDefault(Category.FORMAT), NUMBERSTYLE);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* FORMAT
locale. The
* returned number format is configured to round floating point numbers
* to the nearest integer using IEEE half-even rounding (see {@link
* android.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
* and to parse only the integer part of an input string (see {@link
* #isParseIntegerOnly isParseIntegerOnly}).
*
* @return a number format for integer values
* @see Category#FORMAT
*/
//Bug 4408066 [Richard/GCL]
public final static NumberFormat getIntegerInstance() {
return getInstance(ULocale.getDefault(Category.FORMAT), INTEGERSTYLE);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* FORMAT
locale.
* @return a number format for currency
* @see Category#FORMAT
*/
public final static NumberFormat getCurrencyInstance() {
return getInstance(ULocale.getDefault(Category.FORMAT), CURRENCYSTYLE);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* FORMAT
locale.
* @return a number format for percents
* @see Category#FORMAT
*/
public final static NumberFormat getPercentInstance() {
return getInstance(ULocale.getDefault(Category.FORMAT), PERCENTSTYLE);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* FORMAT
locale.
* @return a scientific number format
* @see Category#FORMAT
*/
public final static NumberFormat getScientificInstance() {
return getInstance(ULocale.getDefault(Category.FORMAT), SCIENTIFICSTYLE);
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
* Note: as of ICU4J 3.2, the default API for NumberFormatFactory uses
* ULocale instead of Locale. Instead of overriding createFormat(Locale, int),
* new implementations should override createFactory(ULocale, int). Note that
* one of these two methods MUST be overridden or else an infinite
* loop will occur.
*
* @hide Only a subset of ICU is exposed in Android
* @hide unsupported on Android
*/
public static abstract class NumberFormatFactory {
/**
* Value passed to format requesting a default number format.
*/
public static final int FORMAT_NUMBER = NUMBERSTYLE;
/**
* Value passed to format requesting a currency format.
*/
public static final int FORMAT_CURRENCY = CURRENCYSTYLE;
/**
* Value passed to format requesting a percent format.
*/
public static final int FORMAT_PERCENT = PERCENTSTYLE;
/**
* Value passed to format requesting a scientific format.
*/
public static final int FORMAT_SCIENTIFIC = SCIENTIFICSTYLE;
/**
* Value passed to format requesting an integer format.
*/
public static final int FORMAT_INTEGER = INTEGERSTYLE;
/**
* Returns true if this factory is visible. Default is true.
* If not visible, the locales supported by this factory will not
* be listed by getAvailableLocales. This value must not change.
* @return true if the factory is visible.
*/
public boolean visible() {
return true;
}
/**
* Returns an immutable collection of the locale names directly
* supported by this factory.
* @return the supported locale names.
*/
public abstract Set Because ICU may choose to cache NumberFormat objects internally, this must
* be called at application startup, prior to any calls to
* NumberFormat.getInstance to avoid undefined behavior.
*
* @param factory the factory to register
* @return a key with which to unregister the factory
* @hide unsupported on Android
*/
public static Object registerFactory(NumberFormatFactory factory) {
if (factory == null) {
throw new IllegalArgumentException("factory must not be null");
}
return getShim().registerFactory(factory);
}
/**
* [icu] Unregisters the factory or instance associated with this key (obtained from
* registerInstance or registerFactory).
* @param registryKey a key obtained from registerFactory
* @return true if the object was successfully unregistered
* @hide unsupported on Android
*/
public static boolean unregister(Object registryKey) {
if (registryKey == null) {
throw new IllegalArgumentException("registryKey must not be null");
}
if (shim == null) {
return false;
}
return shim.unregister(registryKey);
}
// ===== End of factory stuff =====
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return maximumIntegerDigits * 37 + maxFractionDigits;
// just enough fields for a reasonable distribution
}
/**
* Overrides equals.
* Two NumberFormats are equal they are of the same class
* and the user-specified values for settings
* (groupingUsed, parseIntegerOnly, maximumIntegerDigits, etc.)
* are equal.
* @param obj the object to compare against
* @return true if the object is equal to this.
*/
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
NumberFormat other = (NumberFormat) obj;
return maximumIntegerDigits == other.maximumIntegerDigits
&& minimumIntegerDigits == other.minimumIntegerDigits
&& maximumFractionDigits == other.maximumFractionDigits
&& minimumFractionDigits == other.minimumFractionDigits
&& groupingUsed == other.groupingUsed
&& parseIntegerOnly == other.parseIntegerOnly
&& parseStrict == other.parseStrict
&& capitalizationSetting == other.capitalizationSetting;
}
/**
* Overrides clone.
*/
@Override
public Object clone() {
NumberFormat other = (NumberFormat) super.clone();
return other;
}
/**
* Returns true if grouping is used in this format. For example, in the
* en_US locale, with grouping on, the number 1234567 will be formatted
* as "1,234,567". The grouping separator as well as the size of each group
* is locale-dependent and is determined by subclasses of NumberFormat.
* Grouping affects both parsing and formatting.
* @return true if grouping is used
* @see #setGroupingUsed
*/
public boolean isGroupingUsed() {
return groupingUsed;
}
/**
* Sets whether or not grouping will be used in this format. Grouping
* affects both parsing and formatting.
* @see #isGroupingUsed
* @param newValue true to use grouping.
*/
public void setGroupingUsed(boolean newValue) {
groupingUsed = newValue;
}
/**
* Returns the maximum number of digits allowed in the integer portion of a
* number. The default value is 40, which subclasses can override.
*
* When formatting, if the number of digits exceeds this value, the highest-
* significance digits are truncated until the limit is reached, in accordance
* with UTS#35.
*
* This setting has no effect on parsing.
*
* @return the maximum number of integer digits
* @see #setMaximumIntegerDigits
*/
public int getMaximumIntegerDigits() {
return maximumIntegerDigits;
}
/**
* Sets the maximum number of digits allowed in the integer portion of a
* number. This must be >= minimumIntegerDigits. If the
* new value for maximumIntegerDigits is less than the current value
* of minimumIntegerDigits, then minimumIntegerDigits will also be set to
* the new value.
* @param newValue the maximum number of integer digits to be shown; if
* less than zero, then zero is used. Subclasses might enforce an
* upper limit to this value appropriate to the numeric type being formatted.
* @see #getMaximumIntegerDigits
*/
public void setMaximumIntegerDigits(int newValue) {
maximumIntegerDigits = Math.max(0,newValue);
if (minimumIntegerDigits > maximumIntegerDigits)
minimumIntegerDigits = maximumIntegerDigits;
}
/**
* Returns the minimum number of digits allowed in the integer portion of a
* number. The default value is 1, which subclasses can override.
* When formatting, if this value is not reached, numbers are padded on the
* left with the locale-specific '0' character to ensure at least this
* number of integer digits. When parsing, this has no effect.
* @return the minimum number of integer digits
* @see #setMinimumIntegerDigits
*/
public int getMinimumIntegerDigits() {
return minimumIntegerDigits;
}
/**
* Sets the minimum number of digits allowed in the integer portion of a
* number. This must be <= maximumIntegerDigits. If the
* new value for minimumIntegerDigits is more than the current value
* of maximumIntegerDigits, then maximumIntegerDigits will also be set to
* the new value.
* @param newValue the minimum number of integer digits to be shown; if
* less than zero, then zero is used. Subclasses might enforce an
* upper limit to this value appropriate to the numeric type being formatted.
* @see #getMinimumIntegerDigits
*/
public void setMinimumIntegerDigits(int newValue) {
minimumIntegerDigits = Math.max(0,newValue);
if (minimumIntegerDigits > maximumIntegerDigits)
maximumIntegerDigits = minimumIntegerDigits;
}
/**
* Returns the maximum number of digits allowed in the fraction
* portion of a number. The default value is 3, which subclasses
* can override. When formatting, the exact behavior when this
* value is exceeded is subclass-specific. When parsing, this has
* no effect.
* @return the maximum number of fraction digits
* @see #setMaximumFractionDigits
*/
public int getMaximumFractionDigits() {
return maximumFractionDigits;
}
/**
* Sets the maximum number of digits allowed in the fraction portion of a
* number. This must be >= minimumFractionDigits. If the
* new value for maximumFractionDigits is less than the current value
* of minimumFractionDigits, then minimumFractionDigits will also be set to
* the new value.
* @param newValue the maximum number of fraction digits to be shown; if
* less than zero, then zero is used. The concrete subclass may enforce an
* upper limit to this value appropriate to the numeric type being formatted.
* @see #getMaximumFractionDigits
*/
public void setMaximumFractionDigits(int newValue) {
maximumFractionDigits = Math.max(0,newValue);
if (maximumFractionDigits < minimumFractionDigits)
minimumFractionDigits = maximumFractionDigits;
}
/**
* Returns the minimum number of digits allowed in the fraction portion of a
* number. The default value is 0, which subclasses can override.
* When formatting, if this value is not reached, numbers are padded on
* the right with the locale-specific '0' character to ensure at least
* this number of fraction digits. When parsing, this has no effect.
* @return the minimum number of fraction digits
* @see #setMinimumFractionDigits
*/
public int getMinimumFractionDigits() {
return minimumFractionDigits;
}
/**
* Sets the minimum number of digits allowed in the fraction portion of a
* number. This must be <= maximumFractionDigits. If the
* new value for minimumFractionDigits exceeds the current value
* of maximumFractionDigits, then maximumFractionDigits will also be set to
* the new value.
* @param newValue the minimum number of fraction digits to be shown; if
* less than zero, then zero is used. Subclasses might enforce an
* upper limit to this value appropriate to the numeric type being formatted.
* @see #getMinimumFractionDigits
*/
public void setMinimumFractionDigits(int newValue) {
minimumFractionDigits = Math.max(0,newValue);
if (maximumFractionDigits < minimumFractionDigits)
maximumFractionDigits = minimumFractionDigits;
}
/**
* Sets the Currency object used to display currency
* amounts. This takes effect immediately, if this format is a
* currency format. If this format is not a currency format, then
* the currency object is used if and when this object becomes a
* currency format.
* @param theCurrency new currency object to use. May be null for
* some subclasses.
*/
public void setCurrency(Currency theCurrency) {
currency = theCurrency;
}
/**
* Returns the Currency object used to display currency
* amounts. This may be null.
*/
public Currency getCurrency() {
return currency;
}
/**
* Returns the currency in effect for this formatter. Subclasses
* should override this method as needed. Unlike getCurrency(),
* this method should never return null.
* @return a non-null Currency
* @deprecated This API is ICU internal only.
* @hide original deprecated declaration
* @hide draft / provisional / internal are hidden on Android
*/
@Deprecated
protected Currency getEffectiveCurrency() {
Currency c = getCurrency();
if (c == null) {
ULocale uloc = getLocale(ULocale.VALID_LOCALE);
if (uloc == null) {
uloc = ULocale.getDefault(Category.FORMAT);
}
c = Currency.getInstance(uloc);
}
return c;
}
/**
* Returns the rounding mode used in this NumberFormat. The default implementation of
* tis method in NumberFormat always throws
* Note: This field exists only for serialization
* compatibility with JDK 1.1. In JDK 1.2 and higher, the new
*
* Note: This field exists only for serialization
* compatibility with JDK 1.1. In JDK 1.2 and higher, the new
*
* Note: This field exists only for serialization
* compatibility with JDK 1.1. In JDK 1.2 and higher, the new
*
* Note: This field exists only for serialization
* compatibility with JDK 1.1. In JDK 1.2 and higher, the new
*
* There is no public constructor to this class, the only instances are the
* constants defined here.
*
*/
public static class Field extends Format.Field {
// generated by serialver from JDK 1.4.1_01
static final long serialVersionUID = -4516273749929385842L;
/**
*/
public static final Field SIGN = new Field("sign");
/**
*/
public static final Field INTEGER = new Field("integer");
/**
*/
public static final Field FRACTION = new Field("fraction");
/**
*/
public static final Field EXPONENT = new Field("exponent");
/**
*/
public static final Field EXPONENT_SIGN = new Field("exponent sign");
/**
*/
public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
/**
*/
public static final Field DECIMAL_SEPARATOR = new Field("decimal separator");
/**
*/
public static final Field GROUPING_SEPARATOR = new Field("grouping separator");
/**
*/
public static final Field PERCENT = new Field("percent");
/**
*/
public static final Field PERMILLE = new Field("per mille");
/**
*/
public static final Field CURRENCY = new Field("currency");
/**
*/
public static final Field MEASURE_UNIT = new Field("measure unit");
/**
*/
public static final Field COMPACT = new Field("compact");
/**
* Approximately sign. In ICU 70, this was categorized under the generic SIGN field.
*/
@android.annotation.FlaggedApi(com.android.icu.Flags.FLAG_ICU_V_API)
public static final Field APPROXIMATELY_SIGN = new Field("approximately sign");
/**
* Constructs a new instance of NumberFormat.Field with the given field
* name.
*/
protected Field(String fieldName) {
super(fieldName);
}
/**
* serizalization method resolve instances to the constant
* NumberFormat.Field values
*/
@Override
protected Object readResolve() throws InvalidObjectException {
if (this.getName().equals(INTEGER.getName()))
return INTEGER;
if (this.getName().equals(FRACTION.getName()))
return FRACTION;
if (this.getName().equals(EXPONENT.getName()))
return EXPONENT;
if (this.getName().equals(EXPONENT_SIGN.getName()))
return EXPONENT_SIGN;
if (this.getName().equals(EXPONENT_SYMBOL.getName()))
return EXPONENT_SYMBOL;
if (this.getName().equals(CURRENCY.getName()))
return CURRENCY;
if (this.getName().equals(DECIMAL_SEPARATOR.getName()))
return DECIMAL_SEPARATOR;
if (this.getName().equals(GROUPING_SEPARATOR.getName()))
return GROUPING_SEPARATOR;
if (this.getName().equals(PERCENT.getName()))
return PERCENT;
if (this.getName().equals(PERMILLE.getName()))
return PERMILLE;
if (this.getName().equals(SIGN.getName()))
return SIGN;
if (this.getName().equals(MEASURE_UNIT.getName()))
return MEASURE_UNIT;
if (this.getName().equals(COMPACT.getName()))
return COMPACT;
throw new InvalidObjectException("An invalid object.");
}
}
}
UnsupportedOperationException
.
* @return A rounding mode, between BigDecimal.ROUND_UP
* and BigDecimal.ROUND_UNNECESSARY
.
* @see #setRoundingMode(int)
*/
public int getRoundingMode() {
throw new UnsupportedOperationException(
"getRoundingMode must be implemented by the subclass implementation.");
}
/**
* Set the rounding mode used in this NumberFormat. The default implementation of
* tis method in NumberFormat always throws UnsupportedOperationException
.
* @param roundingMode A rounding mode, between
* BigDecimal.ROUND_UP
and
* BigDecimal.ROUND_UNNECESSARY
.
* @see #getRoundingMode()
*/
public void setRoundingMode(int roundingMode) {
throw new UnsupportedOperationException(
"setRoundingMode must be implemented by the subclass implementation.");
}
/**
* NOTE: New users are strongly encouraged to use
* {@link NumberFormatter} instead of NumberFormat.
*
* Returns a specific style number format for a specific locale.
* @param desiredLocale the specific locale.
* @param choice number format style
* @throws IllegalArgumentException if choice is not one of
* NUMBERSTYLE, CURRENCYSTYLE,
* PERCENTSTYLE, SCIENTIFICSTYLE,
* INTEGERSTYLE, ISOCURRENCYSTYLE,
* PLURALCURRENCYSTYLE, ACCOUNTINGCURRENCYSTYLE.
* CASHCURRENCYSTYLE, STANDARDCURRENCYSTYLE.
*/
public static NumberFormat getInstance(ULocale desiredLocale, int choice) {
if (choice < NUMBERSTYLE || choice > STANDARDCURRENCYSTYLE) {
throw new IllegalArgumentException(
"choice should be from NUMBERSTYLE to STANDARDCURRENCYSTYLE");
}
// if (shim == null) {
// return createInstance(desiredLocale, choice);
// } else {
// // TODO: shims must call setLocale() on object they create
// return getShim().createInstance(desiredLocale, choice);
// }
return getShim().createInstance(desiredLocale, choice);
}
// =======================privates===============================
// Hook for service
static NumberFormat createInstance(ULocale desiredLocale, int choice) {
// If the choice is PLURALCURRENCYSTYLE, the pattern is not a single
// pattern, it is a pattern set, so we do not need to get them here.
// If the choice is ISOCURRENCYSTYLE, the pattern is the currency
// pattern in the locale but by replacing the single currency sign
// with double currency sign.
String pattern = getPattern(desiredLocale, choice);
DecimalFormatSymbols symbols = new DecimalFormatSymbols(desiredLocale);
// Here we assume that the locale passed in is in the canonical
// form, e.g: pt_PT_@currency=PTE
// For currency plural format, the pattern is get from
// the locale (from CurrencyUnitPatterns) without override.
if (choice == CURRENCYSTYLE || choice == ISOCURRENCYSTYLE || choice == ACCOUNTINGCURRENCYSTYLE
|| choice == CASHCURRENCYSTYLE || choice == STANDARDCURRENCYSTYLE) {
String temp = symbols.getCurrencyPattern();
if(temp!=null){
pattern = temp;
}
}
// replace single currency sign in the pattern with double currency sign
// if the choice is ISOCURRENCYSTYLE.
if (choice == ISOCURRENCYSTYLE) {
pattern = pattern.replace("\u00A4", doubleCurrencyStr);
}
// Get the numbering system
NumberingSystem ns = NumberingSystem.getInstance(desiredLocale);
if ( ns == null ) {
return null;
}
NumberFormat format;
if ( ns != null && ns.isAlgorithmic()) {
String nsDesc;
String nsRuleSetGroup;
String nsRuleSetName;
ULocale nsLoc;
int desiredRulesType = RuleBasedNumberFormat.NUMBERING_SYSTEM;
nsDesc = ns.getDescription();
int firstSlash = nsDesc.indexOf("/");
int lastSlash = nsDesc.lastIndexOf("/");
if ( lastSlash > firstSlash ) {
String nsLocID = nsDesc.substring(0,firstSlash);
nsRuleSetGroup = nsDesc.substring(firstSlash+1,lastSlash);
nsRuleSetName = nsDesc.substring(lastSlash+1);
nsLoc = new ULocale(nsLocID);
if ( nsRuleSetGroup.equals("SpelloutRules")) {
desiredRulesType = RuleBasedNumberFormat.SPELLOUT;
}
} else {
nsLoc = desiredLocale;
nsRuleSetName = nsDesc;
}
RuleBasedNumberFormat r = new RuleBasedNumberFormat(nsLoc,desiredRulesType);
r.setDefaultRuleSet(nsRuleSetName);
format = r;
} else {
DecimalFormat f = new DecimalFormat(pattern, symbols, choice);
// System.out.println("loc: " + desiredLocale + " choice: " + choice + " pat: " + pattern + " sym: " + symbols + " result: " + format);
/*Bug 4408066
Add codes for the new method getIntegerInstance() [Richard/GCL]
*/
// TODO: revisit this -- this is almost certainly not the way we want
// to do this. aliu 1/6/2004
if (choice == INTEGERSTYLE) {
f.setMaximumFractionDigits(0);
f.setDecimalSeparatorAlwaysShown(false);
f.setParseIntegerOnly(true);
}
if (choice == CASHCURRENCYSTYLE) {
f.setCurrencyUsage(CurrencyUsage.CASH);
}
if (choice == PLURALCURRENCYSTYLE) {
f.setCurrencyPluralInfo(CurrencyPluralInfo.getInstance(desiredLocale));
}
format = f;
}
// TODO: the actual locale of the *pattern* may differ from that
// for the *symbols*. For now, we use the data for the symbols.
// Revisit this.
ULocale valid = symbols.getLocale(ULocale.VALID_LOCALE);
ULocale actual = symbols.getLocale(ULocale.ACTUAL_LOCALE);
format.setLocale(valid, actual);
return format;
}
/**
* Returns the pattern for the provided locale and choice.
* @param forLocale the locale of the data.
* @param choice the pattern format.
* @return the pattern
* @deprecated ICU 3.4 subclassers should override getPattern(ULocale, int) instead of this method.
* @hide original deprecated declaration
*/
@Deprecated
protected static String getPattern(Locale forLocale, int choice) {
return getPattern(ULocale.forLocale(forLocale), choice);
}
/**
* Returns the pattern for the provided locale and choice.
* @param forLocale the locale of the data.
* @param choice the pattern format.
* @return the pattern
*/
protected static String getPattern(ULocale forLocale, int choice) {
return getPatternForStyle(forLocale, choice);
}
/**
* Returns the pattern for the provided locale and choice.
* @param forLocale the locale of the data.
* @param choice the pattern format.
* @return the pattern
* @deprecated This API is ICU internal only.
* @hide draft / provisional / internal are hidden on Android
*/
@Deprecated
public static String getPatternForStyle(ULocale forLocale, int choice) {
NumberingSystem ns = NumberingSystem.getInstance(forLocale);
String nsName = ns.getName();
return getPatternForStyleAndNumberingSystem(forLocale, nsName, choice);
}
/**
* Returns the pattern for the provided locale, numbering system, and choice.
* @param forLocale the locale of the data.
* @param nsName The name of the numbering system, like "latn".
* @param choice the pattern format.
* @return the pattern
* @deprecated This API is ICU internal only.
* @hide draft / provisional / internal are hidden on Android
*/
@Deprecated
public static String getPatternForStyleAndNumberingSystem(ULocale forLocale, String nsName, int choice) {
/* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
* the pattern is the same as the pattern of CURRENCYSTYLE
* but by replacing the single currency sign with
* double currency sign or triple currency sign.
*/
String patternKey = null;
switch (choice) {
case NUMBERSTYLE:
case INTEGERSTYLE:
case PLURALCURRENCYSTYLE:
patternKey = "decimalFormat";
break;
case CURRENCYSTYLE:
String cfKeyValue = forLocale.getKeywordValue("cf");
patternKey = (cfKeyValue != null && cfKeyValue.equals("account")) ?
"accountingFormat" : "currencyFormat";
break;
case CASHCURRENCYSTYLE:
case ISOCURRENCYSTYLE:
case STANDARDCURRENCYSTYLE:
patternKey = "currencyFormat";
break;
case PERCENTSTYLE:
patternKey = "percentFormat";
break;
case SCIENTIFICSTYLE:
patternKey = "scientificFormat";
break;
case ACCOUNTINGCURRENCYSTYLE:
patternKey = "accountingFormat";
break;
default:
assert false;
patternKey = "decimalFormat";
break;
}
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.
getBundleInstance(ICUData.ICU_BASE_NAME, forLocale);
String result = rb.findStringWithFallback(
"NumberElements/" + nsName + "/patterns/" + patternKey);
if (result == null) {
result = rb.getStringWithFallback("NumberElements/latn/patterns/" + patternKey);
}
return result;
}
/**
* First, read in the default serializable data.
*
* Then, if serialVersionOnStream
is less than 1, indicating that
* the stream was written by JDK 1.1,
* set the int
fields such as maximumIntegerDigits
* to be equal to the byte
fields such as maxIntegerDigits
,
* since the int
fields were not present in JDK 1.1.
* Finally, set serialVersionOnStream back to the maximum allowed value so that
* default serialization will work properly if this object is streamed out again.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
///CLOVER:OFF
// we don't have serialization data for this format
if (serialVersionOnStream < 1) {
// Didn't have additional int fields, reassign to use them.
maximumIntegerDigits = maxIntegerDigits;
minimumIntegerDigits = minIntegerDigits;
maximumFractionDigits = maxFractionDigits;
minimumFractionDigits = minFractionDigits;
}
if (serialVersionOnStream < 2) {
// Didn't have capitalizationSetting, set it to default
capitalizationSetting = DisplayContext.CAPITALIZATION_NONE;
}
///CLOVER:ON
/*Bug 4185761
Validate the min and max fields [Richard/GCL]
*/
if (minimumIntegerDigits > maximumIntegerDigits ||
minimumFractionDigits > maximumFractionDigits ||
minimumIntegerDigits < 0 || minimumFractionDigits < 0) {
throw new InvalidObjectException("Digit count range invalid");
}
serialVersionOnStream = currentSerialVersion;
}
/**
* Write out the default serializable data, after first setting
* the byte
fields such as maxIntegerDigits
to be
* equal to the int
fields such as maximumIntegerDigits
* (or to Byte.MAX_VALUE
, whichever is smaller), for compatibility
* with the JDK 1.1 version of the stream format.
*/
private void writeObject(ObjectOutputStream stream)
throws IOException
{
maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
(byte)maximumIntegerDigits;
minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
(byte)minimumIntegerDigits;
maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
(byte)maximumFractionDigits;
minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
(byte)minimumFractionDigits;
stream.defaultWriteObject();
}
// Unused -- Alan 2003-05
// /**
// * Cache to hold the NumberPatterns of a Locale.
// */
// private static final Hashtable cachedLocaleData = new Hashtable(3);
private static final char[] doubleCurrencySign = {0xA4, 0xA4};
private static final String doubleCurrencyStr = new String(doubleCurrencySign);
/*Bug 4408066
Add Field for the new method getIntegerInstance() [Richard/GCL]
*/
/**
* True if the the grouping (i.e. thousands) separator is used when
* formatting and parsing numbers.
*
* @serial
* @see #isGroupingUsed
*/
private boolean groupingUsed = true;
/**
* The maximum number of digits allowed in the integer portion of a
* number. maxIntegerDigits
must be greater than or equal to
* minIntegerDigits
.
* int
field maximumIntegerDigits
is used instead.
* When writing to a stream, maxIntegerDigits
is set to
* maximumIntegerDigits
or Byte.MAX_VALUE
,
* whichever is smaller. When reading from a stream, this field is used
* only if serialVersionOnStream
is less than 1.
*
* @serial
* @see #getMaximumIntegerDigits
*/
private byte maxIntegerDigits = 40;
/**
* The minimum number of digits allowed in the integer portion of a
* number. minimumIntegerDigits
must be less than or equal to
* maximumIntegerDigits
.
* int
field minimumIntegerDigits
is used instead.
* When writing to a stream, minIntegerDigits
is set to
* minimumIntegerDigits
or Byte.MAX_VALUE
,
* whichever is smaller. When reading from a stream, this field is used
* only if serialVersionOnStream
is less than 1.
*
* @serial
* @see #getMinimumIntegerDigits
*/
private byte minIntegerDigits = 1;
/**
* The maximum number of digits allowed in the fractional portion of a
* number. maximumFractionDigits
must be greater than or equal to
* minimumFractionDigits
.
* int
field maximumFractionDigits
is used instead.
* When writing to a stream, maxFractionDigits
is set to
* maximumFractionDigits
or Byte.MAX_VALUE
,
* whichever is smaller. When reading from a stream, this field is used
* only if serialVersionOnStream
is less than 1.
*
* @serial
* @see #getMaximumFractionDigits
*/
private byte maxFractionDigits = 3; // invariant, >= minFractionDigits
/**
* The minimum number of digits allowed in the fractional portion of a
* number. minimumFractionDigits
must be less than or equal to
* maximumFractionDigits
.
* int
field minimumFractionDigits
is used instead.
* When writing to a stream, minFractionDigits
is set to
* minimumFractionDigits
or Byte.MAX_VALUE
,
* whichever is smaller. When reading from a stream, this field is used
* only if serialVersionOnStream
is less than 1.
*
* @serial
* @see #getMinimumFractionDigits
*/
private byte minFractionDigits = 0;
/**
* True if this format will parse numbers as integers only.
*
* @serial
* @see #isParseIntegerOnly
*/
private boolean parseIntegerOnly = false;
// new fields for 1.2. byte is too small for integer digits.
/**
* The maximum number of digits allowed in the integer portion of a
* number. maximumIntegerDigits
must be greater than or equal to
* minimumIntegerDigits
.
*
* @serial
* @see #getMaximumIntegerDigits
*/
private int maximumIntegerDigits = 40;
/**
* The minimum number of digits allowed in the integer portion of a
* number. minimumIntegerDigits
must be less than or equal to
* maximumIntegerDigits
.
*
* @serial
* @see #getMinimumIntegerDigits
*/
private int minimumIntegerDigits = 1;
/**
* The maximum number of digits allowed in the fractional portion of a
* number. maximumFractionDigits
must be greater than or equal to
* minimumFractionDigits
.
*
* @serial
* @see #getMaximumFractionDigits
*/
private int maximumFractionDigits = 3; // invariant, >= minFractionDigits
/**
* The minimum number of digits allowed in the fractional portion of a
* number. minimumFractionDigits
must be less than or equal to
* maximumFractionDigits
.
*
* @serial
* @see #getMinimumFractionDigits
*/
private int minimumFractionDigits = 0;
/**
* Currency object used to format currencies. Subclasses may
* ignore this if they are not currency formats. This will be
* null unless a subclass sets it to a non-null value.
*/
private Currency currency;
static final int currentSerialVersion = 2;
/**
* Describes the version of NumberFormat
present on the stream.
* Possible values are:
*
*
* When streaming out a int
fields such as
* maximumIntegerDigits
were not present, and the byte
* fields such as maxIntegerDigits
are used instead.
*
* byte
fields such as maxIntegerDigits
are ignored,
* and the int
fields such as maximumIntegerDigits
* are used instead.
*
* NumberFormat
, the most recent format
* (corresponding to the highest allowable serialVersionOnStream
)
* is always written.
*
* @serial
*/
private int serialVersionOnStream = currentSerialVersion;
// Removed "implements Cloneable" clause. Needs to update serialization
// ID for backward compatibility.
private static final long serialVersionUID = -2308460125733713944L;
/**
* Empty constructor. Public for API compatibility with historic versions of
* {@link java.text.NumberFormat} which had public constructor even though this is
* an abstract class.
*/
public NumberFormat() {
}
// new in ICU4J 3.6
private boolean parseStrict;
/*
* Capitalization context setting, new in ICU 53
* @serial
*/
private DisplayContext capitalizationSetting = DisplayContext.CAPITALIZATION_NONE;
/**
* The instances of this inner class are used as attribute keys and values
* in AttributedCharacterIterator that
* NumberFormat.formatToCharacterIterator() method returns.
*