0001: //##header
0002: /*
0003: *******************************************************************************
0004: * Copyright (C) 1996-2006, International Business Machines Corporation and *
0005: * others. All Rights Reserved. *
0006: *******************************************************************************
0007: */
0008: package com.ibm.icu.text;
0009:
0010: import java.io.IOException;
0011: import java.io.InvalidObjectException;
0012: import java.io.ObjectInputStream;
0013: import java.io.ObjectOutputStream;
0014: import java.math.BigInteger;
0015: import java.text.FieldPosition;
0016: import java.text.Format;
0017: import java.text.ParseException;
0018: import java.text.ParsePosition;
0019: import java.util.Collections;
0020: import java.util.Locale;
0021: import java.util.MissingResourceException;
0022: import java.util.Set;
0023:
0024: import com.ibm.icu.impl.ICUResourceBundle;
0025: import com.ibm.icu.util.Currency;
0026: import com.ibm.icu.util.CurrencyAmount;
0027: import com.ibm.icu.util.ULocale;
0028: import com.ibm.icu.util.UResourceBundle;
0029:
0030: /**
0031: * <code>NumberFormat</code> is the abstract base class for all number
0032: * formats. This class provides the interface for formatting and parsing
0033: * numbers. <code>NumberFormat</code> also provides methods for determining
0034: * which locales have number formats, and what their names are.
0035: *
0036: * <p><strong>This is an enhanced version of <code>NumberFormat</code> that
0037: * is based on the standard version in the JDK. New or changed functionality
0038: * is labeled
0039: * <strong><font face=helvetica color=red>NEW</font></strong> or
0040: * <strong><font face=helvetica color=red>CHANGED</font></strong>.</strong>
0041: *
0042: * <p>
0043: * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
0044: * Your code can be completely independent of the locale conventions for
0045: * decimal points, thousands-separators, or even the particular decimal
0046: * digits used, or whether the number format is even decimal.
0047: *
0048: * <p>
0049: * To format a number for the current Locale, use one of the factory
0050: * class methods:
0051: * <blockquote>
0052: * <pre>
0053: * myString = NumberFormat.getInstance().format(myNumber);
0054: * </pre>
0055: * </blockquote>
0056: * If you are formatting multiple numbers, it is
0057: * more efficient to get the format and use it multiple times so that
0058: * the system doesn't have to fetch the information about the local
0059: * language and country conventions multiple times.
0060: * <blockquote>
0061: * <pre>
0062: * NumberFormat nf = NumberFormat.getInstance();
0063: * for (int i = 0; i < a.length; ++i) {
0064: * output.println(nf.format(myNumber[i]) + "; ");
0065: * }
0066: * </pre>
0067: * </blockquote>
0068: * To format a number for a different Locale, specify it in the
0069: * call to <code>getInstance</code>.
0070: * <blockquote>
0071: * <pre>
0072: * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
0073: * </pre>
0074: * </blockquote>
0075: * You can also use a <code>NumberFormat</code> to parse numbers:
0076: * <blockquote>
0077: * <pre>
0078: * myNumber = nf.parse(myString);
0079: * </pre>
0080: * </blockquote>
0081: * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
0082: * normal number format. Use <code>getIntegerInstance</code> to get an
0083: * integer number format. Use <code>getCurrencyInstance</code> to get the
0084: * currency number format. And use <code>getPercentInstance</code> to get a
0085: * format for displaying percentages. With this format, a fraction like
0086: * 0.53 is displayed as 53%.
0087: *
0088: * <p>
0089: * You can also control the display of numbers with such methods as
0090: * <code>setMinimumFractionDigits</code>.
0091: * If you want even more control over the format or parsing,
0092: * or want to give your users more control,
0093: * you can try casting the <code>NumberFormat</code> you get from the factory methods
0094: * to a <code>DecimalFormat</code>. This will work for the vast majority
0095: * of locales; just remember to put it in a <code>try</code> block in case you
0096: * encounter an unusual one.
0097: *
0098: * <p>
0099: * NumberFormat is designed such that some controls
0100: * work for formatting and others work for parsing. The following is
0101: * the detailed description for each these control methods,
0102: * <p>
0103: * setParseIntegerOnly : only affects parsing, e.g.
0104: * if true, "3456.78" -> 3456 (and leaves the parse position just after '6')
0105: * if false, "3456.78" -> 3456.78 (and leaves the parse position just after '8')
0106: * This is independent of formatting. If you want to not show a decimal point
0107: * where there might be no digits after the decimal point, use
0108: * setDecimalSeparatorAlwaysShown on DecimalFormat.
0109: * <p>
0110: * You can also use forms of the <code>parse</code> and <code>format</code>
0111: * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
0112: * allow you to:
0113: * <ul>
0114: * <li> progressively parse through pieces of a string
0115: * <li> align the decimal point and other areas
0116: * </ul>
0117: * For example, you can align numbers in two ways:
0118: * <ol>
0119: * <li> If you are using a monospaced font with spacing for alignment,
0120: * you can pass the <code>FieldPosition</code> in your format call, with
0121: * <code>field</code> = <code>INTEGER_FIELD</code>. On output,
0122: * <code>getEndIndex</code> will be set to the offset between the
0123: * last character of the integer and the decimal. Add
0124: * (desiredSpaceCount - getEndIndex) spaces at the front of the string.
0125: *
0126: * <li> If you are using proportional fonts,
0127: * instead of padding with spaces, measure the width
0128: * of the string in pixels from the start to <code>getEndIndex</code>.
0129: * Then move the pen by
0130: * (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
0131: * It also works where there is no decimal, but possibly additional
0132: * characters at the end, e.g., with parentheses in negative
0133: * numbers: "(12)" for -12.
0134: * </ol>
0135: *
0136: * <h4>Synchronization</h4>
0137: * <p>
0138: * Number formats are generally not synchronized. It is recommended to create
0139: * separate format instances for each thread. If multiple threads access a format
0140: * concurrently, it must be synchronized externally.
0141: * <p>
0142: *
0143: * <h4>DecimalFormat</h4>
0144: * <p>DecimalFormat is the concrete implementation of NumberFormat, and the
0145: * NumberFormat API is essentially an abstraction from DecimalFormat's API.
0146: * Refer to DecimalFormat for more information about this API.</p>
0147: *
0148: * see DecimalFormat
0149: * see java.text.ChoiceFormat
0150: * @author Mark Davis
0151: * @author Helena Shih
0152: * @author Alan Liu
0153: * @stable ICU 2.0
0154: */
0155: public abstract class NumberFormat extends UFormat {
0156:
0157: // Constants used by factory methods to specify a style of format.
0158: private static final int NUMBERSTYLE = 0;
0159: private static final int CURRENCYSTYLE = 1;
0160: private static final int PERCENTSTYLE = 2;
0161: private static final int SCIENTIFICSTYLE = 3;
0162: private static final int INTEGERSTYLE = 4;
0163:
0164: /**
0165: * Field constant used to construct a FieldPosition object. Signifies that
0166: * the position of the integer part of a formatted number should be returned.
0167: * @see java.text.FieldPosition
0168: * @stable ICU 2.0
0169: */
0170: public static final int INTEGER_FIELD = 0;
0171:
0172: /**
0173: * Field constant used to construct a FieldPosition object. Signifies that
0174: * the position of the fraction part of a formatted number should be returned.
0175: * @see java.text.FieldPosition
0176: * @stable ICU 2.0
0177: */
0178: public static final int FRACTION_FIELD = 1;
0179:
0180: /**
0181: * <strong><font face=helvetica color=red>CHANGED</font></strong>
0182: * Format an object. Change: recognizes <code>BigInteger</code>
0183: * and <code>BigDecimal</code> objects.
0184: * @stable ICU 2.0
0185: */
0186: public StringBuffer format(Object number, StringBuffer toAppendTo,
0187: FieldPosition pos) {
0188: if (number instanceof Long) {
0189: return format(((Long) number).longValue(), toAppendTo, pos);
0190: } else if (number instanceof BigInteger) {
0191: return format((BigInteger) number, toAppendTo, pos);
0192: //#ifndef FOUNDATION
0193: } else if (number instanceof java.math.BigDecimal) {
0194: return format((java.math.BigDecimal) number, toAppendTo,
0195: pos);
0196: //#endif
0197: } else if (number instanceof com.ibm.icu.math.BigDecimal) {
0198: return format((com.ibm.icu.math.BigDecimal) number,
0199: toAppendTo, pos);
0200: } else if (number instanceof CurrencyAmount) {
0201: return format((CurrencyAmount) number, toAppendTo, pos);
0202: } else if (number instanceof Number) {
0203: return format(((Number) number).doubleValue(), toAppendTo,
0204: pos);
0205: } else {
0206: throw new IllegalArgumentException(
0207: "Cannot format given Object as a Number");
0208: }
0209: }
0210:
0211: /**
0212: * @stable ICU 2.0
0213: */
0214: public final Object parseObject(String source,
0215: ParsePosition parsePosition) {
0216: return parse(source, parsePosition);
0217: }
0218:
0219: /**
0220: * Specialization of format.
0221: * @see java.text.Format#format(Object)
0222: * @stable ICU 2.0
0223: */
0224: public final String format(double number) {
0225: return format(number, new StringBuffer(), new FieldPosition(0))
0226: .toString();
0227: }
0228:
0229: /**
0230: * Specialization of format.
0231: * @see java.text.Format#format(Object)
0232: * @stable ICU 2.0
0233: */
0234: public final String format(long number) {
0235: StringBuffer buf = new StringBuffer(19);
0236: FieldPosition pos = new FieldPosition(0);
0237: format(number, buf, pos);
0238: return buf.toString();
0239: }
0240:
0241: /**
0242: * <strong><font face=helvetica color=red>NEW</font></strong>
0243: * Convenience method to format a BigInteger.
0244: * @stable ICU 2.0
0245: */
0246: public final String format(BigInteger number) {
0247: return format(number, new StringBuffer(), new FieldPosition(0))
0248: .toString();
0249: }
0250:
0251: //#ifndef FOUNDATION
0252: /**
0253: * <strong><font face=helvetica color=red>NEW</font></strong>
0254: * Convenience method to format a BigDecimal.
0255: * @stable ICU 2.0
0256: */
0257: public final String format(java.math.BigDecimal number) {
0258: return format(number, new StringBuffer(), new FieldPosition(0))
0259: .toString();
0260: }
0261:
0262: //#endif
0263:
0264: /**
0265: * <strong><font face=helvetica color=red>NEW</font></strong>
0266: * Convenience method to format an ICU BigDecimal.
0267: * @stable ICU 2.0
0268: */
0269: public final String format(com.ibm.icu.math.BigDecimal number) {
0270: return format(number, new StringBuffer(), new FieldPosition(0))
0271: .toString();
0272: }
0273:
0274: /**
0275: * <strong><font face=helvetica color=red>NEW</font></strong>
0276: * Convenience method to format a CurrencyAmount.
0277: * @stable ICU 3.0
0278: */
0279: public final String format(CurrencyAmount currAmt) {
0280: return format(currAmt, new StringBuffer(), new FieldPosition(0))
0281: .toString();
0282: }
0283:
0284: /**
0285: * Specialization of format.
0286: * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
0287: * @stable ICU 2.0
0288: */
0289: public abstract StringBuffer format(double number,
0290: StringBuffer toAppendTo, FieldPosition pos);
0291:
0292: /**
0293: * Specialization of format.
0294: * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
0295: * @stable ICU 2.0
0296: */
0297: public abstract StringBuffer format(long number,
0298: StringBuffer toAppendTo, FieldPosition pos);
0299:
0300: /**
0301: * <strong><font face=helvetica color=red>NEW</font></strong>
0302: * Format a BigInteger.
0303: * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
0304: * @stable ICU 2.0
0305: */
0306: public abstract StringBuffer format(BigInteger number,
0307: StringBuffer toAppendTo, FieldPosition pos);
0308:
0309: //#ifndef FOUNDATION
0310: /**
0311: * <strong><font face=helvetica color=red>NEW</font></strong>
0312: * Format a BigDecimal.
0313: * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
0314: * @stable ICU 2.0
0315: */
0316: public abstract StringBuffer format(java.math.BigDecimal number,
0317: StringBuffer toAppendTo, FieldPosition pos);
0318:
0319: //#endif
0320:
0321: /**
0322: * <strong><font face=helvetica color=red>NEW</font></strong>
0323: * Format a BigDecimal.
0324: * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
0325: * @stable ICU 2.0
0326: */
0327: public abstract StringBuffer format(
0328: com.ibm.icu.math.BigDecimal number,
0329: StringBuffer toAppendTo, FieldPosition pos);
0330:
0331: /**
0332: * <strong><font face=helvetica color=red>NEW</font></strong>
0333: * Format a CurrencyAmount.
0334: * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
0335: * @stable ICU 3.0
0336: */
0337: public StringBuffer format(CurrencyAmount currAmt,
0338: StringBuffer toAppendTo, FieldPosition pos) {
0339: // Default implementation -- subclasses may override
0340: Currency save = getCurrency(), curr = currAmt.getCurrency();
0341: boolean same = curr.equals(save);
0342: if (!same)
0343: setCurrency(curr);
0344: format(currAmt.getNumber(), toAppendTo, pos);
0345: if (!same)
0346: setCurrency(save);
0347: return toAppendTo;
0348: }
0349:
0350: /**
0351: * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
0352: * Long.MAX_VALUE] and with no decimals), otherwise a Double.
0353: * If IntegerOnly is set, will stop at a decimal
0354: * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
0355: * after the 1).
0356: * Does not throw an exception; if no object can be parsed, index is
0357: * unchanged!
0358: * @see #isParseIntegerOnly
0359: * @see java.text.Format#parseObject(String, ParsePosition)
0360: * @stable ICU 2.0
0361: */
0362: public abstract Number parse(String text,
0363: ParsePosition parsePosition);
0364:
0365: /**
0366: * Parses text from the beginning of the given string to produce a number.
0367: * The method might not use the entire text of the given string.
0368: *
0369: * @param text A String whose beginning should be parsed.
0370: * @return A Number parsed from the string.
0371: * @exception ParseException if the beginning of the specified string
0372: * cannot be parsed.
0373: * @see #format
0374: * @stable ICU 2.0
0375: */
0376: //Bug 4375399 [Richard/GCL]
0377: public Number parse(String text) throws ParseException {
0378: ParsePosition parsePosition = new ParsePosition(0);
0379: Number result = parse(text, parsePosition);
0380: if (parsePosition.getIndex() == 0) {
0381: throw new ParseException("Unparseable number: \"" + text
0382: + '"', parsePosition.getErrorIndex());
0383: }
0384: return result;
0385: }
0386:
0387: /**
0388: * <strong><font face=helvetica color=red>NEW</font></strong>
0389: * Parses text from the given string as a CurrencyAmount. Unlike
0390: * the parse() method, this method will attempt to parse a generic
0391: * currency name, searching for a match of this object's locale's
0392: * currency display names, or for a 3-letter ISO currency code.
0393: * This method will fail if this format is not a currency format,
0394: * that is, if it does not contain the currency pattern symbol
0395: * (U+00A4) in its prefix or suffix.
0396: *
0397: * @param text the string to parse
0398: * @param pos input-output position; on input, the position within
0399: * text to match; must have 0 <= pos.getIndex() < text.length();
0400: * on output, the position after the last matched character. If
0401: * the parse fails, the position in unchanged upon output.
0402: * @return a CurrencyAmount, or null upon failure
0403: * @internal
0404: * @deprecated This API is ICU internal only.
0405: */
0406: CurrencyAmount parseCurrency(String text, ParsePosition pos) {
0407: // Default implementation only -- subclasses should override
0408: Number n = parse(text, pos);
0409: return n == null ? null : new CurrencyAmount(n,
0410: getEffectiveCurrency());
0411: }
0412:
0413: /**
0414: * Returns true if this format will parse numbers as integers only.
0415: * For example in the English locale, with ParseIntegerOnly true, the
0416: * string "1234." would be parsed as the integer value 1234 and parsing
0417: * would stop at the "." character. The decimal separator accepted
0418: * by the parse operation is locale-dependent and determined by the
0419: * subclass.
0420: * @return true if this will parse integers only
0421: * @stable ICU 2.0
0422: */
0423: public boolean isParseIntegerOnly() {
0424: return parseIntegerOnly;
0425: }
0426:
0427: /**
0428: * Sets whether or not numbers should be parsed as integers only.
0429: * @param value true if this should parse integers only
0430: * @see #isParseIntegerOnly
0431: * @stable ICU 2.0
0432: */
0433: public void setParseIntegerOnly(boolean value) {
0434: parseIntegerOnly = value;
0435: }
0436:
0437: /**
0438: * Sets whether strict parsing is in effect. When this is true, the
0439: * following conditions cause a parse failure (examples use the pattern "#,##0.#"):<ul>
0440: * <li>Leading zeros<br>
0441: * '00', '0123' fail the parse, but '0' and '0.001' pass</li>
0442: * <li>Leading or doubled grouping separators<br>
0443: * ',123' and '1,,234" fail</li>
0444: * <li>Groups of incorrect length when grouping is used<br>
0445: * '1,23' and '1234,567' fail, but '1234' passes</li>
0446: * <li>Grouping separators used in numbers followed by exponents<br>
0447: * '1,234E5' fails, but '1234E5' and '1,234E' pass ('E' is not an exponent when
0448: * not followed by a number)</li>
0449: * </ul>
0450: * When strict parsing is off, leading zeros and all grouping separators are ignored.
0451: * This is the default behavior.
0452: * @param value True to enable strict parsing. Default is false.
0453: * @see #isParseStrict
0454: * @draft ICU 3.6
0455: * @provisional This API might change or be removed in a future release.
0456: */
0457: public void setParseStrict(boolean value) {
0458: parseStrict = value;
0459: }
0460:
0461: /**
0462: * Return whether strict parsing is in effect.
0463: * @return true if strict parsing is in effect
0464: * @see #setParseStrict
0465: * @draft ICU 3.6
0466: * @provisional This API might change or be removed in a future release.
0467: */
0468: public boolean isParseStrict() {
0469: return parseStrict;
0470: }
0471:
0472: //============== Locale Stuff =====================
0473:
0474: /**
0475: * Returns the default number format for the current default locale.
0476: * The default format is one of the styles provided by the other
0477: * factory methods: getNumberInstance, getIntegerInstance,
0478: * getCurrencyInstance or getPercentInstance.
0479: * Exactly which one is locale-dependent.
0480: * @stable ICU 2.0
0481: */
0482: //Bug 4408066 [Richard/GCL]
0483: public final static NumberFormat getInstance() {
0484: return getInstance(ULocale.getDefault(), NUMBERSTYLE);
0485: }
0486:
0487: /**
0488: * Returns the default number format for the specified locale.
0489: * The default format is one of the styles provided by the other
0490: * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
0491: * Exactly which one is locale-dependent.
0492: * @stable ICU 2.0
0493: */
0494: public static NumberFormat getInstance(Locale inLocale) {
0495: return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
0496: }
0497:
0498: /**
0499: * Returns the default number format for the specified locale.
0500: * The default format is one of the styles provided by the other
0501: * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
0502: * Exactly which one is locale-dependent.
0503: * @draft ICU 3.2
0504: * @provisional This API might change or be removed in a future release.
0505: */
0506: public static NumberFormat getInstance(ULocale inLocale) {
0507: return getInstance(inLocale, NUMBERSTYLE);
0508: }
0509:
0510: /**
0511: * Returns a general-purpose number format for the current default locale.
0512: * @stable ICU 2.0
0513: */
0514: public final static NumberFormat getNumberInstance() {
0515: return getInstance(ULocale.getDefault(), NUMBERSTYLE);
0516: }
0517:
0518: /**
0519: * Returns a general-purpose number format for the specified locale.
0520: * @stable ICU 2.0
0521: */
0522: public static NumberFormat getNumberInstance(Locale inLocale) {
0523: return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
0524: }
0525:
0526: /**
0527: * Returns a general-purpose number format for the specified locale.
0528: * @draft ICU 3.2
0529: * @provisional This API might change or be removed in a future release.
0530: */
0531: public static NumberFormat getNumberInstance(ULocale inLocale) {
0532: return getInstance(inLocale, NUMBERSTYLE);
0533: }
0534:
0535: /**
0536: * Returns an integer number format for the current default locale. The
0537: * returned number format is configured to round floating point numbers
0538: * to the nearest integer using IEEE half-even rounding (see {@link
0539: * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
0540: * and to parse only the integer part of an input string (see {@link
0541: * #isParseIntegerOnly isParseIntegerOnly}).
0542: *
0543: * @return a number format for integer values
0544: * @stable ICU 2.0
0545: */
0546: //Bug 4408066 [Richard/GCL]
0547: public final static NumberFormat getIntegerInstance() {
0548: return getInstance(ULocale.getDefault(), INTEGERSTYLE);
0549: }
0550:
0551: /**
0552: * Returns an integer number format for the specified locale. The
0553: * returned number format is configured to round floating point numbers
0554: * to the nearest integer using IEEE half-even rounding (see {@link
0555: * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
0556: * and to parse only the integer part of an input string (see {@link
0557: * #isParseIntegerOnly isParseIntegerOnly}).
0558: *
0559: * @param inLocale the locale for which a number format is needed
0560: * @return a number format for integer values
0561: * @stable ICU 2.0
0562: */
0563: //Bug 4408066 [Richard/GCL]
0564: public static NumberFormat getIntegerInstance(Locale inLocale) {
0565: return getInstance(ULocale.forLocale(inLocale), INTEGERSTYLE);
0566: }
0567:
0568: /**
0569: * Returns an integer number format for the specified locale. The
0570: * returned number format is configured to round floating point numbers
0571: * to the nearest integer using IEEE half-even rounding (see {@link
0572: * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
0573: * and to parse only the integer part of an input string (see {@link
0574: * #isParseIntegerOnly isParseIntegerOnly}).
0575: *
0576: * @param inLocale the locale for which a number format is needed
0577: * @return a number format for integer values
0578: * @draft ICU 3.2
0579: * @provisional This API might change or be removed in a future release.
0580: */
0581: public static NumberFormat getIntegerInstance(ULocale inLocale) {
0582: return getInstance(inLocale, INTEGERSTYLE);
0583: }
0584:
0585: /**
0586: * Returns a currency format for the current default locale.
0587: * @return a number format for currency
0588: * @stable ICU 2.0
0589: */
0590: public final static NumberFormat getCurrencyInstance() {
0591: return getInstance(ULocale.getDefault(), CURRENCYSTYLE);
0592: }
0593:
0594: /**
0595: * Returns a currency format for the specified locale.
0596: * @return a number format for currency
0597: * @stable ICU 2.0
0598: */
0599: public static NumberFormat getCurrencyInstance(Locale inLocale) {
0600: return getInstance(ULocale.forLocale(inLocale), CURRENCYSTYLE);
0601: }
0602:
0603: /**
0604: * Returns a currency format for the specified locale.
0605: * @return a number format for currency
0606: * @draft ICU 3.2
0607: * @provisional This API might change or be removed in a future release.
0608: */
0609: public static NumberFormat getCurrencyInstance(ULocale inLocale) {
0610: return getInstance(inLocale, CURRENCYSTYLE);
0611: }
0612:
0613: /**
0614: * Returns a percentage format for the current default locale.
0615: * @return a number format for percents
0616: * @stable ICU 2.0
0617: */
0618: public final static NumberFormat getPercentInstance() {
0619: return getInstance(ULocale.getDefault(), PERCENTSTYLE);
0620: }
0621:
0622: /**
0623: * Returns a percentage format for the specified locale.
0624: * @return a number format for percents
0625: * @stable ICU 2.0
0626: */
0627: public static NumberFormat getPercentInstance(Locale inLocale) {
0628: return getInstance(ULocale.forLocale(inLocale), PERCENTSTYLE);
0629: }
0630:
0631: /**
0632: * Returns a percentage format for the specified locale.
0633: * @return a number format for percents
0634: * @draft ICU 3.2
0635: * @provisional This API might change or be removed in a future release.
0636: */
0637: public static NumberFormat getPercentInstance(ULocale inLocale) {
0638: return getInstance(inLocale, PERCENTSTYLE);
0639: }
0640:
0641: /**
0642: * <strong><font face=helvetica color=red>NEW</font></strong>
0643: * Returns a scientific format for the current default locale.
0644: * @return a scientific number format
0645: * @stable ICU 2.0
0646: */
0647: public final static NumberFormat getScientificInstance() {
0648: return getInstance(ULocale.getDefault(), SCIENTIFICSTYLE);
0649: }
0650:
0651: /**
0652: * <strong><font face=helvetica color=red>NEW</font></strong>
0653: * Returns a scientific format for the specified locale.
0654: * @return a scientific number format
0655: * @stable ICU 2.0
0656: */
0657: public static NumberFormat getScientificInstance(Locale inLocale) {
0658: return getInstance(ULocale.forLocale(inLocale), SCIENTIFICSTYLE);
0659: }
0660:
0661: /**
0662: * <strong><font face=helvetica color=red>NEW</font></strong>
0663: * Returns a scientific format for the specified locale.
0664: * @return a scientific number format
0665: * @draft ICU 3.2
0666: * @provisional This API might change or be removed in a future release.
0667: */
0668: public static NumberFormat getScientificInstance(ULocale inLocale) {
0669: return getInstance(inLocale, SCIENTIFICSTYLE);
0670: }
0671:
0672: // ===== Factory stuff =====
0673: /**
0674: * A NumberFormatFactory is used to register new number formats. The factory
0675: * should be able to create any of the predefined formats for each locale it
0676: * supports. When registered, the locales it supports extend or override the
0677: * locales already supported by ICU.
0678: * <p><b>Note:</b> as of ICU4J 3.2, the default API for NumberFormatFactory uses
0679: * ULocale instead of Locale. Instead of overriding createFormat(Locale, int),
0680: * new implementations should override createFactory(ULocale, int). Note that
0681: * one of these two methods <b>MUST</b> be overridden or else an infinite
0682: * loop will occur.
0683: *
0684: * @stable ICU 2.6
0685: */
0686: public static abstract class NumberFormatFactory {
0687: /**
0688: * Value passed to format requesting a default number format.
0689: * @stable ICU 2.6
0690: */
0691: public static final int FORMAT_NUMBER = NUMBERSTYLE;
0692:
0693: /**
0694: * Value passed to format requesting a currency format.
0695: * @stable ICU 2.6
0696: */
0697: public static final int FORMAT_CURRENCY = CURRENCYSTYLE;
0698:
0699: /**
0700: * Value passed to format requesting a percent format.
0701: * @stable ICU 2.6
0702: */
0703: public static final int FORMAT_PERCENT = PERCENTSTYLE;
0704:
0705: /**
0706: * Value passed to format requesting a scientific format.
0707: * @stable ICU 2.6
0708: */
0709: public static final int FORMAT_SCIENTIFIC = SCIENTIFICSTYLE;
0710:
0711: /**
0712: * Value passed to format requesting an integer format.
0713: * @stable ICU 2.6
0714: */
0715: public static final int FORMAT_INTEGER = INTEGERSTYLE;
0716:
0717: /**
0718: * Returns true if this factory is visible. Default is true.
0719: * If not visible, the locales supported by this factory will not
0720: * be listed by getAvailableLocales. This value must not change.
0721: * @return true if the factory is visible.
0722: * @stable ICU 2.6
0723: */
0724: ///CLOVER:OFF
0725: public boolean visible() {
0726: return true;
0727: }
0728:
0729: ///CLOVER:ON
0730:
0731: /**
0732: * Returns an immutable collection of the locale names directly
0733: * supported by this factory.
0734: * @return the supported locale names.
0735: * @stable ICU 2.6
0736: */
0737: public abstract Set getSupportedLocaleNames();
0738:
0739: /**
0740: * Returns a number format of the appropriate type. If the locale
0741: * is not supported, return null. If the locale is supported, but
0742: * the type is not provided by this service, return null. Otherwise
0743: * return an appropriate instance of NumberFormat.
0744: * <b>Note:</b> as of ICU4J 3.2, implementations should override
0745: * this method instead of createFormat(Locale, int).
0746: * @param loc the locale for which to create the format
0747: * @param formatType the type of format
0748: * @return the NumberFormat, or null.
0749: * @draft ICU 3.2
0750: * @provisional This API might change or be removed in a future release.
0751: */
0752: public NumberFormat createFormat(ULocale loc, int formatType) {
0753: return createFormat(loc.toLocale(), formatType);
0754: }
0755:
0756: /**
0757: * Returns a number format of the appropriate type. If the locale
0758: * is not supported, return null. If the locale is supported, but
0759: * the type is not provided by this service, return null. Otherwise
0760: * return an appropriate instance of NumberFormat.
0761: * <b>Note:</b> as of ICU4J 3.2, createFormat(ULocale, int) should be
0762: * overridden instead of this method. This method is no longer
0763: * abstract and delegates to that method.
0764: * @param loc the locale for which to create the format
0765: * @param formatType the type of format
0766: * @return the NumberFormat, or null.
0767: * @stable ICU 2.6
0768: */
0769: public NumberFormat createFormat(Locale loc, int formatType) {
0770: return createFormat(ULocale.forLocale(loc), formatType);
0771: }
0772:
0773: /**
0774: * @stable ICU 2.6
0775: */
0776: protected NumberFormatFactory() {
0777: }
0778: }
0779:
0780: /**
0781: * A NumberFormatFactory that supports a single locale. It can be visible or invisible.
0782: * @stable ICU 2.6
0783: */
0784: public static abstract class SimpleNumberFormatFactory extends
0785: NumberFormatFactory {
0786: final Set localeNames;
0787: final boolean visible;
0788:
0789: /**
0790: * @stable ICU 2.6
0791: */
0792: public SimpleNumberFormatFactory(Locale locale) {
0793: this (locale, true);
0794: }
0795:
0796: /**
0797: * @stable ICU 2.6
0798: */
0799: public SimpleNumberFormatFactory(Locale locale, boolean visible) {
0800: localeNames = Collections.singleton(ULocale.forLocale(
0801: locale).getBaseName());
0802: this .visible = visible;
0803: }
0804:
0805: /**
0806: * @draft ICU 3.2
0807: * @provisional This API might change or be removed in a future release.
0808: */
0809: public SimpleNumberFormatFactory(ULocale locale) {
0810: this (locale, true);
0811: }
0812:
0813: /**
0814: * @draft ICU 3.2
0815: * @provisional This API might change or be removed in a future release.
0816: */
0817: public SimpleNumberFormatFactory(ULocale locale, boolean visible) {
0818: localeNames = Collections.singleton(locale.getBaseName());
0819: this .visible = visible;
0820: }
0821:
0822: /**
0823: * @stable ICU 2.6
0824: */
0825: public final boolean visible() {
0826: return visible;
0827: }
0828:
0829: /**
0830: * @stable ICU 2.6
0831: */
0832: public final Set getSupportedLocaleNames() {
0833: return localeNames;
0834: }
0835: }
0836:
0837: // shim so we can build without service code
0838: static abstract class NumberFormatShim {
0839: abstract Locale[] getAvailableLocales();
0840:
0841: abstract ULocale[] getAvailableULocales();
0842:
0843: abstract Object registerFactory(NumberFormatFactory f);
0844:
0845: abstract boolean unregister(Object k);
0846:
0847: abstract NumberFormat createInstance(ULocale l, int k);
0848: }
0849:
0850: private static NumberFormatShim shim;
0851:
0852: private static NumberFormatShim getShim() {
0853: // Note: this instantiation is safe on loose-memory-model configurations
0854: // despite lack of synchronization, since the shim instance has no state--
0855: // it's all in the class init. The worst problem is we might instantiate
0856: // two shim instances, but they'll share the same state so that's ok.
0857: if (shim == null) {
0858: try {
0859: Class cls = Class
0860: .forName("com.ibm.icu.text.NumberFormatServiceShim");
0861: shim = (NumberFormatShim) cls.newInstance();
0862: } catch (MissingResourceException e) {
0863: throw e;
0864: } catch (Exception e) {
0865: ///CLOVER:OFF
0866: // e.printStackTrace();
0867: throw new RuntimeException(e.getMessage());
0868: ///CLOVER:ON
0869: }
0870: }
0871: return shim;
0872: }
0873:
0874: /**
0875: * Get the list of Locales for which NumberFormats are available.
0876: * @return the available locales
0877: * @stable ICU 2.0
0878: */
0879: public static Locale[] getAvailableLocales() {
0880: if (shim == null) {
0881: return ICUResourceBundle
0882: .getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);
0883: }
0884: return getShim().getAvailableLocales();
0885: }
0886:
0887: /**
0888: * Get the list of Locales for which NumberFormats are available.
0889: * @return the available locales
0890: * @draft ICU 3.2
0891: * @provisional This API might change or be removed in a future release.
0892: */
0893: public static ULocale[] getAvailableULocales() {
0894: if (shim == null) {
0895: return ICUResourceBundle
0896: .getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);
0897: }
0898: return getShim().getAvailableULocales();
0899: }
0900:
0901: /**
0902: * Registers a new NumberFormatFactory. The factory is adopted by
0903: * the service and must not be modified. The returned object is a
0904: * key that can be used to unregister this factory.
0905: * @param factory the factory to register
0906: * @return a key with which to unregister the factory
0907: * @stable ICU 2.6
0908: */
0909: public static Object registerFactory(NumberFormatFactory factory) {
0910: if (factory == null) {
0911: throw new IllegalArgumentException(
0912: "factory must not be null");
0913: }
0914: return getShim().registerFactory(factory);
0915: }
0916:
0917: /**
0918: * Unregister the factory or instance associated with this key (obtained from
0919: * registerInstance or registerFactory).
0920: * @param registryKey a key obtained from registerFactory
0921: * @return true if the object was successfully unregistered
0922: * @stable ICU 2.6
0923: */
0924: public static boolean unregister(Object registryKey) {
0925: if (registryKey == null) {
0926: throw new IllegalArgumentException(
0927: "registryKey must not be null");
0928: }
0929:
0930: if (shim == null) {
0931: return false;
0932: }
0933:
0934: return shim.unregister(registryKey);
0935: }
0936:
0937: // ===== End of factory stuff =====
0938:
0939: /**
0940: * Overrides hashCode
0941: * @stable ICU 2.0
0942: */
0943: public int hashCode() {
0944: return maximumIntegerDigits * 37 + maxFractionDigits;
0945: // just enough fields for a reasonable distribution
0946: }
0947:
0948: /**
0949: * Overrides equals. Two NumberFormats are equal if they are of the same class
0950: * and the settings (groupingUsed, parseIntegerOnly, maximumIntegerDigits, etc.
0951: * are equal.
0952: * @param obj the object to compare against
0953: * @return true if the object is equal to this.
0954: * @stable ICU 2.0
0955: */
0956: public boolean equals(Object obj) {
0957: if (obj == null)
0958: return false;
0959: if (this == obj)
0960: return true;
0961: if (getClass() != obj.getClass())
0962: return false;
0963: NumberFormat other = (NumberFormat) obj;
0964: return maximumIntegerDigits == other.maximumIntegerDigits
0965: && minimumIntegerDigits == other.minimumIntegerDigits
0966: && maximumFractionDigits == other.maximumFractionDigits
0967: && minimumFractionDigits == other.minimumFractionDigits
0968: && groupingUsed == other.groupingUsed
0969: && parseIntegerOnly == other.parseIntegerOnly
0970: && parseStrict == other.parseStrict;
0971: }
0972:
0973: /**
0974: * Overrides Cloneable.
0975: * @stable ICU 2.0
0976: */
0977: public Object clone() {
0978: NumberFormat other = (NumberFormat) super .clone();
0979: return other;
0980: }
0981:
0982: /**
0983: * Returns true if grouping is used in this format. For example, in the
0984: * en_US locale, with grouping on, the number 1234567 will be formatted
0985: * as "1,234,567". The grouping separator as well as the size of each group
0986: * is locale-dependent and is determined by subclasses of NumberFormat.
0987: * Grouping affects both parsing and formatting.
0988: * @return true if grouping is used
0989: * @see #setGroupingUsed
0990: * @stable ICU 2.0
0991: */
0992: public boolean isGroupingUsed() {
0993: return groupingUsed;
0994: }
0995:
0996: /**
0997: * Sets whether or not grouping will be used in this format. Grouping
0998: * affects both parsing and formatting.
0999: * @see #isGroupingUsed
1000: * @param newValue true to use grouping.
1001: * @stable ICU 2.0
1002: */
1003: public void setGroupingUsed(boolean newValue) {
1004: groupingUsed = newValue;
1005: }
1006:
1007: /**
1008: * Returns the maximum number of digits allowed in the integer portion of a
1009: * number. The default value is 40, which subclasses can override.
1010: * When formatting, the exact behavior when this value is exceeded is
1011: * subclass-specific. When parsing, this has no effect.
1012: * @return the maximum number of integer digits
1013: * @see #setMaximumIntegerDigits
1014: * @stable ICU 2.0
1015: */
1016: public int getMaximumIntegerDigits() {
1017: return maximumIntegerDigits;
1018: }
1019:
1020: /**
1021: * Sets the maximum number of digits allowed in the integer portion of a
1022: * number. This must be >= minimumIntegerDigits. If the
1023: * new value for maximumIntegerDigits is less than the current value
1024: * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
1025: * the new value.
1026: * @param newValue the maximum number of integer digits to be shown; if
1027: * less than zero, then zero is used. Subclasses might enforce an
1028: * upper limit to this value appropriate to the numeric type being formatted.
1029: * @see #getMaximumIntegerDigits
1030: * @stable ICU 2.0
1031: */
1032: public void setMaximumIntegerDigits(int newValue) {
1033: maximumIntegerDigits = Math.max(0, newValue);
1034: if (minimumIntegerDigits > maximumIntegerDigits)
1035: minimumIntegerDigits = maximumIntegerDigits;
1036: }
1037:
1038: /**
1039: * Returns the minimum number of digits allowed in the integer portion of a
1040: * number. The default value is 1, which subclasses can override.
1041: * When formatting, if this value is not reached, numbers are padded on the
1042: * left with the locale-specific '0' character to ensure at least this
1043: * number of integer digits. When parsing, this has no effect.
1044: * @return the minimum number of integer digits
1045: * @see #setMinimumIntegerDigits
1046: * @stable ICU 2.0
1047: */
1048: public int getMinimumIntegerDigits() {
1049: return minimumIntegerDigits;
1050: }
1051:
1052: /**
1053: * Sets the minimum number of digits allowed in the integer portion of a
1054: * number. This must be <= maximumIntegerDigits. If the
1055: * new value for minimumIntegerDigits is more than the current value
1056: * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
1057: * the new value.
1058: * @param newValue the minimum number of integer digits to be shown; if
1059: * less than zero, then zero is used. Subclasses might enforce an
1060: * upper limit to this value appropriate to the numeric type being formatted.
1061: * @see #getMinimumIntegerDigits
1062: * @stable ICU 2.0
1063: */
1064: public void setMinimumIntegerDigits(int newValue) {
1065: minimumIntegerDigits = Math.max(0, newValue);
1066: if (minimumIntegerDigits > maximumIntegerDigits)
1067: maximumIntegerDigits = minimumIntegerDigits;
1068: }
1069:
1070: /**
1071: * Returns the maximum number of digits allowed in the fraction
1072: * portion of a number. The default value is 3, which subclasses
1073: * can override. When formatting, the exact behavior when this
1074: * value is exceeded is subclass-specific. When parsing, this has
1075: * no effect.
1076: * @return the maximum number of fraction digits
1077: * @see #setMaximumFractionDigits
1078: * @stable ICU 2.0
1079: */
1080: public int getMaximumFractionDigits() {
1081: return maximumFractionDigits;
1082: }
1083:
1084: /**
1085: * Sets the maximum number of digits allowed in the fraction portion of a
1086: * number. This must be >= minimumFractionDigits. If the
1087: * new value for maximumFractionDigits is less than the current value
1088: * of minimumFractionDigits, then minimumFractionDigits will also be set to
1089: * the new value.
1090: * @param newValue the maximum number of fraction digits to be shown; if
1091: * less than zero, then zero is used. The concrete subclass may enforce an
1092: * upper limit to this value appropriate to the numeric type being formatted.
1093: * @see #getMaximumFractionDigits
1094: * @stable ICU 2.0
1095: */
1096: public void setMaximumFractionDigits(int newValue) {
1097: maximumFractionDigits = Math.max(0, newValue);
1098: if (maximumFractionDigits < minimumFractionDigits)
1099: minimumFractionDigits = maximumFractionDigits;
1100: }
1101:
1102: /**
1103: * Returns the minimum number of digits allowed in the fraction portion of a
1104: * number. The default value is 0, which subclasses can override.
1105: * When formatting, if this value is not reached, numbers are padded on
1106: * the right with the locale-specific '0' character to ensure at least
1107: * this number of fraction digits. When parsing, this has no effect.
1108: * @return the minimum number of fraction digits
1109: * @see #setMinimumFractionDigits
1110: * @stable ICU 2.0
1111: */
1112: public int getMinimumFractionDigits() {
1113: return minimumFractionDigits;
1114: }
1115:
1116: /**
1117: * Sets the minimum number of digits allowed in the fraction portion of a
1118: * number. This must be <= maximumFractionDigits. If the
1119: * new value for minimumFractionDigits exceeds the current value
1120: * of maximumFractionDigits, then maximumFractionDigits will also be set to
1121: * the new value.
1122: * @param newValue the minimum number of fraction digits to be shown; if
1123: * less than zero, then zero is used. Subclasses might enforce an
1124: * upper limit to this value appropriate to the numeric type being formatted.
1125: * @see #getMinimumFractionDigits
1126: * @stable ICU 2.0
1127: */
1128: public void setMinimumFractionDigits(int newValue) {
1129: minimumFractionDigits = Math.max(0, newValue);
1130: if (maximumFractionDigits < minimumFractionDigits)
1131: maximumFractionDigits = minimumFractionDigits;
1132: }
1133:
1134: /**
1135: * Sets the <tt>Currency</tt> object used to display currency
1136: * amounts. This takes effect immediately, if this format is a
1137: * currency format. If this format is not a currency format, then
1138: * the currency object is used if and when this object becomes a
1139: * currency format.
1140: * @param theCurrency new currency object to use. May be null for
1141: * some subclasses.
1142: * @stable ICU 2.6
1143: */
1144: public void setCurrency(Currency theCurrency) {
1145: currency = theCurrency;
1146: }
1147:
1148: /**
1149: * Gets the <tt>Currency</tt> object used to display currency
1150: * amounts. This may be null.
1151: * @stable ICU 2.6
1152: */
1153: public Currency getCurrency() {
1154: return currency;
1155: }
1156:
1157: /**
1158: * Returns the currency in effect for this formatter. Subclasses
1159: * should override this method as needed. Unlike getCurrency(),
1160: * this method should never return null.
1161: * @return a non-null Currency
1162: * @internal
1163: * @deprecated This API is ICU internal only.
1164: */
1165: protected Currency getEffectiveCurrency() {
1166: Currency c = getCurrency();
1167: if (c == null) {
1168: ULocale uloc = getLocale(ULocale.VALID_LOCALE);
1169: if (uloc == null) {
1170: uloc = ULocale.getDefault();
1171: }
1172: c = Currency.getInstance(uloc);
1173: }
1174: return c;
1175: }
1176:
1177: // =======================privates===============================
1178:
1179: // Hook for service
1180: private static NumberFormat getInstance(ULocale desiredLocale,
1181: int choice) {
1182: // if (shim == null) {
1183: // return createInstance(desiredLocale, choice);
1184: // } else {
1185: // // TODO: shims must call setLocale() on object they create
1186: // return getShim().createInstance(desiredLocale, choice);
1187: // }
1188: return getShim().createInstance(desiredLocale, choice);
1189: }
1190:
1191: // [NEW]
1192: static NumberFormat createInstance(ULocale desiredLocale, int choice) {
1193: String pattern = getPattern(desiredLocale, choice);
1194: DecimalFormatSymbols symbols = new DecimalFormatSymbols(
1195: desiredLocale);
1196:
1197: // Here we assume that the locale passed in is in the canonical
1198: // form, e.g: pt_PT_@currency=PTE not pt_PT_PREEURO
1199: if (choice == CURRENCYSTYLE) {
1200: String temp = symbols.getCurrencyPattern();
1201: if (temp != null) {
1202: pattern = temp;
1203: }
1204: }
1205:
1206: DecimalFormat format = new DecimalFormat(pattern, symbols);
1207: // System.out.println("loc: " + desiredLocale + " choice: " + choice + " pat: " + pattern + " sym: " + symbols + " result: " + format);
1208:
1209: /*Bug 4408066
1210: Add codes for the new method getIntegerInstance() [Richard/GCL]
1211: */
1212: // TODO: revisit this -- this is almost certainly not the way we want
1213: // to do this. aliu 1/6/2004
1214: if (choice == INTEGERSTYLE) {
1215: format.setMaximumFractionDigits(0);
1216: format.setDecimalSeparatorAlwaysShown(false);
1217: format.setParseIntegerOnly(true);
1218: }
1219:
1220: // TODO: the actual locale of the *pattern* may differ from that
1221: // for the *symbols*. For now, we use the data for the symbols.
1222: // Revisit this.
1223: ULocale valid = symbols.getLocale(ULocale.VALID_LOCALE);
1224: ULocale actual = symbols.getLocale(ULocale.ACTUAL_LOCALE);
1225: format.setLocale(valid, actual);
1226:
1227: return format;
1228: }
1229:
1230: /**
1231: * Returns the pattern for the provided locale and choice.
1232: * @param forLocale the locale of the data.
1233: * @param choice the pattern format.
1234: * @return the pattern
1235: * @deprecated ICU 3.4 subclassers should override getPattern(ULocale, int) instead of this method.
1236: */
1237: protected static String getPattern(Locale forLocale, int choice) {
1238: return getPattern(ULocale.forLocale(forLocale), choice);
1239: }
1240:
1241: /**
1242: * Returns the pattern for the provided locale and choice.
1243: * @param forLocale the locale of the data.
1244: * @param choice the pattern format.
1245: * @return the pattern
1246: * @draft ICU 3.2
1247: * @provisional This API might change or be removed in a future release.
1248: */
1249: protected static String getPattern(ULocale forLocale, int choice) {
1250:
1251: /* The following code takes care of a few cases where the
1252: * resource data in the underlying JDK lags the new features
1253: * we have added to ICU4J: scientific notation, rounding, and
1254: * secondary grouping.
1255: *
1256: * We detect these cases here and return various hard-coded
1257: * resource data. This is the simplest solution for now, but
1258: * it is not a good long-term mechanism.
1259: *
1260: * We should replace this code with a data-driven mechanism
1261: * that reads the bundle com.ibm.icu.impl.data.LocaleElements
1262: * and parses an exception table that overrides the standard
1263: * data at java.text.resource.LocaleElements*.java.
1264: * Alternatively, we should create our own copy of the
1265: * resource data, and use that exclusively.
1266: */
1267:
1268: // TEMPORARY, until we get scientific patterns into the main
1269: // resources: Retrieve scientific patterns from our resources.
1270: if (choice == SCIENTIFICSTYLE) {
1271: // Temporarily hard code; retrieve from resource later
1272: /*For ICU compatibility [Richard/GCL]*/
1273: return "#E0";
1274: // return NumberFormat.getBaseStringArray("NumberPatterns")[SCIENTIFICSTYLE];
1275: }
1276: // TEMPORARY: Use rounding for Swiss currency
1277: //if (choice == CURRENCYSTYLE &&
1278: // forLocale.getCountry().equals("CH")) {
1279: // return "'Fr. '#,##0.05;'Fr.-'#,##0.05";
1280: //}
1281: // TEMPORARY: Special case IN number format
1282: //if (choice == NUMBERSTYLE &&
1283: // forLocale.getCountry().equals("IN")) {
1284: // return "#,##,##0.###";
1285: //}
1286:
1287: // {dlf}
1288: ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle
1289: .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
1290: forLocale);
1291: String[] numberPatterns = rb.getStringArray("NumberPatterns");
1292:
1293: /* {dlf}
1294: // Try the cache first
1295: String[] numberPatterns = (String[]) cachedLocaleData.get(forLocale);
1296: if (numberPatterns == null) {
1297: OverlayBundle resource = new OverlayBundle(new String[]
1298: { "com.ibm.icu.impl.data.LocaleElements", RESOURCE_BASE }, forLocale);
1299: numberPatterns = resource.getStringArray("NumberPatterns");
1300: // Update the cache
1301: cachedLocaleData.put(forLocale, numberPatterns);
1302: }
1303: */
1304:
1305: /*Bug 4408066
1306: Add codes for the new method getIntegerInstance() [Richard/GCL]
1307: */
1308: int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice; //[Richard/GCL]
1309: return numberPatterns[entry]; //[Richard/GCL]
1310: }
1311:
1312: /**
1313: * First, read in the default serializable data.
1314: *
1315: * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
1316: * the stream was written by JDK 1.1,
1317: * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1318: * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
1319: * since the <code>int</code> fields were not present in JDK 1.1.
1320: * Finally, set serialVersionOnStream back to the maximum allowed value so that
1321: * default serialization will work properly if this object is streamed out again.
1322: */
1323: private void readObject(ObjectInputStream stream)
1324: throws IOException, ClassNotFoundException {
1325: stream.defaultReadObject();
1326: ///CLOVER:OFF
1327: // we don't have serialization data for this format
1328: if (serialVersionOnStream < 1) {
1329: // Didn't have additional int fields, reassign to use them.
1330: maximumIntegerDigits = maxIntegerDigits;
1331: minimumIntegerDigits = minIntegerDigits;
1332: maximumFractionDigits = maxFractionDigits;
1333: minimumFractionDigits = minFractionDigits;
1334: }
1335: ///CLOVER:ON
1336: /*Bug 4185761
1337: Validate the min and max fields [Richard/GCL]
1338: */
1339: if (minimumIntegerDigits > maximumIntegerDigits
1340: || minimumFractionDigits > maximumFractionDigits
1341: || minimumIntegerDigits < 0
1342: || minimumFractionDigits < 0) {
1343: throw new InvalidObjectException(
1344: "Digit count range invalid");
1345: }
1346: serialVersionOnStream = currentSerialVersion;
1347: }
1348:
1349: /**
1350: * Write out the default serializable data, after first setting
1351: * the <code>byte</code> fields such as <code>maxIntegerDigits</code> to be
1352: * equal to the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1353: * (or to <code>Byte.MAX_VALUE</code>, whichever is smaller), for compatibility
1354: * with the JDK 1.1 version of the stream format.
1355: */
1356: private void writeObject(ObjectOutputStream stream)
1357: throws IOException {
1358: maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE
1359: : (byte) maximumIntegerDigits;
1360: minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE
1361: : (byte) minimumIntegerDigits;
1362: maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE
1363: : (byte) maximumFractionDigits;
1364: minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE
1365: : (byte) minimumFractionDigits;
1366: stream.defaultWriteObject();
1367: }
1368:
1369: // Unused -- Alan 2003-05
1370: // /**
1371: // * Cache to hold the NumberPatterns of a Locale.
1372: // */
1373: // private static final Hashtable cachedLocaleData = new Hashtable(3);
1374:
1375: /*Bug 4408066
1376: Add Field for the new method getIntegerInstance() [Richard/GCL]
1377: */
1378:
1379: /**
1380: * True if the the grouping (i.e. thousands) separator is used when
1381: * formatting and parsing numbers.
1382: *
1383: * @serial
1384: * @see #isGroupingUsed
1385: */
1386: private boolean groupingUsed = true;
1387:
1388: /**
1389: * The maximum number of digits allowed in the integer portion of a
1390: * number. <code>maxIntegerDigits</code> must be greater than or equal to
1391: * <code>minIntegerDigits</code>.
1392: * <p>
1393: * <strong>Note:</strong> This field exists only for serialization
1394: * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1395: * <code>int</code> field <code>maximumIntegerDigits</code> is used instead.
1396: * When writing to a stream, <code>maxIntegerDigits</code> is set to
1397: * <code>maximumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
1398: * whichever is smaller. When reading from a stream, this field is used
1399: * only if <code>serialVersionOnStream</code> is less than 1.
1400: *
1401: * @serial
1402: * @see #getMaximumIntegerDigits
1403: */
1404: private byte maxIntegerDigits = 40;
1405:
1406: /**
1407: * The minimum number of digits allowed in the integer portion of a
1408: * number. <code>minimumIntegerDigits</code> must be less than or equal to
1409: * <code>maximumIntegerDigits</code>.
1410: * <p>
1411: * <strong>Note:</strong> This field exists only for serialization
1412: * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1413: * <code>int</code> field <code>minimumIntegerDigits</code> is used instead.
1414: * When writing to a stream, <code>minIntegerDigits</code> is set to
1415: * <code>minimumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
1416: * whichever is smaller. When reading from a stream, this field is used
1417: * only if <code>serialVersionOnStream</code> is less than 1.
1418: *
1419: * @serial
1420: * @see #getMinimumIntegerDigits
1421: */
1422: private byte minIntegerDigits = 1;
1423:
1424: /**
1425: * The maximum number of digits allowed in the fractional portion of a
1426: * number. <code>maximumFractionDigits</code> must be greater than or equal to
1427: * <code>minimumFractionDigits</code>.
1428: * <p>
1429: * <strong>Note:</strong> This field exists only for serialization
1430: * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1431: * <code>int</code> field <code>maximumFractionDigits</code> is used instead.
1432: * When writing to a stream, <code>maxFractionDigits</code> is set to
1433: * <code>maximumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
1434: * whichever is smaller. When reading from a stream, this field is used
1435: * only if <code>serialVersionOnStream</code> is less than 1.
1436: *
1437: * @serial
1438: * @see #getMaximumFractionDigits
1439: */
1440: private byte maxFractionDigits = 3; // invariant, >= minFractionDigits
1441:
1442: /**
1443: * The minimum number of digits allowed in the fractional portion of a
1444: * number. <code>minimumFractionDigits</code> must be less than or equal to
1445: * <code>maximumFractionDigits</code>.
1446: * <p>
1447: * <strong>Note:</strong> This field exists only for serialization
1448: * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1449: * <code>int</code> field <code>minimumFractionDigits</code> is used instead.
1450: * When writing to a stream, <code>minFractionDigits</code> is set to
1451: * <code>minimumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
1452: * whichever is smaller. When reading from a stream, this field is used
1453: * only if <code>serialVersionOnStream</code> is less than 1.
1454: *
1455: * @serial
1456: * @see #getMinimumFractionDigits
1457: */
1458: private byte minFractionDigits = 0;
1459:
1460: /**
1461: * True if this format will parse numbers as integers only.
1462: *
1463: * @serial
1464: * @see #isParseIntegerOnly
1465: */
1466: private boolean parseIntegerOnly = false;
1467:
1468: // new fields for 1.2. byte is too small for integer digits.
1469:
1470: /**
1471: * The maximum number of digits allowed in the integer portion of a
1472: * number. <code>maximumIntegerDigits</code> must be greater than or equal to
1473: * <code>minimumIntegerDigits</code>.
1474: *
1475: * @serial
1476: * @see #getMaximumIntegerDigits
1477: */
1478: private int maximumIntegerDigits = 40;
1479:
1480: /**
1481: * The minimum number of digits allowed in the integer portion of a
1482: * number. <code>minimumIntegerDigits</code> must be less than or equal to
1483: * <code>maximumIntegerDigits</code>.
1484: *
1485: * @serial
1486: * @see #getMinimumIntegerDigits
1487: */
1488: private int minimumIntegerDigits = 1;
1489:
1490: /**
1491: * The maximum number of digits allowed in the fractional portion of a
1492: * number. <code>maximumFractionDigits</code> must be greater than or equal to
1493: * <code>minimumFractionDigits</code>.
1494: *
1495: * @serial
1496: * @see #getMaximumFractionDigits
1497: */
1498: private int maximumFractionDigits = 3; // invariant, >= minFractionDigits
1499:
1500: /**
1501: * The minimum number of digits allowed in the fractional portion of a
1502: * number. <code>minimumFractionDigits</code> must be less than or equal to
1503: * <code>maximumFractionDigits</code>.
1504: *
1505: * @serial
1506: * @see #getMinimumFractionDigits
1507: */
1508: private int minimumFractionDigits = 0;
1509:
1510: /**
1511: * Currency object used to format currencies. Subclasses may
1512: * ignore this if they are not currency formats. This will be
1513: * null unless a subclass sets it to a non-null value.
1514: * @since ICU 2.6
1515: */
1516: private Currency currency;
1517:
1518: static final int currentSerialVersion = 1;
1519:
1520: /**
1521: * Describes the version of <code>NumberFormat</code> present on the stream.
1522: * Possible values are:
1523: * <ul>
1524: * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format.
1525: * In this version, the <code>int</code> fields such as
1526: * <code>maximumIntegerDigits</code> were not present, and the <code>byte</code>
1527: * fields such as <code>maxIntegerDigits</code> are used instead.
1528: *
1529: * <li><b>1</b>: the JDK 1.2 version of the stream format. The values of the
1530: * <code>byte</code> fields such as <code>maxIntegerDigits</code> are ignored,
1531: * and the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1532: * are used instead.
1533: * </ul>
1534: * When streaming out a <code>NumberFormat</code>, the most recent format
1535: * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
1536: * is always written.
1537: *
1538: * @serial
1539: */
1540: private int serialVersionOnStream = currentSerialVersion;
1541:
1542: // Removed "implements Cloneable" clause. Needs to update serialization
1543: // ID for backward compatibility.
1544: private static final long serialVersionUID = -2308460125733713944L;
1545:
1546: /**
1547: * Empty constructor. Public for compatibily with JDK which lets the
1548: * compiler generate a default public constructor even though this is
1549: * an abstract class.
1550: * @stable ICU 2.6
1551: */
1552: public NumberFormat() {
1553: }
1554:
1555: // new in ICU4J 3.6
1556: private boolean parseStrict;
1557:
1558: //#ifndef FOUNDATION
1559: /**
1560: * [Spark/CDL] The instances of this inner class are used as attribute keys and values
1561: * in AttributedCharacterIterator that
1562: * NumberFormat.formatToCharacterIterator() method returns.
1563: * <p>
1564: * There is no public constructor to this class, the only instances are the
1565: * constants defined here.
1566: * <p>
1567: * @stable ICU 3.6
1568: */
1569: public static class Field extends Format.Field {
1570: // generated by serialver from JDK 1.4.1_01
1571: static final long serialVersionUID = -4516273749929385842L;
1572:
1573: /**
1574: * @stable ICU 3.6
1575: */
1576: public static final Field SIGN = new Field("sign");
1577:
1578: /**
1579: * @stable ICU 3.6
1580: */
1581: public static final Field INTEGER = new Field("integer");
1582:
1583: /**
1584: * @stable ICU 3.6
1585: */
1586: public static final Field FRACTION = new Field("fraction");
1587:
1588: /**
1589: * @stable ICU 3.6
1590: */
1591: public static final Field EXPONENT = new Field("exponent");
1592:
1593: /**
1594: * @stable ICU 3.6
1595: */
1596: public static final Field EXPONENT_SIGN = new Field(
1597: "exponent sign");
1598:
1599: /**
1600: * @stable ICU 3.6
1601: */
1602: public static final Field EXPONENT_SYMBOL = new Field(
1603: "exponent symbol");
1604:
1605: /**
1606: * @stable ICU 3.6
1607: */
1608: public static final Field DECIMAL_SEPARATOR = new Field(
1609: "decimal separator");
1610: /**
1611: * @stable ICU 3.6
1612: */
1613: public static final Field GROUPING_SEPARATOR = new Field(
1614: "grouping separator");
1615:
1616: /**
1617: * @stable ICU 3.6
1618: */
1619: public static final Field PERCENT = new Field("percent");
1620:
1621: /**
1622: * @stable ICU 3.6
1623: */
1624: public static final Field PERMILLE = new Field("per mille");
1625:
1626: /**
1627: * @stable ICU 3.6
1628: */
1629: public static final Field CURRENCY = new Field("currency");
1630:
1631: /**
1632: * Constructs a new instance of NumberFormat.Field with the given field
1633: * name.
1634: * @stable ICU 3.6
1635: */
1636: protected Field(String fieldName) {
1637: super (fieldName);
1638: }
1639:
1640: /**
1641: * serizalization method resolve instances to the constant
1642: * NumberFormat.Field values
1643: * @stable ICU 3.6
1644: */
1645: protected Object readResolve() throws InvalidObjectException {
1646: if (this .getName().equals(INTEGER.getName()))
1647: return INTEGER;
1648: if (this .getName().equals(FRACTION.getName()))
1649: return FRACTION;
1650: if (this .getName().equals(EXPONENT.getName()))
1651: return EXPONENT;
1652: if (this .getName().equals(EXPONENT_SIGN.getName()))
1653: return EXPONENT_SIGN;
1654: if (this .getName().equals(EXPONENT_SYMBOL.getName()))
1655: return EXPONENT_SYMBOL;
1656: if (this .getName().equals(CURRENCY.getName()))
1657: return CURRENCY;
1658: if (this .getName().equals(DECIMAL_SEPARATOR.getName()))
1659: return DECIMAL_SEPARATOR;
1660: if (this .getName().equals(GROUPING_SEPARATOR.getName()))
1661: return GROUPING_SEPARATOR;
1662: if (this .getName().equals(PERCENT.getName()))
1663: return PERCENT;
1664: if (this .getName().equals(PERMILLE.getName()))
1665: return PERMILLE;
1666: if (this .getName().equals(SIGN.getName()))
1667: return SIGN;
1668:
1669: throw new InvalidObjectException("An invalid object.");
1670: }
1671: }
1672: //#endif
1673: }
|