Source Code Cross Referenced for DecimalFormat.java in  » Internationalization-Localization » icu4j » com » ibm » icu » text » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Internationalization Localization » icu4j » com.ibm.icu.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.ObjectInputStream;
0012:        import java.io.ObjectOutputStream;
0013:        import java.math.BigInteger;
0014:        import java.text.AttributedCharacterIterator;
0015:        import java.text.AttributedString;
0016:        import java.text.ChoiceFormat;
0017:        import java.text.FieldPosition;
0018:        import java.text.Format;
0019:        import java.text.ParsePosition;
0020:        import java.util.ArrayList;
0021:
0022:        import com.ibm.icu.impl.UCharacterProperty;
0023:        import com.ibm.icu.lang.UCharacter;
0024:        import com.ibm.icu.math.BigDecimal;
0025:        import com.ibm.icu.util.Currency;
0026:        import com.ibm.icu.util.CurrencyAmount;
0027:        import com.ibm.icu.util.ULocale;
0028:
0029:        /**
0030:         * <code>DecimalFormat</code> is a concrete subclass of
0031:         * {@link NumberFormat} that formats decimal numbers. It has a variety of
0032:         * features designed to make it possible to parse and format numbers in any
0033:         * locale, including support for Western, Arabic, or Indic digits.  It also
0034:         * supports different flavors of numbers, including integers ("123"),
0035:         * fixed-point numbers ("123.4"), scientific notation ("1.23E4"), percentages
0036:         * ("12%"), and currency amounts ("$123").  All of these flavors can be easily
0037:         * localized.
0038:         *
0039:         * <p><strong>This is an enhanced version of <code>DecimalFormat</code> that
0040:         * is based on the standard version in the JDK.  New or changed functionality
0041:         * is labeled
0042:         * <strong><font face=helvetica color=red>NEW</font></strong> or
0043:         * <strong><font face=helvetica color=red>CHANGED</font></strong>.</strong>
0044:         *
0045:         * <p>To obtain a {@link NumberFormat} for a specific locale (including the
0046:         * default locale) call one of <code>NumberFormat</code>'s factory methods such
0047:         * as {@link NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code>
0048:         * constructors directly, unless you know what you are doing, since the
0049:         * {@link NumberFormat} factory methods may return subclasses other than
0050:         * <code>DecimalFormat</code>. If you need to customize the format object, do
0051:         * something like this:
0052:         *
0053:         * <blockquote><pre>
0054:         * NumberFormat f = NumberFormat.getInstance(loc);
0055:         * if (f instanceof DecimalFormat) {
0056:         *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
0057:         * }</pre></blockquote>
0058:         *
0059:         * <p><strong>Example Usage</strong>
0060:         *
0061:         * <blockquote><pre>
0062:         * <strong>// Print out a number using the localized number, currency,
0063:         * // and percent format for each locale</strong>
0064:         * Locale[] locales = NumberFormat.getAvailableLocales();
0065:         * double myNumber = -1234.56;
0066:         * NumberFormat format;
0067:         * for (int j=0; j<3; ++j) {
0068:         *     System.out.println("FORMAT");
0069:         *     for (int i = 0; i < locales.length; ++i) {
0070:         *         if (locales[i].getCountry().length() == 0) {
0071:         *            // Skip language-only locales
0072:         *            continue;
0073:         *         }
0074:         *         System.out.print(locales[i].getDisplayName());
0075:         *         switch (j) {
0076:         *         case 0:
0077:         *             format = NumberFormat.getInstance(locales[i]); break;
0078:         *         case 1:
0079:         *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
0080:         *         default:
0081:         *             format = NumberFormat.getPercentInstance(locales[i]); break;
0082:         *         }
0083:         *         try {
0084:         *             // Assume format is a DecimalFormat
0085:         *             System.out.print(": " + ((DecimalFormat) format).toPattern()
0086:         *                              + " -> " + form.format(myNumber));
0087:         *         } catch (Exception e) {}
0088:         *         try {
0089:         *             System.out.println(" -> " + format.parse(form.format(myNumber)));
0090:         *         } catch (ParseException e) {}
0091:         *     }
0092:         * }</pre></blockquote>
0093:         *
0094:         * <h4>Patterns</h4>
0095:         *
0096:         * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
0097:         * <em>symbols</em>.  The pattern may be set directly using
0098:         * {@link #applyPattern}, or indirectly using other API methods which
0099:         * manipulate aspects of the pattern, such as the minimum number of integer
0100:         * digits.  The symbols are stored in a {@link DecimalFormatSymbols}
0101:         * object.  When using the {@link NumberFormat} factory methods, the
0102:         * pattern and symbols are read from ICU's locale data.
0103:         * 
0104:         * <h4>Special Pattern Characters</h4>
0105:         *
0106:         * <p>Many characters in a pattern are taken literally; they are matched during
0107:         * parsing and output unchanged during formatting.  Special characters, on the
0108:         * other hand, stand for other characters, strings, or classes of characters.
0109:         * For example, the '#' character is replaced by a localized digit.  Often the
0110:         * replacement character is the same as the pattern character; in the U.S. locale,
0111:         * the ',' grouping character is replaced by ','.  However, the replacement is
0112:         * still happening, and if the symbols are modified, the grouping character
0113:         * changes.  Some special characters affect the behavior of the formatter by
0114:         * their presence; for example, if the percent character is seen, then the
0115:         * value is multiplied by 100 before being displayed.
0116:         *
0117:         * <p>To insert a special character in a pattern as a literal, that is, without
0118:         * any special meaning, the character must be quoted.  There are some exceptions to
0119:         * this which are noted below.
0120:         *
0121:         * <p>The characters listed here are used in non-localized patterns.  Localized
0122:         * patterns use the corresponding characters taken from this formatter's
0123:         * {@link DecimalFormatSymbols} object instead, and these characters lose
0124:         * their special status.  Two exceptions are the currency sign and quote, which
0125:         * are not localized.
0126:         *
0127:         * <blockquote>
0128:         * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
0129:         *  location, localized, and meaning.">
0130:         *   <tr bgcolor="#ccccff">
0131:         *     <th align=left>Symbol
0132:         *     <th align=left>Location
0133:         *     <th align=left>Localized?
0134:         *     <th align=left>Meaning
0135:         *   <tr valign=top>
0136:         *     <td><code>0</code>
0137:         *     <td>Number
0138:         *     <td>Yes
0139:         *     <td>Digit
0140:         *   <tr valign=top bgcolor="#eeeeff">
0141:         *     <td><code>1-9</code>
0142:         *     <td>Number
0143:         *     <td>Yes
0144:         *     <td><strong><font face=helvetica color=red>NEW</font></strong>
0145:         *         '1' through '9' indicate rounding.
0146:         *   <tr valign=top>
0147:         *     <td><code>@</code>
0148:         *     <td>Number
0149:         *     <td>No
0150:         *     <td><strong><font face=helvetica color=red>NEW</font></strong>
0151:         *         Significant digit
0152:         *   <tr valign=top bgcolor="#eeeeff">
0153:         *     <td><code>#</code>
0154:         *     <td>Number
0155:         *     <td>Yes
0156:         *     <td>Digit, zero shows as absent
0157:         *   <tr valign=top>
0158:         *     <td><code>.</code>
0159:         *     <td>Number
0160:         *     <td>Yes
0161:         *     <td>Decimal separator or monetary decimal separator
0162:         *   <tr valign=top bgcolor="#eeeeff">
0163:         *     <td><code>-</code>
0164:         *     <td>Number
0165:         *     <td>Yes
0166:         *     <td>Minus sign
0167:         *   <tr valign=top>
0168:         *     <td><code>,</code>
0169:         *     <td>Number
0170:         *     <td>Yes
0171:         *     <td>Grouping separator
0172:         *   <tr valign=top bgcolor="#eeeeff">
0173:         *     <td><code>E</code>
0174:         *     <td>Number
0175:         *     <td>Yes
0176:         *     <td>Separates mantissa and exponent in scientific notation.
0177:         *         <em>Need not be quoted in prefix or suffix.</em>
0178:         *   <tr valign=top>
0179:         *     <td><code>+</code>
0180:         *     <td>Exponent
0181:         *     <td>Yes
0182:         *     <td><strong><font face=helvetica color=red>NEW</font></strong>
0183:         *         Prefix positive exponents with localized plus sign.
0184:         *         <em>Need not be quoted in prefix or suffix.</em>
0185:         *   <tr valign=top bgcolor="#eeeeff">
0186:         *     <td><code>;</code>
0187:         *     <td>Subpattern boundary
0188:         *     <td>Yes
0189:         *     <td>Separates positive and negative subpatterns
0190:         *   <tr valign=top>
0191:         *     <td><code>%</code>
0192:         *     <td>Prefix or suffix
0193:         *     <td>Yes
0194:         *     <td>Multiply by 100 and show as percentage
0195:         *   <tr valign=top bgcolor="#eeeeff">
0196:         *     <td><code>&#92;u2030</code>
0197:         *     <td>Prefix or suffix
0198:         *     <td>Yes
0199:         *     <td>Multiply by 1000 and show as per mille
0200:         *   <tr valign=top>
0201:         *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
0202:         *     <td>Prefix or suffix
0203:         *     <td>No
0204:         *     <td>Currency sign, replaced by currency symbol.  If
0205:         *         doubled, replaced by international currency symbol.
0206:         *         If present in a pattern, the monetary decimal separator
0207:         *         is used instead of the decimal separator.
0208:         *   <tr valign=top bgcolor="#eeeeff">
0209:         *     <td><code>'</code>
0210:         *     <td>Prefix or suffix
0211:         *     <td>No
0212:         *     <td>Used to quote special characters in a prefix or suffix,
0213:         *         for example, <code>"'#'#"</code> formats 123 to
0214:         *         <code>"#123"</code>.  To create a single quote
0215:         *         itself, use two in a row: <code>"# o''clock"</code>.
0216:         *   <tr valign=top>
0217:         *     <td><code>*</code>
0218:         *     <td>Prefix or suffix boundary
0219:         *     <td>Yes
0220:         *     <td><strong><font face=helvetica color=red>NEW</font></strong>
0221:         *         Pad escape, precedes pad character
0222:         * </table>
0223:         * </blockquote>
0224:         *
0225:         * <p>A <code>DecimalFormat</code> pattern contains a postive and negative
0226:         * subpattern, for example, "#,##0.00;(#,##0.00)".  Each subpattern has a
0227:         * prefix, a numeric part, and a suffix.  If there is no explicit negative
0228:         * subpattern, the negative subpattern is the localized minus sign prefixed to the
0229:         * positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00".  If there
0230:         * is an explicit negative subpattern, it serves only to specify the negative
0231:         * prefix and suffix; the number of digits, minimal digits, and other
0232:         * characteristics are ignored in the negative subpattern. That means that
0233:         * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
0234:         *
0235:         * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
0236:         * thousands separators, decimal separators, etc. may be set to arbitrary
0237:         * values, and they will appear properly during formatting.  However, care must
0238:         * be taken that the symbols and strings do not conflict, or parsing will be
0239:         * unreliable.  For example, either the positive and negative prefixes or the
0240:         * suffixes must be distinct for {@link #parse} to be able
0241:         * to distinguish positive from negative values.  Another example is that the
0242:         * decimal separator and thousands separator should be distinct characters, or
0243:         * parsing will be impossible.
0244:         *
0245:         * <p>The <em>grouping separator</em> is a character that separates clusters of
0246:         * integer digits to make large numbers more legible.  It commonly used for
0247:         * thousands, but in some locales it separates ten-thousands.  The <em>grouping
0248:         * size</em> is the number of digits between the grouping separators, such as 3
0249:         * for "100,000,000" or 4 for "1 0000 0000". There are actually two different
0250:         * grouping sizes: One used for the least significant integer digits, the
0251:         * <em>primary grouping size</em>, and one used for all others, the
0252:         * <em>secondary grouping size</em>.  In most locales these are the same, but
0253:         * sometimes they are different. For example, if the primary grouping interval
0254:         * is 3, and the secondary is 2, then this corresponds to the pattern
0255:         * "#,##,##0", and the number 123456789 is formatted as "12,34,56,789".  If a
0256:         * pattern contains multiple grouping separators, the interval between the last
0257:         * one and the end of the integer defines the primary grouping size, and the
0258:         * interval between the last two defines the secondary grouping size. All others
0259:         * are ignored, so "#,##,###,####" == "###,###,####" == "##,#,###,####".
0260:         *
0261:         * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
0262:         * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException}
0263:         * with a message that describes the problem.
0264:         *
0265:         * <h4>Pattern BNF</h4>
0266:         *
0267:         * <pre>
0268:         * pattern    := subpattern (';' subpattern)?
0269:         * subpattern := prefix? number exponent? suffix?
0270:         * number     := (integer ('.' fraction)?) | sigDigits
0271:         * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
0272:         * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
0273:         * integer    := '#'* '0'* '0'
0274:         * fraction   := '0'* '#'*
0275:         * sigDigits  := '#'* '@' '@'* '#'*
0276:         * exponent   := 'E' '+'? '0'* '0'
0277:         * padSpec    := '*' padChar
0278:         * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
0279:         * &#32;
0280:         * Notation:
0281:         *   X*       0 or more instances of X
0282:         *   X?       0 or 1 instances of X
0283:         *   X|Y      either X or Y
0284:         *   C..D     any character from C up to D, inclusive
0285:         *   S-T      characters in S, except those in T
0286:         * </pre>
0287:         * The first subpattern is for positive numbers. The second (optional)
0288:         * subpattern is for negative numbers.
0289:         * 
0290:         * <p>Not indicated in the BNF syntax above:
0291:         *
0292:         * <ul><li>The grouping separator ',' can occur inside the integer and
0293:         * sigDigits elements, between any two pattern characters of that
0294:         * element, as long as the integer or sigDigits element is not
0295:         * followed by the exponent element.
0296:         *
0297:         * <li><font color=red face=helvetica><strong>NEW</strong></font>
0298:         *     Two grouping intervals are recognized: That between the
0299:         *     decimal point and the first grouping symbol, and that
0300:         *     between the first and second grouping symbols. These
0301:         *     intervals are identical in most locales, but in some
0302:         *     locales they differ. For example, the pattern
0303:         *     &quot;#,##,###&quot; formats the number 123456789 as
0304:         *     &quot;12,34,56,789&quot;.</li>
0305:         * 
0306:         * <li>
0307:         * <strong><font face=helvetica color=red>NEW</font></strong>
0308:         * The pad specifier <code>padSpec</code> may appear before the prefix,
0309:         * after the prefix, before the suffix, after the suffix, or not at all.
0310:         *
0311:         * <li>
0312:         * <strong><font face=helvetica color=red>NEW</font></strong>
0313:         * In place of '0', the digits '1' through '9' may be used to
0314:         * indicate a rounding increment.
0315:         * </ul>
0316:         *
0317:         * <h4>Parsing</h4>
0318:         *
0319:         * <p><code>DecimalFormat</code> parses all Unicode characters that represent
0320:         * decimal digits, as defined by {@link UCharacter#digit}.  In addition,
0321:         * <code>DecimalFormat</code> also recognizes as digits the ten consecutive
0322:         * characters starting with the localized zero digit defined in the
0323:         * {@link DecimalFormatSymbols} object.  During formatting, the
0324:         * {@link DecimalFormatSymbols}-based digits are output.
0325:         *
0326:         * <p>During parsing, grouping separators are ignored.
0327:         *
0328:         * <p>If {@link #parse(String, ParsePosition)} fails to parse
0329:         * a string, it returns <code>null</code> and leaves the parse position
0330:         * unchanged.  The convenience method {@link #parse(String)}
0331:         * indicates parse failure by throwing a {@link java.text.ParseException}.
0332:         *
0333:         * <h4>Formatting</h4>
0334:         *
0335:         * <p>Formatting is guided by several parameters, all of which can be
0336:         * specified either using a pattern or using the API.  The following
0337:         * description applies to formats that do not use <a href="#sci">scientific
0338:         * notation</a> or <a href="#sigdig">significant digits</a>.
0339:         *
0340:         * <ul><li>If the number of actual integer digits exceeds the
0341:         * <em>maximum integer digits</em>, then only the least significant
0342:         * digits are shown.  For example, 1997 is formatted as "97" if the
0343:         * maximum integer digits is set to 2.
0344:         *
0345:         * <li>If the number of actual integer digits is less than the
0346:         * <em>minimum integer digits</em>, then leading zeros are added.  For
0347:         * example, 1997 is formatted as "01997" if the minimum integer digits
0348:         * is set to 5.
0349:         *
0350:         * <li>If the number of actual fraction digits exceeds the <em>maximum
0351:         * fraction digits</em>, then half-even rounding it performed to the
0352:         * maximum fraction digits.  For example, 0.125 is formatted as "0.12"
0353:         * if the maximum fraction digits is 2.  This behavior can be changed
0354:         * by specifying a rounding increment and a rounding mode.
0355:         *
0356:         * <li>If the number of actual fraction digits is less than the
0357:         * <em>minimum fraction digits</em>, then trailing zeros are added.
0358:         * For example, 0.125 is formatted as "0.1250" if the mimimum fraction
0359:         * digits is set to 4.
0360:         *
0361:         * <li>Trailing fractional zeros are not displayed if they occur
0362:         * <em>j</em> positions after the decimal, where <em>j</em> is less
0363:         * than the maximum fraction digits. For example, 0.10004 is
0364:         * formatted as "0.1" if the maximum fraction digits is four or less.
0365:         * </ul>
0366:         * 
0367:         * <p><strong>Special Values</strong>
0368:         *
0369:         * <p><code>NaN</code> is represented as a single character, typically
0370:         * <code>&#92;uFFFD</code>.  This character is determined by the
0371:         * {@link DecimalFormatSymbols} object.  This is the only value for which
0372:         * the prefixes and suffixes are not used.
0373:         *
0374:         * <p>Infinity is represented as a single character, typically
0375:         * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
0376:         * applied.  The infinity character is determined by the
0377:         * {@link DecimalFormatSymbols} object.
0378:         *
0379:         * <a name="sci"><h4>Scientific Notation</h4></a>
0380:         *
0381:         * <p>Numbers in scientific notation are expressed as the product of a mantissa
0382:         * and a power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
0383:         * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
0384:         * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
0385:         * <code>DecimalFormat</code> can be instructed to use scientific
0386:         * notation through the API or through the pattern.  In a pattern, the exponent
0387:         * character immediately followed by one or more digit characters indicates
0388:         * scientific notation.  Example: "0.###E0" formats the number 1234 as
0389:         * "1.234E3".
0390:         *
0391:         * <ul>
0392:         * <li>The number of digit characters after the exponent character gives the
0393:         * minimum exponent digit count.  There is no maximum.  Negative exponents are
0394:         * formatted using the localized minus sign, <em>not</em> the prefix and suffix
0395:         * from the pattern.  This allows patterns such as "0.###E0 m/s".  To prefix
0396:         * positive exponents with a localized plus sign, specify '+' between the
0397:         * exponent and the digits: "0.###E+0" will produce formats "1E+1", "1E+0",
0398:         * "1E-1", etc.  (In localized patterns, use the localized plus sign rather than
0399:         * '+'.)
0400:         *
0401:         * <li>The minimum number of integer digits is achieved by adjusting the
0402:         * exponent.  Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This
0403:         * only happens if there is no maximum number of integer digits.  If there is a
0404:         * maximum, then the minimum number of integer digits is fixed at one.
0405:         *
0406:         * <li>The maximum number of integer digits, if present, specifies the exponent
0407:         * grouping.  The most common use of this is to generate <em>engineering
0408:         * notation</em>, in which the exponent is a multiple of three, e.g.,
0409:         * "##0.###E0".  The number 12345 is formatted using "##0.####E0" as "12.345E3".
0410:         *
0411:         * <li>When using scientific notation, the formatter controls the
0412:         * digit counts using significant digits logic.  The maximum number of
0413:         * significant digits limits the total number of integer and fraction
0414:         * digits that will be shown in the mantissa; it does not affect
0415:         * parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".
0416:         * See the section on significant digits for more details.
0417:         *
0418:         * <li>The number of significant digits shown is determined as
0419:         * follows: If areSignificantDigitsUsed() returns false, then the
0420:         * minimum number of significant digits shown is one, and the maximum
0421:         * number of significant digits shown is the sum of the <em>minimum
0422:         * integer</em> and <em>maximum fraction</em> digits, and is
0423:         * unaffected by the maximum integer digits.  If this sum is zero,
0424:         * then all significant digits are shown.  If
0425:         * areSignificantDigitsUsed() returns true, then the significant digit
0426:         * counts are specified by getMinimumSignificantDigits() and
0427:         * getMaximumSignificantDigits().  In this case, the number of
0428:         * integer digits is fixed at one, and there is no exponent grouping.
0429:         *
0430:         * <li>Exponential patterns may not contain grouping separators.
0431:         * </ul>
0432:         *
0433:         * <a name="sigdig"><h4>
0434:         * <strong><font face=helvetica color=red>NEW</font></strong>
0435:         * Significant Digits</h4></a>
0436:         *
0437:         * <code>DecimalFormat</code> has two ways of controlling how many
0438:         * digits are shows: (a) significant digits counts, or (b) integer and
0439:         * fraction digit counts.  Integer and fraction digit counts are
0440:         * described above.  When a formatter is using significant digits
0441:         * counts, the number of integer and fraction digits is not specified
0442:         * directly, and the formatter settings for these counts are ignored.
0443:         * Instead, the formatter uses however many integer and fraction
0444:         * digits are required to display the specified number of significant
0445:         * digits.  Examples:
0446:         *
0447:         * <blockquote>
0448:         * <table border=0 cellspacing=3 cellpadding=0>
0449:         *   <tr bgcolor="#ccccff">
0450:         *     <th align=left>Pattern
0451:         *     <th align=left>Minimum significant digits
0452:         *     <th align=left>Maximum significant digits
0453:         *     <th align=left>Number
0454:         *     <th align=left>Output of format()
0455:         *   <tr valign=top>
0456:         *     <td><code>@@@</code>
0457:         *     <td>3
0458:         *     <td>3
0459:         *     <td>12345
0460:         *     <td><code>12300</code>
0461:         *   <tr valign=top bgcolor="#eeeeff">
0462:         *     <td><code>@@@</code>
0463:         *     <td>3
0464:         *     <td>3
0465:         *     <td>0.12345
0466:         *     <td><code>0.123</code>
0467:         *   <tr valign=top>
0468:         *     <td><code>@@##</code>
0469:         *     <td>2
0470:         *     <td>4
0471:         *     <td>3.14159
0472:         *     <td><code>3.142</code>
0473:         *   <tr valign=top bgcolor="#eeeeff">
0474:         *     <td><code>@@##</code>
0475:         *     <td>2
0476:         *     <td>4
0477:         *     <td>1.23004
0478:         *     <td><code>1.23</code>
0479:         * </table>
0480:         * </blockquote>
0481:         *
0482:         * <ul>
0483:         * <li>Significant digit counts may be expressed using patterns that
0484:         * specify a minimum and maximum number of significant digits.  These
0485:         * are indicated by the <code>'@'</code> and <code>'#'</code>
0486:         * characters.  The minimum number of significant digits is the number
0487:         * of <code>'@'</code> characters.  The maximum number of significant
0488:         * digits is the number of <code>'@'</code> characters plus the number
0489:         * of <code>'#'</code> characters following on the right.  For
0490:         * example, the pattern <code>"@@@"</code> indicates exactly 3
0491:         * significant digits.  The pattern <code>"@##"</code> indicates from
0492:         * 1 to 3 significant digits.  Trailing zero digits to the right of
0493:         * the decimal separator are suppressed after the minimum number of
0494:         * significant digits have been shown.  For example, the pattern
0495:         * <code>"@##"</code> formats the number 0.1203 as
0496:         * <code>"0.12"</code>.
0497:         *
0498:         * <li>If a pattern uses significant digits, it may not contain a
0499:         * decimal separator, nor the <code>'0'</code> pattern character.
0500:         * Patterns such as <code>"@00"</code> or <code>"@.###"</code> are
0501:         * disallowed.
0502:         *
0503:         * <li>Any number of <code>'#'</code> characters may be prepended to
0504:         * the left of the leftmost <code>'@'</code> character.  These have no
0505:         * effect on the minimum and maximum significant digits counts, but
0506:         * may be used to position grouping separators.  For example,
0507:         * <code>"#,#@#"</code> indicates a minimum of one significant digits,
0508:         * a maximum of two significant digits, and a grouping size of three.
0509:         *
0510:         * <li>In order to enable significant digits formatting, use a pattern
0511:         * containing the <code>'@'</code> pattern character.  Alternatively,
0512:         * call {@link #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
0513:         *
0514:         * <li>In order to disable significant digits formatting, use a
0515:         * pattern that does not contain the <code>'@'</code> pattern
0516:         * character. Alternatively, call {@link #setSignificantDigitsUsed
0517:         * setSignificantDigitsUsed(false)}.
0518:         *
0519:         * <li>The number of significant digits has no effect on parsing.
0520:         *
0521:         * <li>Significant digits may be used together with exponential notation. Such
0522:         * patterns are equivalent to a normal exponential pattern with a minimum and
0523:         * maximum integer digit count of one, a minimum fraction digit count of
0524:         * <code>getMinimumSignificantDigits() - 1</code>, and a maximum fraction digit
0525:         * count of <code>getMaximumSignificantDigits() - 1</code>. For example, the
0526:         * pattern <code>"@@###E0"</code> is equivalent to <code>"0.0###E0"</code>.
0527:         *
0528:         * <li>If signficant digits are in use, then the integer and fraction
0529:         * digit counts, as set via the API, are ignored.  If significant
0530:         * digits are not in use, then the signficant digit counts, as set via
0531:         * the API, are ignored.
0532:         *
0533:         * </ul>
0534:         * 
0535:         * <h4>
0536:         * <strong><font face=helvetica color=red>NEW</font></strong>
0537:         * Padding</h4>
0538:         *
0539:         * <p><code>DecimalFormat</code> supports padding the result of
0540:         * {@link #format} to a specific width.  Padding may be specified either
0541:         * through the API or through the pattern syntax.  In a pattern the pad escape
0542:         * character, followed by a single pad character, causes padding to be parsed
0543:         * and formatted.  The pad escape character is '*' in unlocalized patterns, and
0544:         * can be localized using {@link DecimalFormatSymbols#setPadEscape}.  For
0545:         * example, <code>"$*x#,##0.00"</code> formats 123 to <code>"$xx123.00"</code>,
0546:         * and 1234 to <code>"$1,234.00"</code>.
0547:         *
0548:         * <ul>
0549:         * <li>When padding is in effect, the width of the positive subpattern,
0550:         * including prefix and suffix, determines the format width.  For example, in
0551:         * the pattern <code>"* #0 o''clock"</code>, the format width is 10.
0552:         *
0553:         * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
0554:         *
0555:         * <li>Some parameters which usually do not matter have meaning when padding is
0556:         * used, because the pattern width is significant with padding.  In the pattern
0557:         * "* ##,##,#,##0.##", the format width is 14.  The initial characters "##,##,"
0558:         * do not affect the grouping size or maximum integer digits, but they do affect
0559:         * the format width.
0560:         *
0561:         * <li>Padding may be inserted at one of four locations: before the prefix,
0562:         * after the prefix, before the suffix, or after the suffix.  If padding is
0563:         * specified in any other location, {@link #applyPattern} throws an {@link
0564:         * IllegalArgumentException}.  If there is no prefix, before the
0565:         * prefix and after the prefix are equivalent, likewise for the suffix.
0566:         *
0567:         * <li>When specified in a pattern, the 16-bit <code>char</code> immediately
0568:         * following the pad escape is the pad character. This may be any character,
0569:         * including a special pattern character. That is, the pad escape
0570:         * <em>escapes</em> the following character. If there is no character after
0571:         * the pad escape, then the pattern is illegal.
0572:         *
0573:         * </ul>
0574:         *
0575:         * <p>
0576:         * <strong><font face=helvetica color=red>NEW</font></strong>
0577:         * <strong>Rounding</strong>
0578:         *
0579:         * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For
0580:         * example, 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the
0581:         * nearest 0.65 is 1.3.  The rounding increment may be specified through the API
0582:         * or in a pattern.  To specify a rounding increment in a pattern, include the
0583:         * increment in the pattern itself.  "#,#50" specifies a rounding increment of
0584:         * 50.  "#,##0.05" specifies a rounding increment of 0.05.
0585:         *
0586:         * <ul>
0587:         * <li>Rounding only affects the string produced by formatting.  It does
0588:         * not affect parsing or change any numerical values.
0589:         *
0590:         * <li>A <em>rounding mode</em> determines how values are rounded; see the
0591:         * {@link com.ibm.icu.math.BigDecimal} documentation for a description of the
0592:         * modes.  Rounding increments specified in patterns use the default mode,
0593:         * {@link com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
0594:         *
0595:         * <li>Some locales use rounding in their currency formats to reflect the
0596:         * smallest currency denomination.
0597:         *
0598:         * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise
0599:         * behave identically to digit '0'.
0600:         * </ul>
0601:         *
0602:         * <h4>Synchronization</h4>
0603:         *
0604:         * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple
0605:         * threads should not access one formatter concurrently.
0606:         *
0607:         * @see          java.text.Format
0608:         * @see          NumberFormat
0609:         * @author       Mark Davis
0610:         * @author       Alan Liu
0611:         * @stable ICU 2.0
0612:         */
0613:        public class DecimalFormat extends NumberFormat {
0614:
0615:            /**
0616:             * Create a DecimalFormat using the default pattern and symbols
0617:             * for the default locale. This is a convenient way to obtain a
0618:             * DecimalFormat when internationalization is not the main concern.
0619:             * <p>
0620:             * To obtain standard formats for a given locale, use the factory methods
0621:             * on NumberFormat such as getNumberInstance. These factories will
0622:             * return the most appropriate sub-class of NumberFormat for a given
0623:             * locale.
0624:             * @see NumberFormat#getInstance
0625:             * @see NumberFormat#getNumberInstance
0626:             * @see NumberFormat#getCurrencyInstance
0627:             * @see NumberFormat#getPercentInstance
0628:             * @stable ICU 2.0
0629:             */
0630:            public DecimalFormat() {
0631:                // [NEW]
0632:                ULocale def = ULocale.getDefault();
0633:                String pattern = getPattern(def, 0);
0634:                // Always applyPattern after the symbols are set
0635:                this .symbols = new DecimalFormatSymbols(def);
0636:                setCurrency(Currency.getInstance(def));
0637:                applyPattern(pattern, false);
0638:            }
0639:
0640:            /**
0641:             * Create a DecimalFormat from the given pattern and the symbols
0642:             * for the default locale. This is a convenient way to obtain a
0643:             * DecimalFormat when internationalization is not the main concern.
0644:             * <p>
0645:             * To obtain standard formats for a given locale, use the factory methods
0646:             * on NumberFormat such as getNumberInstance. These factories will
0647:             * return the most appropriate sub-class of NumberFormat for a given
0648:             * locale.
0649:             * @param pattern A non-localized pattern string.
0650:             * @exception IllegalArgumentException if the given pattern is invalid.
0651:             * @see NumberFormat#getInstance
0652:             * @see NumberFormat#getNumberInstance
0653:             * @see NumberFormat#getCurrencyInstance
0654:             * @see NumberFormat#getPercentInstance
0655:             * @stable ICU 2.0
0656:             */
0657:            public DecimalFormat(String pattern) {
0658:                // Always applyPattern after the symbols are set
0659:                ULocale def = ULocale.getDefault();
0660:                this .symbols = new DecimalFormatSymbols(def);
0661:                setCurrency(Currency.getInstance(def));
0662:                applyPattern(pattern, false);
0663:            }
0664:
0665:            /**
0666:             * Create a DecimalFormat from the given pattern and symbols.
0667:             * Use this constructor when you need to completely customize the
0668:             * behavior of the format.
0669:             * <p>
0670:             * To obtain standard formats for a given
0671:             * locale, use the factory methods on NumberFormat such as
0672:             * getInstance or getCurrencyInstance. If you need only minor adjustments
0673:             * to a standard format, you can modify the format returned by
0674:             * a NumberFormat factory method.
0675:             * @param pattern a non-localized pattern string
0676:             * @param symbols the set of symbols to be used
0677:             * @exception IllegalArgumentException if the given pattern is invalid
0678:             * @see NumberFormat#getInstance
0679:             * @see NumberFormat#getNumberInstance
0680:             * @see NumberFormat#getCurrencyInstance
0681:             * @see NumberFormat#getPercentInstance
0682:             * @see DecimalFormatSymbols
0683:             * @stable ICU 2.0
0684:             */
0685:            public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
0686:                // Always applyPattern after the symbols are set
0687:                this .symbols = (DecimalFormatSymbols) symbols.clone();
0688:                setCurrencyForSymbols();
0689:                applyPattern(pattern, false);
0690:            }
0691:
0692:            /**
0693:             * @stable ICU 2.0
0694:             */
0695:            public StringBuffer format(double number, StringBuffer result,
0696:                    FieldPosition fieldPosition) {
0697:                return format(number, result, fieldPosition, false);
0698:            }
0699:
0700:            // [Spark/CDL] The actual method to format number. If boolean value
0701:            // parseAttr == true, then attribute information will be recorded.
0702:            private StringBuffer format(double number, StringBuffer result,
0703:                    FieldPosition fieldPosition, boolean parseAttr) {
0704:                fieldPosition.setBeginIndex(0);
0705:                fieldPosition.setEndIndex(0);
0706:
0707:                if (Double.isNaN(number)) {
0708:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
0709:                        fieldPosition.setBeginIndex(result.length());
0710:                    }
0711:
0712:                    result.append(symbols.getNaN());
0713:                    // [Spark/CDL] Add attribute for NaN here.
0714:                    // result.append(symbols.getNaN());
0715:                    //#ifndef FOUNDATION
0716:                    if (parseAttr) {
0717:                        addAttribute(Field.INTEGER, result.length()
0718:                                - symbols.getNaN().length(), result.length());
0719:                    }
0720:                    //#endif
0721:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
0722:                        fieldPosition.setEndIndex(result.length());
0723:                    }
0724:
0725:                    addPadding(result, fieldPosition, 0, 0);
0726:                    return result;
0727:                }
0728:
0729:                /* Detecting whether a double is negative is easy with the exception of
0730:                 * the value -0.0.  This is a double which has a zero mantissa (and
0731:                 * exponent), but a negative sign bit.  It is semantically distinct from
0732:                 * a zero with a positive sign bit, and this distinction is important
0733:                 * to certain kinds of computations.  However, it's a little tricky to
0734:                 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0).  How then, you may
0735:                 * ask, does it behave distinctly from +0.0?  Well, 1/(-0.0) ==
0736:                 * -Infinity.  Proper detection of -0.0 is needed to deal with the
0737:                 * issues raised by bugs 4106658, 4106667, and 4147706.  Liu 7/6/98.
0738:                 */
0739:                boolean isNegative = (number < 0.0)
0740:                        || (number == 0.0 && 1 / number < 0.0);
0741:                if (isNegative)
0742:                    number = -number;
0743:
0744:                // Do this BEFORE checking to see if value is infinite!
0745:                if (multiplier != 1)
0746:                    number *= multiplier;
0747:
0748:                // Apply rounding after multiplier
0749:                if (roundingDouble > 0.0) {
0750:                    // number = roundingDouble
0751:                    //  * round(number / roundingDouble, roundingMode, isNegative);
0752:                    double newNumber = round(number, roundingDouble,
0753:                            roundingDoubleReciprocal, roundingMode, isNegative);
0754:                    if (newNumber == 0.0 && number != newNumber)
0755:                        isNegative = false; // if we touched it, then make zero be zero.
0756:                    number = newNumber;
0757:                }
0758:
0759:                if (Double.isInfinite(number)) {
0760:                    int prefixLen = appendAffix(result, isNegative, true,
0761:                            parseAttr);
0762:
0763:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
0764:                        fieldPosition.setBeginIndex(result.length());
0765:                    }
0766:
0767:                    // [Spark/CDL] Add attribute for infinity here.
0768:                    result.append(symbols.getInfinity());
0769:                    //#ifndef FOUNDATION
0770:                    if (parseAttr) {
0771:                        addAttribute(Field.INTEGER, result.length()
0772:                                - symbols.getInfinity().length(), result
0773:                                .length());
0774:                    }
0775:                    //#endif
0776:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
0777:                        fieldPosition.setEndIndex(result.length());
0778:                    }
0779:
0780:                    int suffixLen = appendAffix(result, isNegative, false,
0781:                            parseAttr);
0782:
0783:                    addPadding(result, fieldPosition, prefixLen, suffixLen);
0784:                    return result;
0785:                }
0786:
0787:                // At this point we are guaranteed a nonnegative finite
0788:                // number.
0789:                synchronized (digitList) {
0790:                    digitList.set(number, precision(false),
0791:                            !useExponentialNotation
0792:                                    && !areSignificantDigitsUsed());
0793:                    return subformat(result, fieldPosition, isNegative, false,
0794:                            parseAttr);
0795:                }
0796:            }
0797:
0798:            /**
0799:             * <strong><font face=helvetica color=red>NEW</font></strong>
0800:             * Round a double value to the nearest multiple of the given
0801:             * rounding increment, according to the given mode.  This is
0802:             * equivalent to rounding value/roundingInc to the nearest
0803:             * integer, according to the given mode, and returning that
0804:             * integer * roundingInc.
0805:             * Note this is changed from the version in 2.4, since division of doubles
0806:             * have inaccuracies. jitterbug 1871.
0807:             * @param number the absolute value of the number to be rounded
0808:             * @param roundingInc the rounding increment
0809:             * @param roundingIncReciprocal if non-zero, is the 
0810:             * @param mode a BigDecimal rounding mode
0811:             * @param isNegative true if the number to be rounded is negative
0812:             * @return the absolute value of the rounded result
0813:             */
0814:            private static double round(double number, double roundingInc,
0815:                    double roundingIncReciprocal, int mode, boolean isNegative) {
0816:
0817:                double div = roundingIncReciprocal == 0.0 ? number
0818:                        / roundingInc : number * roundingIncReciprocal;
0819:
0820:                // do the absolute cases first
0821:
0822:                switch (mode) {
0823:                case BigDecimal.ROUND_CEILING:
0824:                    div = (isNegative ? Math.floor(div + epsilon) : Math
0825:                            .ceil(div - epsilon));
0826:                    break;
0827:                case BigDecimal.ROUND_FLOOR:
0828:                    div = (isNegative ? Math.ceil(div - epsilon) : Math
0829:                            .floor(div + epsilon));
0830:                    break;
0831:                case BigDecimal.ROUND_DOWN:
0832:                    div = (Math.floor(div + epsilon));
0833:                    break;
0834:                case BigDecimal.ROUND_UP:
0835:                    div = (Math.ceil(div - epsilon));
0836:                    break;
0837:                case BigDecimal.ROUND_UNNECESSARY:
0838:                    if (div != Math.floor(div)) {
0839:                        throw new ArithmeticException("Rounding necessary");
0840:                    }
0841:                    return number;
0842:                default:
0843:
0844:                    // Handle complex cases, where the choice depends on the closer value.
0845:
0846:                    // We figure out the distances to the two possible values, ceiling and floor.
0847:                    // We then go for the diff that is smaller.
0848:                    // Only if they are equal does the mode matter.
0849:
0850:                    double ceil = Math.ceil(div);
0851:                    double ceildiff = ceil - div; // (ceil * roundingInc) - number;
0852:                    double floor = Math.floor(div);
0853:                    double floordiff = div - floor; // number - (floor * roundingInc);
0854:
0855:                    // Note that the diff values were those mapped back to the "normal" space
0856:                    // by using the roundingInc. I don't have access to the original author of the code
0857:                    // but suspect that that was to produce better result in edge cases because of machine
0858:                    // precision, rather than simply using the difference between, say, ceil and div.
0859:                    // However, it didn't work in all cases. Am trying instead using an epsilon value.
0860:
0861:                    switch (mode) {
0862:                    case BigDecimal.ROUND_HALF_EVEN:
0863:                        // We should be able to just return Math.rint(a), but this
0864:                        // doesn't work in some VMs.
0865:                        // if one is smaller than the other, take the corresponding side
0866:                        if (floordiff + epsilon < ceildiff) {
0867:                            div = floor;
0868:                        } else if (ceildiff + epsilon < floordiff) {
0869:                            div = ceil;
0870:                        } else { // they are equal, so we want to round to whichever is even
0871:                            double testFloor = floor / 2;
0872:                            div = (testFloor == Math.floor(testFloor)) ? floor
0873:                                    : ceil;
0874:                        }
0875:                        break;
0876:                    case BigDecimal.ROUND_HALF_DOWN:
0877:                        div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
0878:                        break;
0879:                    case BigDecimal.ROUND_HALF_UP:
0880:                        div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
0881:                        break;
0882:                    default:
0883:                        throw new IllegalArgumentException(
0884:                                "Invalid rounding mode: " + mode);
0885:                    }
0886:                }
0887:                number = roundingIncReciprocal == 0.0 ? div * roundingInc : div
0888:                        / roundingIncReciprocal;
0889:                return number;
0890:            }
0891:
0892:            private static double epsilon = 0.00000000001;
0893:
0894:            /**
0895:             * @stable ICU 2.0
0896:             */
0897:            // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
0898:            public StringBuffer format(long number, StringBuffer result,
0899:                    FieldPosition fieldPosition) {
0900:                return format(number, result, fieldPosition, false);
0901:            }
0902:
0903:            private StringBuffer format(long number, StringBuffer result,
0904:                    FieldPosition fieldPosition, boolean parseAttr) {
0905:                fieldPosition.setBeginIndex(0);
0906:                fieldPosition.setEndIndex(0);
0907:
0908:                // If we are to do rounding, we need to move into the BigDecimal
0909:                // domain in order to do divide/multiply correctly.
0910:                // [NEW]
0911:                if (roundingIncrementICU != null) {
0912:                    return format(BigDecimal.valueOf(number), result,
0913:                            fieldPosition);
0914:                }
0915:
0916:                boolean isNegative = (number < 0);
0917:                if (isNegative)
0918:                    number = -number;
0919:
0920:                // In general, long values always represent real finite numbers, so
0921:                // we don't have to check for +/- Infinity or NaN.  However, there
0922:                // is one case we have to be careful of:  The multiplier can push
0923:                // a number near MIN_VALUE or MAX_VALUE outside the legal range.  We
0924:                // check for this before multiplying, and if it happens we use BigInteger
0925:                // instead.
0926:                // [NEW]
0927:                if (multiplier != 1) {
0928:                    boolean tooBig = false;
0929:                    if (number < 0) { // This can only happen if number == Long.MIN_VALUE
0930:                        long cutoff = Long.MIN_VALUE / multiplier;
0931:                        tooBig = (number < cutoff);
0932:                    } else {
0933:                        long cutoff = Long.MAX_VALUE / multiplier;
0934:                        tooBig = (number > cutoff);
0935:                    }
0936:                    if (tooBig) {
0937:                        // [Spark/CDL] Use
0938:                        // format_BigInteger_StringBuffer_FieldPosition_boolean instead
0939:                        // parseAttr is used to judge whether to synthesize attributes.
0940:                        return format(BigInteger.valueOf(isNegative ? -number
0941:                                : number), result, fieldPosition, parseAttr);
0942:                    }
0943:                }
0944:
0945:                number *= multiplier;
0946:                synchronized (digitList) {
0947:                    digitList.set(number, precision(true));
0948:                    return subformat(result, fieldPosition, isNegative, true,
0949:                            parseAttr);
0950:                }
0951:            }
0952:
0953:            /**
0954:             * <strong><font face=helvetica color=red>NEW</font></strong> Format a
0955:             * BigInteger number.
0956:             * 
0957:             * @stable ICU 2.0
0958:             */
0959:            public StringBuffer format(BigInteger number, StringBuffer result,
0960:                    FieldPosition fieldPosition) {
0961:                return format(number, result, fieldPosition, false);
0962:            }
0963:
0964:            // [Spark/CDL] 
0965:            private StringBuffer format(BigInteger number, StringBuffer result,
0966:                    FieldPosition fieldPosition, boolean parseAttr) {
0967:                // If we are to do rounding, we need to move into the BigDecimal
0968:                // domain in order to do divide/multiply correctly.
0969:                if (roundingIncrementICU != null) {
0970:                    return format(new BigDecimal(number), result, fieldPosition);
0971:                }
0972:
0973:                if (multiplier != 1) {
0974:                    number = number.multiply(BigInteger.valueOf(multiplier));
0975:                }
0976:
0977:                // At this point we are guaranteed a nonnegative finite
0978:                // number.
0979:                synchronized (digitList) {
0980:                    digitList.set(number, precision(true));
0981:                    return subformat(result, fieldPosition,
0982:                            number.signum() < 0, false, parseAttr);
0983:                }
0984:            }
0985:
0986:            //#ifndef FOUNDATION
0987:            /**
0988:             * <strong><font face=helvetica color=red>NEW</font></strong>
0989:             * Format a BigDecimal number.
0990:             * @stable ICU 2.0
0991:             */
0992:            public StringBuffer format(java.math.BigDecimal number,
0993:                    StringBuffer result, FieldPosition fieldPosition) {
0994:                return format(number, result, fieldPosition, false);
0995:            }
0996:
0997:            private StringBuffer format(java.math.BigDecimal number,
0998:                    StringBuffer result, FieldPosition fieldPosition,
0999:                    boolean parseAttr) {
1000:                if (multiplier != 1) {
1001:                    number = number.multiply(java.math.BigDecimal
1002:                            .valueOf(multiplier));
1003:                }
1004:
1005:                if (roundingIncrement != null) {
1006:                    number = number.divide(roundingIncrement, 0, roundingMode)
1007:                            .multiply(roundingIncrement);
1008:                }
1009:
1010:                synchronized (digitList) {
1011:                    digitList.set(number, precision(false),
1012:                            !useExponentialNotation
1013:                                    && !areSignificantDigitsUsed());
1014:                    return subformat(result, fieldPosition,
1015:                            number.signum() < 0, false, parseAttr);
1016:                }
1017:            }
1018:
1019:            //#endif
1020:
1021:            /**
1022:             * <strong><font face=helvetica color=red>NEW</font></strong>
1023:             * Format a BigDecimal number.
1024:             * @stable ICU 2.0
1025:             */
1026:            public StringBuffer format(BigDecimal number, StringBuffer result,
1027:                    FieldPosition fieldPosition) {
1028:                /* This method is just a copy of the corresponding java.math.BigDecimal
1029:                 * method for now.  It isn't very efficient since it must create a
1030:                 * conversion object to do math on the rounding increment.  In the
1031:                 * future we may try to clean this up, or even better, limit our support
1032:                 * to just one flavor of BigDecimal.
1033:                 */
1034:                if (multiplier != 1) {
1035:                    number = number.multiply(BigDecimal.valueOf(multiplier));
1036:                }
1037:
1038:                if (roundingIncrementICU != null) {
1039:                    number = number.divide(roundingIncrementICU, 0,
1040:                            roundingMode).multiply(roundingIncrementICU);
1041:                }
1042:
1043:                synchronized (digitList) {
1044:                    digitList.set(number, precision(false),
1045:                            !useExponentialNotation
1046:                                    && !areSignificantDigitsUsed());
1047:                    return subformat(result, fieldPosition,
1048:                            number.signum() < 0, false);
1049:                }
1050:            }
1051:
1052:            /**
1053:             * Return true if a grouping separator belongs at the given
1054:             * position, based on whether grouping is in use and the values of
1055:             * the primary and secondary grouping interval.
1056:             * @param pos the number of integer digits to the right of
1057:             * the current position.  Zero indicates the position after the
1058:             * rightmost integer digit.
1059:             * @return true if a grouping character belongs at the current
1060:             * position.
1061:             */
1062:            private boolean isGroupingPosition(int pos) {
1063:                boolean result = false;
1064:                if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
1065:                    if ((groupingSize2 > 0) && (pos > groupingSize)) {
1066:                        result = ((pos - groupingSize) % groupingSize2) == 0;
1067:                    } else {
1068:                        result = pos % groupingSize == 0;
1069:                    }
1070:                }
1071:                return result;
1072:            }
1073:
1074:            /**
1075:             * Return the number of fraction digits to display, or the total
1076:             * number of digits for significant digit formats and exponential
1077:             * formats.
1078:             */
1079:            private int precision(boolean isIntegral) {
1080:                if (areSignificantDigitsUsed()) {
1081:                    return getMaximumSignificantDigits();
1082:                } else if (useExponentialNotation) {
1083:                    return getMinimumIntegerDigits()
1084:                            + getMaximumFractionDigits();
1085:                } else {
1086:                    return isIntegral ? 0 : getMaximumFractionDigits();
1087:                }
1088:            }
1089:
1090:            /**
1091:             * Complete the formatting of a finite number.  On entry, the digitList must
1092:             * be filled in with the correct digits.
1093:             */
1094:            private StringBuffer subformat(StringBuffer result,
1095:                    FieldPosition fieldPosition, boolean isNegative,
1096:                    boolean isInteger) {
1097:                return subformat(result, fieldPosition, isNegative, isInteger,
1098:                        false);
1099:            }
1100:
1101:            private StringBuffer subformat(StringBuffer result,
1102:                    FieldPosition fieldPosition, boolean isNegative,
1103:                    boolean isInteger, boolean parseAttr) {
1104:                // NOTE: This isn't required anymore because DigitList takes care of this.
1105:                //
1106:                //  // The negative of the exponent represents the number of leading
1107:                //  // zeros between the decimal and the first non-zero digit, for
1108:                //  // a value < 0.1 (e.g., for 0.00123, -fExponent == 2).  If this
1109:                //  // is more than the maximum fraction digits, then we have an underflow
1110:                //  // for the printed representation.  We recognize this here and set
1111:                //  // the DigitList representation to zero in this situation.
1112:                //
1113:                //  if (-digitList.decimalAt >= getMaximumFractionDigits())
1114:                //  {
1115:                //      digitList.count = 0;
1116:                //  }
1117:
1118:                int i;
1119:                char zero = symbols.getZeroDigit();
1120:                int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
1121:                char grouping = isCurrencyFormat ? symbols
1122:                        .getMonetaryGroupingSeparator() : symbols
1123:                        .getGroupingSeparator();
1124:                char decimal = isCurrencyFormat ? symbols
1125:                        .getMonetaryDecimalSeparator() : symbols
1126:                        .getDecimalSeparator();
1127:                boolean useSigDig = areSignificantDigitsUsed();
1128:                int maxIntDig = getMaximumIntegerDigits();
1129:                int minIntDig = getMinimumIntegerDigits();
1130:
1131:                /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
1132:                 * format as zero.  This allows sensible computations and preserves
1133:                 * relations such as signum(1/x) = signum(x), where x is +Infinity or
1134:                 * -Infinity.  Prior to this fix, we always formatted zero values as if
1135:                 * they were positive.  Liu 7/6/98.
1136:                 */
1137:                if (digitList.isZero()) {
1138:                    digitList.decimalAt = 0; // Normalize
1139:                }
1140:
1141:                int prefixLen = appendAffix(result, isNegative, true, parseAttr);
1142:
1143:                if (useExponentialNotation) {
1144:                    // Record field information for caller.
1145:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1146:                        fieldPosition.setBeginIndex(result.length());
1147:                        fieldPosition.setEndIndex(-1);
1148:                    } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1149:                        fieldPosition.setBeginIndex(-1);
1150:                    }
1151:
1152:                    // [Spark/CDL]
1153:                    // the begin index of integer part
1154:                    // the end index of integer part
1155:                    // the begin index of fractional part
1156:                    int intBegin = result.length();
1157:                    int intEnd = -1;
1158:                    int fracBegin = -1;
1159:
1160:                    int minFracDig = 0;
1161:                    if (useSigDig) {
1162:                        maxIntDig = minIntDig = 1;
1163:                        minFracDig = getMinimumSignificantDigits() - 1;
1164:                    } else {
1165:                        minFracDig = getMinimumFractionDigits();
1166:                        if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
1167:                            maxIntDig = 1;
1168:                            if (maxIntDig < minIntDig) {
1169:                                maxIntDig = minIntDig;
1170:                            }
1171:                        }
1172:                        if (maxIntDig > minIntDig) {
1173:                            minIntDig = 1;
1174:                        }
1175:                    }
1176:
1177:                    // Minimum integer digits are handled in exponential format by
1178:                    // adjusting the exponent.  For example, 0.01234 with 3 minimum
1179:                    // integer digits is "123.4E-4".
1180:
1181:                    // Maximum integer digits are interpreted as indicating the
1182:                    // repeating range.  This is useful for engineering notation, in
1183:                    // which the exponent is restricted to a multiple of 3.  For
1184:                    // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1185:                    // If maximum integer digits are defined and are larger than
1186:                    // minimum integer digits, then minimum integer digits are
1187:                    // ignored.
1188:
1189:                    int exponent = digitList.decimalAt;
1190:                    if (maxIntDig > 1 && maxIntDig != minIntDig) {
1191:                        // A exponent increment is defined; adjust to it.
1192:                        exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
1193:                                : (exponent / maxIntDig) - 1;
1194:                        exponent *= maxIntDig;
1195:                    } else {
1196:                        // No exponent increment is defined; use minimum integer digits.
1197:                        // If none is specified, as in "#E0", generate 1 integer digit.
1198:                        exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig
1199:                                : 1;
1200:                    }
1201:
1202:                    // We now output a minimum number of digits, and more if there
1203:                    // are more digits, up to the maximum number of digits.  We
1204:                    // place the decimal point after the "integer" digits, which
1205:                    // are the first (decimalAt - exponent) digits.
1206:                    int minimumDigits = minIntDig + minFracDig;
1207:                    // The number of integer digits is handled specially if the number
1208:                    // is zero, since then there may be no digits.
1209:                    int integerDigits = digitList.isZero() ? minIntDig
1210:                            : digitList.decimalAt - exponent;
1211:                    int totalDigits = digitList.count;
1212:                    if (minimumDigits > totalDigits)
1213:                        totalDigits = minimumDigits;
1214:                    if (integerDigits > totalDigits)
1215:                        totalDigits = integerDigits;
1216:
1217:                    for (i = 0; i < totalDigits; ++i) {
1218:                        if (i == integerDigits) {
1219:                            // Record field information for caller.
1220:                            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1221:                                fieldPosition.setEndIndex(result.length());
1222:                            }
1223:                            //#ifndef FOUNDATION
1224:                            // [Spark/CDL] Add attribute for integer part
1225:                            if (parseAttr) {
1226:                                intEnd = result.length();
1227:                                addAttribute(Field.INTEGER, intBegin, result
1228:                                        .length());
1229:                            }
1230:                            //#endif
1231:                            result.append(decimal);
1232:                            //#ifndef FOUNDATION
1233:                            // [Spark/CDL] Add attribute for decimal separator
1234:                            if (parseAttr) {
1235:                                // Length of decimal separator is 1.
1236:                                int decimalSeparatorBegin = result.length() - 1;
1237:                                addAttribute(Field.DECIMAL_SEPARATOR,
1238:                                        decimalSeparatorBegin, result.length());
1239:                                fracBegin = result.length();
1240:                            }
1241:                            //#endif
1242:                            // Record field information for caller.
1243:                            if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1244:                                fieldPosition.setBeginIndex(result.length());
1245:                            }
1246:                        }
1247:                        result
1248:                                .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta)
1249:                                        : zero);
1250:                    }
1251:
1252:                    //For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
1253:                    if (digitList.isZero() && (totalDigits == 0)) {
1254:                        result.append(zero);
1255:                    }
1256:
1257:                    // Record field information
1258:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1259:                        if (fieldPosition.getEndIndex() < 0) {
1260:                            fieldPosition.setEndIndex(result.length());
1261:                        }
1262:                    } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1263:                        if (fieldPosition.getBeginIndex() < 0) {
1264:                            fieldPosition.setBeginIndex(result.length());
1265:                        }
1266:                        fieldPosition.setEndIndex(result.length());
1267:                    }
1268:                    //#ifndef FOUNDATION
1269:                    // [Spark/CDL] Calcuate the end index of integer part and fractional
1270:                    // part if they are not properly processed yet.
1271:                    if (parseAttr) {
1272:                        if (intEnd < 0) {
1273:                            addAttribute(Field.INTEGER, intBegin, result
1274:                                    .length());
1275:                        }
1276:                        if (fracBegin > 0) {
1277:                            addAttribute(Field.FRACTION, fracBegin, result
1278:                                    .length());
1279:                        }
1280:                    }
1281:                    //#endif
1282:
1283:                    // The exponent is output using the pattern-specified minimum
1284:                    // exponent digits.  There is no maximum limit to the exponent
1285:                    // digits, since truncating the exponent would result in an
1286:                    // unacceptable inaccuracy.
1287:                    result.append(symbols.getExponentSeparator());
1288:                    //#ifndef FOUNDATION
1289:                    // [Spark/CDL] For exponent symbol, add an attribute.
1290:                    if (parseAttr) {
1291:                        addAttribute(Field.EXPONENT_SYMBOL, result.length()
1292:                                - symbols.getExponentSeparator().length(),
1293:                                result.length());
1294:                    }
1295:                    //#endif
1296:                    // For zero values, we force the exponent to zero.  We
1297:                    // must do this here, and not earlier, because the value
1298:                    // is used to determine integer digit count above.
1299:                    if (digitList.isZero())
1300:                        exponent = 0;
1301:
1302:                    boolean negativeExponent = exponent < 0;
1303:                    if (negativeExponent) {
1304:                        exponent = -exponent;
1305:                        result.append(symbols.getMinusSign());
1306:                        //#ifndef FOUNDATION
1307:                        // [Spark/CDL] If exponent has sign, then add an exponent sign
1308:                        // attribute.
1309:                        if (parseAttr) {
1310:                            // Length of exponent sign is 1.
1311:                            addAttribute(Field.EXPONENT_SIGN,
1312:                                    result.length() - 1, result.length());
1313:                        }
1314:                        //#endif
1315:                    } else if (exponentSignAlwaysShown) {
1316:                        result.append(symbols.getPlusSign());
1317:                        //#ifndef FOUNDATION
1318:                        // [Spark/CDL] Add an plus sign attribute.
1319:                        if (parseAttr) {
1320:                            // Length of exponent sign is 1.
1321:                            int expSignBegin = result.length() - 1;
1322:                            addAttribute(Field.EXPONENT_SIGN, expSignBegin,
1323:                                    result.length());
1324:                        }
1325:                        //#endif
1326:                    }
1327:                    int expBegin = result.length();
1328:                    digitList.set(exponent);
1329:                    {
1330:                        int expDig = minExponentDigits;
1331:                        if (useExponentialNotation && expDig < 1) {
1332:                            expDig = 1;
1333:                        }
1334:                        for (i = digitList.decimalAt; i < expDig; ++i)
1335:                            result.append(zero);
1336:                    }
1337:                    for (i = 0; i < digitList.decimalAt; ++i) {
1338:                        result
1339:                                .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta)
1340:                                        : zero);
1341:                    }
1342:                    //#ifndef FOUNDATION
1343:                    // [Spark/CDL] Add attribute for exponent part.
1344:                    if (parseAttr) {
1345:                        addAttribute(Field.EXPONENT, expBegin, result.length());
1346:                    }
1347:                    //#endif
1348:                } else {
1349:                    // [Spark/CDL] Record the integer start index.
1350:                    int intBegin = result.length();
1351:                    // Record field information for caller.
1352:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1353:                        fieldPosition.setBeginIndex(result.length());
1354:                    }
1355:
1356:                    int sigCount = 0;
1357:                    int minSigDig = getMinimumSignificantDigits();
1358:                    int maxSigDig = getMaximumSignificantDigits();
1359:                    if (!useSigDig) {
1360:                        minSigDig = 0;
1361:                        maxSigDig = Integer.MAX_VALUE;
1362:                    }
1363:
1364:                    // Output the integer portion.  Here 'count' is the total
1365:                    // number of integer digits we will display, including both
1366:                    // leading zeros required to satisfy getMinimumIntegerDigits,
1367:                    // and actual digits present in the number.
1368:                    int count = useSigDig ? Math.max(1, digitList.decimalAt)
1369:                            : minIntDig;
1370:                    if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
1371:                        count = digitList.decimalAt;
1372:                    }
1373:
1374:                    // Handle the case where getMaximumIntegerDigits() is smaller
1375:                    // than the real number of integer digits.  If this is so, we
1376:                    // output the least significant max integer digits.  For example,
1377:                    // the value 1997 printed with 2 max integer digits is just "97".
1378:
1379:                    int digitIndex = 0; // Index into digitList.fDigits[]
1380:                    if (count > maxIntDig && maxIntDig >= 0) {
1381:                        count = maxIntDig;
1382:                        digitIndex = digitList.decimalAt - count;
1383:                    }
1384:
1385:                    int sizeBeforeIntegerPart = result.length();
1386:                    for (i = count - 1; i >= 0; --i) {
1387:                        if (i < digitList.decimalAt
1388:                                && digitIndex < digitList.count
1389:                                && sigCount < maxSigDig) {
1390:                            // Output a real digit
1391:                            byte d = digitList.digits[digitIndex++];
1392:                            result.append((char) (d + zeroDelta));
1393:                            ++sigCount;
1394:                        } else {
1395:                            // Output a zero (leading or trailing)
1396:                            result.append(zero);
1397:                            if (sigCount > 0) {
1398:                                ++sigCount;
1399:                            }
1400:                        }
1401:
1402:                        // Output grouping separator if necessary.
1403:                        if (isGroupingPosition(i)) {
1404:                            result.append(grouping);
1405:                            //#ifndef FOUNDATION
1406:                            // [Spark/CDL] Add grouping separator attribute here.
1407:                            if (parseAttr) {
1408:                                // Length of grouping separator is 1.
1409:                                addAttribute(Field.GROUPING_SEPARATOR, result
1410:                                        .length() - 1, result.length());
1411:                            }
1412:                            //#endif
1413:                        }
1414:                    }
1415:
1416:                    // Record field information for caller.
1417:                    if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1418:                        fieldPosition.setEndIndex(result.length());
1419:                    }
1420:
1421:                    // Determine whether or not there are any printable fractional
1422:                    // digits.  If we've used up the digits we know there aren't.
1423:                    boolean fractionPresent = (!isInteger && digitIndex < digitList.count)
1424:                            || (useSigDig ? (sigCount < minSigDig)
1425:                                    : (getMinimumFractionDigits() > 0));
1426:
1427:                    // If there is no fraction present, and we haven't printed any
1428:                    // integer digits, then print a zero.  Otherwise we won't print
1429:                    // _any_ digits, and we won't be able to parse this string.
1430:                    if (!fractionPresent
1431:                            && result.length() == sizeBeforeIntegerPart)
1432:                        result.append(zero);
1433:                    //#ifndef FOUNDATION
1434:                    // [Spark/CDL] Add attribute for integer part.
1435:                    if (parseAttr) {
1436:                        addAttribute(Field.INTEGER, intBegin, result.length());
1437:                    }
1438:                    //#endif
1439:                    // Output the decimal separator if we always do so.
1440:                    if (decimalSeparatorAlwaysShown || fractionPresent) {
1441:                        result.append(decimal);
1442:                        //#ifndef FOUNDATION
1443:                        // [Spark/CDL] Add attribute for decimal separator
1444:                        if (parseAttr) {
1445:                            addAttribute(Field.DECIMAL_SEPARATOR, result
1446:                                    .length() - 1, result.length());
1447:                        }
1448:                        //#endif
1449:                    }
1450:
1451:                    // Record field information for caller.
1452:                    if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1453:                        fieldPosition.setBeginIndex(result.length());
1454:                    }
1455:
1456:                    // [Spark/CDL] Record the begin index of fraction part.
1457:                    int fracBegin = result.length();
1458:
1459:                    count = useSigDig ? Integer.MAX_VALUE
1460:                            : getMaximumFractionDigits();
1461:                    if (useSigDig
1462:                            && (sigCount == maxSigDig || (sigCount >= minSigDig && digitIndex == digitList.count))) {
1463:                        count = 0;
1464:                    }
1465:                    for (i = 0; i < count; ++i) {
1466:                        // Here is where we escape from the loop.  We escape
1467:                        // if we've output the maximum fraction digits
1468:                        // (specified in the for expression above).  We also
1469:                        // stop when we've output the minimum digits and
1470:                        // either: we have an integer, so there is no
1471:                        // fractional stuff to display, or we're out of
1472:                        // significant digits.
1473:                        if (!useSigDig && i >= getMinimumFractionDigits()
1474:                                && (isInteger || digitIndex >= digitList.count)) {
1475:                            break;
1476:                        }
1477:
1478:                        // Output leading fractional zeros.  These are zeros
1479:                        // that come after the decimal but before any
1480:                        // significant digits.  These are only output if
1481:                        // abs(number being formatted) < 1.0.
1482:                        if (-1 - i > (digitList.decimalAt - 1)) {
1483:                            result.append(zero);
1484:                            continue;
1485:                        }
1486:
1487:                        // Output a digit, if we have any precision left, or a
1488:                        // zero if we don't.  We don't want to output noise digits.
1489:                        if (!isInteger && digitIndex < digitList.count) {
1490:                            result
1491:                                    .append((char) (digitList.digits[digitIndex++] + zeroDelta));
1492:                        } else {
1493:                            result.append(zero);
1494:                        }
1495:
1496:                        // If we reach the maximum number of significant
1497:                        // digits, or if we output all the real digits and
1498:                        // reach the minimum, then we are done.
1499:                        ++sigCount;
1500:                        if (useSigDig
1501:                                && (sigCount == maxSigDig || (digitIndex == digitList.count && sigCount >= minSigDig))) {
1502:                            break;
1503:                        }
1504:                    }
1505:
1506:                    // Record field information for caller.
1507:                    if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1508:                        fieldPosition.setEndIndex(result.length());
1509:                    }
1510:                    //#ifndef FOUNDATION
1511:                    // [Spark/CDL] Add attribute information if necessary.
1512:                    if (parseAttr
1513:                            && (decimalSeparatorAlwaysShown || fractionPresent)) {
1514:                        addAttribute(Field.FRACTION, fracBegin, result.length());
1515:                    }
1516:                    //#endif
1517:                }
1518:
1519:                int suffixLen = appendAffix(result, isNegative, false,
1520:                        parseAttr);
1521:
1522:                // [NEW]
1523:                addPadding(result, fieldPosition, prefixLen, suffixLen);
1524:                return result;
1525:            }
1526:
1527:            // [NEW]
1528:            private final void addPadding(StringBuffer result,
1529:                    FieldPosition fieldPosition, int prefixLen, int suffixLen) {
1530:                if (formatWidth > 0) {
1531:                    int len = formatWidth - result.length();
1532:                    if (len > 0) {
1533:                        char[] padding = new char[len];
1534:                        for (int i = 0; i < len; ++i) {
1535:                            padding[i] = pad;
1536:                        }
1537:                        switch (padPosition) {
1538:                        case PAD_AFTER_PREFIX:
1539:                            result.insert(prefixLen, padding);
1540:                            break;
1541:                        case PAD_BEFORE_PREFIX:
1542:                            result.insert(0, padding);
1543:                            break;
1544:                        case PAD_BEFORE_SUFFIX:
1545:                            result.insert(result.length() - suffixLen, padding);
1546:                            break;
1547:                        case PAD_AFTER_SUFFIX:
1548:                            result.append(padding);
1549:                            break;
1550:                        }
1551:                        if (padPosition == PAD_BEFORE_PREFIX
1552:                                || padPosition == PAD_AFTER_PREFIX) {
1553:                            fieldPosition.setBeginIndex(fieldPosition
1554:                                    .getBeginIndex()
1555:                                    + len);
1556:                            fieldPosition.setEndIndex(fieldPosition
1557:                                    .getEndIndex()
1558:                                    + len);
1559:                        }
1560:                    }
1561:                }
1562:            }
1563:
1564:            /**
1565:             * <strong><font face=helvetica color=red>CHANGED</font></strong>
1566:             * Parse the given string, returning a <code>Number</code> object to
1567:             * represent the parsed value.  <code>Double</code> objects are returned to
1568:             * represent non-integral values which cannot be stored in a
1569:             * <code>BigDecimal</code>.  These are <code>NaN</code>, infinity,
1570:             * -infinity, and -0.0.  If {@link #isParseBigDecimal()} is false (the
1571:             * default), all other values are returned as <code>Long</code>,
1572:             * <code>BigInteger</code>, or <code>BigDecimal</code> values,
1573:             * in that order of preference. If {@link #isParseBigDecimal()} is true,
1574:             * all other values are returned as <code>BigDecimal</code> valuse.
1575:             * If the parse fails, null is returned.
1576:             * @param text the string to be parsed
1577:             * @param parsePosition defines the position where parsing is to begin,
1578:             * and upon return, the position where parsing left off.  If the position
1579:             * has not changed upon return, then parsing failed.
1580:             * @return a <code>Number</code> object with the parsed value or
1581:             * <code>null</code> if the parse failed
1582:             * @stable ICU 2.0
1583:             */
1584:            public Number parse(String text, ParsePosition parsePosition) {
1585:                return (Number) parse(text, parsePosition, false);
1586:            }
1587:
1588:            /**
1589:             * <strong><font face=helvetica color=red>NEW</font></strong>
1590:             * Parses text from the given string as a CurrencyAmount.  Unlike
1591:             * the parse() method, this method will attempt to parse a generic
1592:             * currency name, searching for a match of this object's locale's
1593:             * currency display names, or for a 3-letter ISO currency code.
1594:             * This method will fail if this format is not a currency format,
1595:             * that is, if it does not contain the currency pattern symbol
1596:             * (U+00A4) in its prefix or suffix.
1597:             *
1598:             * @param text the string to parse
1599:             * @param pos input-output position; on input, the position within
1600:             * text to match; must have 0 <= pos.getIndex() < text.length();
1601:             * on output, the position after the last matched character. If
1602:             * the parse fails, the position in unchanged upon output.
1603:             * @return a CurrencyAmount, or null upon failure
1604:             * @internal
1605:             * @deprecated This API is ICU internal only.
1606:             */
1607:            CurrencyAmount parseCurrency(String text, ParsePosition pos) {
1608:                return (CurrencyAmount) parse(text, pos, true);
1609:            }
1610:
1611:            /**
1612:             * Parses the given text as either a Number or a CurrencyAmount.
1613:             * @param text the string to parse
1614:             * @param parsePosition input-output position; on input, the
1615:             * position within text to match; must have 0 <= pos.getIndex() <
1616:             * text.length(); on output, the position after the last matched
1617:             * character. If the parse fails, the position in unchanged upon
1618:             * output.
1619:             * @param parseCurrency if true, a CurrencyAmount is parsed and
1620:             * returned; otherwise a Number is parsed and returned
1621:             * @return a Number or CurrencyAmount or null
1622:             */
1623:            private Object parse(String text, ParsePosition parsePosition,
1624:                    boolean parseCurrency) {
1625:                int backup;
1626:                int i = backup = parsePosition.getIndex();
1627:
1628:                // Handle NaN as a special case:
1629:
1630:                // Skip padding characters, if around prefix
1631:                if (formatWidth > 0
1632:                        && (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {
1633:                    i = skipPadding(text, i);
1634:                }
1635:                if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN()
1636:                        .length())) {
1637:                    i += symbols.getNaN().length();
1638:                    // Skip padding characters, if around suffix
1639:                    if (formatWidth > 0
1640:                            && (padPosition == PAD_BEFORE_SUFFIX || padPosition == PAD_AFTER_SUFFIX)) {
1641:                        i = skipPadding(text, i);
1642:                    }
1643:                    parsePosition.setIndex(i);
1644:                    return new Double(Double.NaN);
1645:                }
1646:
1647:                // NaN parse failed; start over
1648:                i = backup;
1649:
1650:                boolean[] status = new boolean[STATUS_LENGTH];
1651:                Currency[] currency = parseCurrency ? new Currency[1] : null;
1652:                if (!subparse(text, parsePosition, digitList, false, status,
1653:                        currency)) {
1654:                    parsePosition.setIndex(backup);
1655:                    return null;
1656:                }
1657:
1658:                Number n = null;
1659:
1660:                // Handle infinity
1661:                if (status[STATUS_INFINITE]) {
1662:                    n = new Double(
1663:                            status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY
1664:                                    : Double.NEGATIVE_INFINITY);
1665:                }
1666:
1667:                // Handle -0.0
1668:                else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
1669:                    n = new Double(-0.0);
1670:                }
1671:
1672:                else {
1673:                    // Do as much of the multiplier conversion as possible without
1674:                    // losing accuracy.
1675:                    int mult = multiplier; // Don't modify this.multiplier
1676:                    while (mult % 10 == 0) {
1677:                        --digitList.decimalAt;
1678:                        mult /= 10;
1679:                    }
1680:
1681:                    // Handle integral values
1682:                    if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
1683:                        // hack quick long
1684:                        if (digitList.decimalAt < 12) { // quick check for long
1685:                            long l = 0;
1686:                            if (digitList.count > 0) {
1687:                                int nx = 0;
1688:                                while (nx < digitList.count) {
1689:                                    l = l * 10 + (char) digitList.digits[nx++]
1690:                                            - '0';
1691:                                }
1692:                                while (nx++ < digitList.decimalAt) {
1693:                                    l *= 10;
1694:                                }
1695:                                if (!status[STATUS_POSITIVE]) {
1696:                                    l = -l;
1697:                                }
1698:                            }
1699:                            n = new Long(l);
1700:                        } else {
1701:                            BigInteger big = digitList
1702:                                    .getBigInteger(status[STATUS_POSITIVE]);
1703:                            n = (big.bitLength() < 64) ? (Number) new Long(big
1704:                                    .longValue()) : (Number) big;
1705:                        }
1706:                    }
1707:
1708:                    // Handle non-integral values or the case where parseBigDecimal is set
1709:                    else {
1710:                        BigDecimal big = digitList
1711:                                .getBigDecimalICU(status[STATUS_POSITIVE]);
1712:                        n = big;
1713:                        if (mult != 1) {
1714:                            n = big.divide(BigDecimal.valueOf(mult),
1715:                                    BigDecimal.ROUND_HALF_EVEN);
1716:                        }
1717:                    }
1718:                }
1719:
1720:                // Assemble into CurrencyAmount if necessary
1721:                return parseCurrency ? (Object) new CurrencyAmount(n,
1722:                        currency[0]) : (Object) n;
1723:            }
1724:
1725:            private static final int STATUS_INFINITE = 0;
1726:            private static final int STATUS_POSITIVE = 1;
1727:            private static final int STATUS_LENGTH = 2;
1728:
1729:            /**
1730:             * <strong><font face=helvetica color=red>CHANGED</font></strong>
1731:             * Parse the given text into a number.  The text is parsed beginning at
1732:             * parsePosition, until an unparseable character is seen.
1733:             * @param text The string to parse.
1734:             * @param parsePosition The position at which to being parsing.  Upon
1735:             * return, the first unparseable character.
1736:             * @param digits The DigitList to set to the parsed value.
1737:             * @param isExponent If true, parse an exponent.  This means no
1738:             * infinite values and integer only.
1739:             * @param status Upon return contains boolean status flags indicating
1740:             * whether the value was infinite and whether it was positive.
1741:             * @param currency return value for parsed currency, for generic
1742:             * currency parsing mode, or null for normal parsing. In generic
1743:             * currency parsing mode, any currency is parsed, not just the
1744:             * currency that this formatter is set to.
1745:             */
1746:            private final boolean subparse(String text,
1747:                    ParsePosition parsePosition, DigitList digits,
1748:                    boolean isExponent, boolean status[], Currency currency[]) {
1749:                int position = parsePosition.getIndex();
1750:                int oldStart = parsePosition.getIndex();
1751:
1752:                // Match padding before prefix
1753:                if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
1754:                    position = skipPadding(text, position);
1755:                }
1756:
1757:                // Match positive and negative prefixes; prefer longest match.
1758:                int posMatch = compareAffix(text, position, false, true,
1759:                        currency);
1760:                int negMatch = compareAffix(text, position, true, true,
1761:                        currency);
1762:                if (posMatch >= 0 && negMatch >= 0) {
1763:                    if (posMatch > negMatch) {
1764:                        negMatch = -1;
1765:                    } else if (negMatch > posMatch) {
1766:                        posMatch = -1;
1767:                    }
1768:                }
1769:                if (posMatch >= 0) {
1770:                    position += posMatch;
1771:                } else if (negMatch >= 0) {
1772:                    position += negMatch;
1773:                } else {
1774:                    parsePosition.setErrorIndex(position);
1775:                    return false;
1776:                }
1777:
1778:                // Match padding after prefix
1779:                if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
1780:                    position = skipPadding(text, position);
1781:                }
1782:
1783:                // process digits or Inf, find decimal position
1784:                status[STATUS_INFINITE] = false;
1785:                if (!isExponent
1786:                        && text.regionMatches(position, symbols.getInfinity(),
1787:                                0, symbols.getInfinity().length())) {
1788:                    position += symbols.getInfinity().length();
1789:                    status[STATUS_INFINITE] = true;
1790:                } else {
1791:                    // We now have a string of digits, possibly with grouping symbols,
1792:                    // and decimal points.  We want to process these into a DigitList.
1793:                    // We don't want to put a bunch of leading zeros into the DigitList
1794:                    // though, so we keep track of the location of the decimal point,
1795:                    // put only significant digits into the DigitList, and adjust the
1796:                    // exponent as needed.
1797:
1798:                    digits.decimalAt = digits.count = 0;
1799:                    char zero = symbols.getZeroDigit();
1800:                    char decimal = isCurrencyFormat ? symbols
1801:                            .getMonetaryDecimalSeparator() : symbols
1802:                            .getDecimalSeparator();
1803:                    char grouping = symbols.getGroupingSeparator();
1804:                    String exponentSep = symbols.getExponentSeparator();
1805:                    boolean sawDecimal = false;
1806:                    boolean sawExponent = false;
1807:                    boolean sawDigit = false;
1808:                    int exponent = 0; // Set to the exponent value, if any
1809:                    int digit = 0;
1810:
1811:                    // strict parsing
1812:                    boolean strictParse = isParseStrict();
1813:                    boolean strictFail = false; // did we exit with a strict parse failure?
1814:                    boolean leadingZero = false; // did we see a leading zero?
1815:                    int lastGroup = -1; // where did we last see a grouping separator?
1816:                    int prevGroup = -1; // where did we see the grouping separator before that?
1817:                    int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
1818:
1819:                    // We have to track digitCount ourselves, because digits.count will
1820:                    // pin when the maximum allowable digits is reached.
1821:                    int digitCount = 0;
1822:
1823:                    int backup = -1;
1824:                    for (; position < text.length(); ++position) {
1825:                        char ch = text.charAt(position);
1826:
1827:                        /* We recognize all digit ranges, not only the Latin digit range
1828:                         * '0'..'9'.  We do so by using the UCharacter.digit() method,
1829:                         * which converts a valid Unicode digit to the range 0..9.
1830:                         *
1831:                         * The character 'ch' may be a digit.  If so, place its value
1832:                         * from 0 to 9 in 'digit'.  First try using the locale digit,
1833:                         * which may or MAY NOT be a standard Unicode digit range.  If
1834:                         * this fails, try using the standard Unicode digit ranges by
1835:                         * calling UCharacter.digit().  If this also fails, digit will
1836:                         * have a value outside the range 0..9.
1837:                         */
1838:                        digit = ch - zero;
1839:                        if (digit < 0 || digit > 9)
1840:                            digit = UCharacter.digit(ch, 10);
1841:
1842:                        if (digit == 0) {
1843:                            // Cancel out backup setting (see grouping handler below)
1844:                            if (strictParse && backup != -1) {
1845:                                // comma followed by digit, so group before comma is a 
1846:                                // secondary group.  If there was a group separator
1847:                                // before that, the group must == the secondary group
1848:                                // length, else it can be <= the the secondary group
1849:                                // length.
1850:                                if ((lastGroup != -1 && backup - lastGroup - 1 != gs2)
1851:                                        || (lastGroup == -1 && position
1852:                                                - oldStart - 1 > gs2)) {
1853:                                    strictFail = true;
1854:                                    break;
1855:                                }
1856:                                prevGroup = lastGroup;
1857:                                lastGroup = backup;
1858:                            }
1859:                            backup = -1; // Do this BEFORE continue statement below!!!
1860:                            sawDigit = true;
1861:
1862:                            // Handle leading zeros
1863:                            if (digits.count == 0) {
1864:                                if (!sawDecimal) {
1865:                                    if (strictParse && !isExponent) {
1866:                                        // Allow leading zeros in exponents
1867:                                        if (leadingZero) {
1868:                                            strictFail = true;
1869:                                            break;
1870:                                        }
1871:                                        leadingZero = true;
1872:                                    }
1873:                                    // Ignore leading zeros in integer part of number.
1874:                                    continue;
1875:                                }
1876:
1877:                                // If we have seen the decimal, but no significant digits yet,
1878:                                // then we account for leading zeros by decrementing the
1879:                                // digits.decimalAt into negative values.
1880:                                --digits.decimalAt;
1881:                            } else {
1882:                                ++digitCount;
1883:                                digits.append((char) (digit + '0'));
1884:                            }
1885:                        } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
1886:                        {
1887:                            if (strictParse) {
1888:                                if (leadingZero) {
1889:                                    // a leading zero before a digit is an error with strict parsing
1890:                                    strictFail = true;
1891:                                    break;
1892:                                }
1893:                                if (backup != -1) {
1894:                                    if ((lastGroup != -1 && backup - lastGroup
1895:                                            - 1 != gs2)
1896:                                            || (lastGroup == -1 && position
1897:                                                    - oldStart - 1 > gs2)) {
1898:                                        strictFail = true;
1899:                                        break;
1900:                                    }
1901:                                    prevGroup = lastGroup;
1902:                                    lastGroup = backup;
1903:                                }
1904:                            }
1905:
1906:                            sawDigit = true;
1907:                            ++digitCount;
1908:                            digits.append((char) (digit + '0'));
1909:
1910:                            // Cancel out backup setting (see grouping handler below)
1911:                            backup = -1;
1912:                        } else if (!isExponent && ch == decimal) {
1913:                            if (strictParse) {
1914:                                if (backup != -1
1915:                                        || (lastGroup != -1 && position
1916:                                                - lastGroup != groupingSize - 1)) {
1917:                                    strictFail = true;
1918:                                    break;
1919:                                }
1920:                            }
1921:                            // If we're only parsing integers, or if we ALREADY saw the
1922:                            // decimal, then don't parse this one.
1923:                            if (isParseIntegerOnly() || sawDecimal)
1924:                                break;
1925:                            digits.decimalAt = digitCount; // Not digits.count!
1926:                            sawDecimal = true;
1927:                            leadingZero = false; // a single leading zero before a decimal is ok
1928:                        } else if (!isExponent && ch == grouping
1929:                                && isGroupingUsed()) {
1930:                            if (sawDecimal) {
1931:                                break;
1932:                            }
1933:                            if (strictParse) {
1934:                                if ((!sawDigit || backup != -1)) {
1935:                                    // leading group, or two group separators in a row
1936:                                    strictFail = true;
1937:                                    break;
1938:                                }
1939:                            }
1940:                            // Ignore grouping characters, if we are using them, but require
1941:                            // that they be followed by a digit.  Otherwise we backup and
1942:                            // reprocess them.
1943:                            backup = position;
1944:                        } else if (!isExponent
1945:                                && !sawExponent
1946:                                && text.regionMatches(position, exponentSep, 0,
1947:                                        exponentSep.length())) {
1948:                            // Parse sign, if present
1949:                            boolean negExp = false;
1950:                            int pos = position + exponentSep.length();
1951:                            if (pos < text.length()) {
1952:                                ch = text.charAt(pos);
1953:                                if (ch == symbols.getPlusSign()) {
1954:                                    ++pos;
1955:                                } else if (ch == symbols.getMinusSign()) {
1956:                                    ++pos;
1957:                                    negExp = true;
1958:                                }
1959:                            }
1960:
1961:                            DigitList exponentDigits = new DigitList();
1962:                            exponentDigits.count = 0;
1963:                            while (pos < text.length()) {
1964:                                digit = text.charAt(pos) - zero;
1965:                                if (digit < 0 || digit > 9) {
1966:                                    /*
1967:                                      Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
1968:                                      Should update reassign the value of 'ch' in the
1969:                                      code:  digit = Character.digit(ch, 10);
1970:                                      [Richard/GCL]
1971:                                     */
1972:                                    digit = UCharacter.digit(text.charAt(pos),
1973:                                            10);
1974:                                }
1975:                                if (digit >= 0 && digit <= 9) {
1976:                                    exponentDigits.append((char) (digit + '0'));
1977:                                    ++pos;
1978:                                } else {
1979:                                    break;
1980:                                }
1981:                            }
1982:
1983:                            if (exponentDigits.count > 0) {
1984:                                // defer strict parse until we know we have a bona-fide exponent
1985:                                if (strictParse) {
1986:                                    if (backup != -1 || lastGroup != -1) {
1987:                                        strictFail = true;
1988:                                        break;
1989:                                    }
1990:                                }
1991:
1992:                                exponentDigits.decimalAt = exponentDigits.count;
1993:                                exponent = (int) exponentDigits.getLong();
1994:                                if (negExp) {
1995:                                    exponent = -exponent;
1996:                                }
1997:                                position = pos; // Advance past the exponent
1998:                                sawExponent = true;
1999:                            }
2000:
2001:                            break; // Whether we fail or succeed, we exit this loop
2002:                        } else
2003:                            break;
2004:                    }
2005:
2006:                    if (backup != -1)
2007:                        position = backup;
2008:
2009:                    if (strictParse && !sawDecimal) {
2010:                        if (lastGroup != -1
2011:                                && position - lastGroup != groupingSize + 1) {
2012:                            strictFail = true;
2013:                        }
2014:                    }
2015:                    if (strictFail) {
2016:                        // only set with strictParse and a leading zero error
2017:                        // leading zeros are an error with strict parsing except
2018:                        // immediately before nondigit (except group separator 
2019:                        // followed by digit), or end of text.
2020:
2021:                        parsePosition.setIndex(oldStart);
2022:                        parsePosition.setErrorIndex(position);
2023:                        return false;
2024:                    }
2025:
2026:                    // If there was no decimal point we have an integer
2027:                    if (!sawDecimal)
2028:                        digits.decimalAt = digitCount; // Not digits.count!
2029:
2030:                    // Adjust for exponent, if any
2031:                    digits.decimalAt += exponent;
2032:
2033:                    // If none of the text string was recognized.  For example, parse
2034:                    // "x" with pattern "#0.00" (return index and error index both 0)
2035:                    // parse "$" with pattern "$#0.00". (return index 0 and error index
2036:                    // 1).
2037:                    if (!sawDigit && digitCount == 0) {
2038:                        parsePosition.setIndex(oldStart);
2039:                        parsePosition.setErrorIndex(oldStart);
2040:                        return false;
2041:                    }
2042:                }
2043:
2044:                // Match padding before suffix
2045:                if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
2046:                    position = skipPadding(text, position);
2047:                }
2048:
2049:                // Match positive and negative suffixes; prefer longest match.
2050:                if (posMatch >= 0) {
2051:                    posMatch = compareAffix(text, position, false, false,
2052:                            currency);
2053:                }
2054:                if (negMatch >= 0) {
2055:                    negMatch = compareAffix(text, position, true, false,
2056:                            currency);
2057:                }
2058:                if (posMatch >= 0 && negMatch >= 0) {
2059:                    if (posMatch > negMatch) {
2060:                        negMatch = -1;
2061:                    } else if (negMatch > posMatch) {
2062:                        posMatch = -1;
2063:                    }
2064:                }
2065:
2066:                // Fail if neither or both
2067:                if ((posMatch >= 0) == (negMatch >= 0)) {
2068:                    parsePosition.setErrorIndex(position);
2069:                    return false;
2070:                }
2071:
2072:                position += (posMatch >= 0 ? posMatch : negMatch);
2073:
2074:                // Match padding after suffix
2075:                if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
2076:                    position = skipPadding(text, position);
2077:                }
2078:
2079:                parsePosition.setIndex(position);
2080:
2081:                status[STATUS_POSITIVE] = (posMatch >= 0);
2082:
2083:                if (parsePosition.getIndex() == oldStart) {
2084:                    parsePosition.setErrorIndex(position);
2085:                    return false;
2086:                }
2087:                return true;
2088:            }
2089:
2090:            /**
2091:             * Starting at position, advance past a run of pad characters, if any.
2092:             * Return the index of the first character after position that is not a pad
2093:             * character.  Result is >= position.
2094:             */
2095:            private final int skipPadding(String text, int position) {
2096:                while (position < text.length() && text.charAt(position) == pad) {
2097:                    ++position;
2098:                }
2099:                return position;
2100:            }
2101:
2102:            /**
2103:             * Return the length matched by the given affix, or -1 if none.
2104:             * Runs of white space in the affix, match runs of white space in
2105:             * the input.  Pattern white space and input white space are
2106:             * determined differently; see code.
2107:             * @param text input text
2108:             * @param pos offset into input at which to begin matching
2109:             * @param isNegative
2110:             * @param isPrefix
2111:             * @param currency return value for parsed currency, for generic
2112:             * currency parsing mode, or null for normal parsing. In generic
2113:             * currency parsing mode, any currency is parsed, not just the
2114:             * currency that this formatter is set to.
2115:             * @return length of input that matches, or -1 if match failure
2116:             */
2117:            private int compareAffix(String text, int pos, boolean isNegative,
2118:                    boolean isPrefix, Currency[] currency) {
2119:                if (currency != null || currencyChoice != null) {
2120:                    if (isPrefix) {
2121:                        return compareComplexAffix(
2122:                                isNegative ? negPrefixPattern
2123:                                        : posPrefixPattern, text, pos, currency);
2124:                    } else {
2125:                        return compareComplexAffix(
2126:                                isNegative ? negSuffixPattern
2127:                                        : posSuffixPattern, text, pos, currency);
2128:                    }
2129:                }
2130:
2131:                if (isPrefix) {
2132:                    return compareSimpleAffix(isNegative ? negativePrefix
2133:                            : positivePrefix, text, pos);
2134:                } else {
2135:                    return compareSimpleAffix(isNegative ? negativeSuffix
2136:                            : positiveSuffix, text, pos);
2137:                }
2138:            }
2139:
2140:            /**
2141:             * Return the length matched by the given affix, or -1 if none.
2142:             * Runs of white space in the affix, match runs of white space in
2143:             * the input.  Pattern white space and input white space are
2144:             * determined differently; see code.
2145:             * @param affix pattern string, taken as a literal
2146:             * @param input input text
2147:             * @param pos offset into input at which to begin matching
2148:             * @return length of input that matches, or -1 if match failure
2149:             */
2150:            private static int compareSimpleAffix(String affix, String input,
2151:                    int pos) {
2152:                int start = pos;
2153:                for (int i = 0; i < affix.length();) {
2154:                    int c = UTF16.charAt(affix, i);
2155:                    int len = UTF16.getCharCount(c);
2156:                    if (UCharacterProperty.isRuleWhiteSpace(c)) {
2157:                        // We may have a pattern like: \u200F \u0020
2158:                        //        and input text like: \u200F \u0020
2159:                        // Note that U+200F and U+0020 are RuleWhiteSpace but only
2160:                        // U+0020 is UWhiteSpace.  So we have to first do a direct
2161:                        // match of the run of RULE whitespace in the pattern,
2162:                        // then match any extra characters.
2163:                        boolean literalMatch = false;
2164:                        while (pos < input.length()
2165:                                && UTF16.charAt(input, pos) == c) {
2166:                            literalMatch = true;
2167:                            i += len;
2168:                            pos += len;
2169:                            if (i == affix.length()) {
2170:                                break;
2171:                            }
2172:                            c = UTF16.charAt(affix, i);
2173:                            len = UTF16.getCharCount(c);
2174:                            if (!UCharacterProperty.isRuleWhiteSpace(c)) {
2175:                                break;
2176:                            }
2177:                        }
2178:
2179:                        // Advance over run in affix
2180:                        i = skipRuleWhiteSpace(affix, i);
2181:
2182:                        // Advance over run in input text
2183:                        // Must see at least one white space char in input,
2184:                        // unless we've already matched some characters literally.
2185:                        int s = pos;
2186:                        pos = skipUWhiteSpace(input, pos);
2187:                        if (pos == s && !literalMatch) {
2188:                            return -1;
2189:                        }
2190:                    } else {
2191:                        if (pos < input.length()
2192:                                && UTF16.charAt(input, pos) == c) {
2193:                            i += len;
2194:                            pos += len;
2195:                        } else {
2196:                            return -1;
2197:                        }
2198:                    }
2199:                }
2200:                return pos - start;
2201:            }
2202:
2203:            /**
2204:             * Skip over a run of zero or more isRuleWhiteSpace() characters at
2205:             * pos in text.
2206:             */
2207:            private static int skipRuleWhiteSpace(String text, int pos) {
2208:                while (pos < text.length()) {
2209:                    int c = UTF16.charAt(text, pos);
2210:                    if (!UCharacterProperty.isRuleWhiteSpace(c)) {
2211:                        break;
2212:                    }
2213:                    pos += UTF16.getCharCount(c);
2214:                }
2215:                return pos;
2216:            }
2217:
2218:            /**
2219:             * Skip over a run of zero or more isUWhiteSpace() characters at pos
2220:             * in text.
2221:             */
2222:            private static int skipUWhiteSpace(String text, int pos) {
2223:                while (pos < text.length()) {
2224:                    int c = UTF16.charAt(text, pos);
2225:                    if (!UCharacter.isUWhiteSpace(c)) {
2226:                        break;
2227:                    }
2228:                    pos += UTF16.getCharCount(c);
2229:                }
2230:                return pos;
2231:            }
2232:
2233:            /**
2234:             * Return the length matched by the given affix, or -1 if none.
2235:             * @param affixPat pattern string
2236:             * @param text input text
2237:             * @param pos offset into input at which to begin matching
2238:             * @param currency return value for parsed currency, for generic
2239:             * currency parsing mode, or null for normal parsing. In generic
2240:             * currency parsing mode, any currency is parsed, not just the
2241:             * currency that this formatter is set to.
2242:             * @return length of input that matches, or -1 if match failure
2243:             */
2244:            private int compareComplexAffix(String affixPat, String text,
2245:                    int pos, Currency[] currency) {
2246:
2247:                for (int i = 0; i < affixPat.length() && pos >= 0;) {
2248:                    char c = affixPat.charAt(i++);
2249:                    if (c == QUOTE) {
2250:                        for (;;) {
2251:                            int j = affixPat.indexOf(QUOTE, i);
2252:                            if (j == i) {
2253:                                pos = match(text, pos, QUOTE);
2254:                                i = j + 1;
2255:                                break;
2256:                            } else if (j > i) {
2257:                                pos = match(text, pos, affixPat.substring(i, j));
2258:                                i = j + 1;
2259:                                if (i < affixPat.length()
2260:                                        && affixPat.charAt(i) == QUOTE) {
2261:                                    pos = match(text, pos, QUOTE);
2262:                                    ++i;
2263:                                    // loop again
2264:                                } else {
2265:                                    break;
2266:                                }
2267:                            } else {
2268:                                // Unterminated quote; should be caught by apply
2269:                                // pattern.
2270:                                throw new RuntimeException();
2271:                            }
2272:                        }
2273:                        continue;
2274:                    }
2275:
2276:                    switch (c) {
2277:                    case CURRENCY_SIGN:
2278:                        // If currency != null, then perform generic currency matching.
2279:                        // Otherwise, do currency choice parsing.
2280:                        //assert(currency != null ||
2281:                        //       (getCurrency() != null && currencyChoice != null));
2282:                        boolean intl = i < affixPat.length()
2283:                                && affixPat.charAt(i) == CURRENCY_SIGN;
2284:
2285:                        // Parse generic currency -- anything for which we
2286:                        // have a display name, or any 3-letter ISO code.
2287:                        if (currency != null) {
2288:                            // Try to parse display name for our locale; first
2289:                            // determine our locale.
2290:                            ULocale uloc = getLocale(ULocale.VALID_LOCALE);
2291:                            if (uloc == null) {
2292:                                // applyPattern has been called; use the symbols
2293:                                uloc = symbols.getLocale(ULocale.VALID_LOCALE);
2294:                            }
2295:                            // Delegate parse of display name => ISO code to Currency
2296:                            ParsePosition ppos = new ParsePosition(pos);
2297:                            String iso = Currency.parse(uloc, text, ppos);
2298:
2299:                            // If parse succeeds, populate currency[0]
2300:                            if (iso != null) {
2301:                                currency[0] = Currency.getInstance(iso);
2302:                                pos = ppos.getIndex();
2303:                            } else {
2304:                                pos = -1;
2305:                            }
2306:                        } else {
2307:                            if (intl) {
2308:                                ++i;
2309:                                pos = match(text, pos, getCurrency()
2310:                                        .getCurrencyCode());
2311:                            } else {
2312:                                ParsePosition ppos = new ParsePosition(pos);
2313:                                /* Number n = */currencyChoice.parse(text,
2314:                                        ppos);
2315:                                pos = (ppos.getIndex() == pos) ? -1 : ppos
2316:                                        .getIndex();
2317:                            }
2318:                        }
2319:                        continue;
2320:                    case PATTERN_PERCENT:
2321:                        c = symbols.getPercent();
2322:                        break;
2323:                    case PATTERN_PER_MILLE:
2324:                        c = symbols.getPerMill();
2325:                        break;
2326:                    case PATTERN_MINUS:
2327:                        c = symbols.getMinusSign();
2328:                        break;
2329:                    }
2330:                    pos = match(text, pos, c);
2331:                    if (UCharacterProperty.isRuleWhiteSpace(c)) {
2332:                        i = skipRuleWhiteSpace(affixPat, i);
2333:                    }
2334:                }
2335:
2336:                return pos;
2337:            }
2338:
2339:            /**
2340:             * Match a single character at text[pos] and return the index of the
2341:             * next character upon success.  Return -1 on failure.  If
2342:             * isRuleWhiteSpace(ch) then match a run of white space in text.
2343:             */
2344:            static final int match(String text, int pos, int ch) {
2345:                if (UCharacterProperty.isRuleWhiteSpace(ch)) {
2346:                    // Advance over run of white space in input text
2347:                    // Must see at least one white space char in input
2348:                    int s = pos;
2349:                    pos = skipUWhiteSpace(text, pos);
2350:                    if (pos == s) {
2351:                        return -1;
2352:                    }
2353:                    return pos;
2354:                }
2355:                return (pos >= 0 && UTF16.charAt(text, pos) == ch) ? (pos + UTF16
2356:                        .getCharCount(ch))
2357:                        : -1;
2358:            }
2359:
2360:            /**
2361:             * Match a string at text[pos] and return the index of the next
2362:             * character upon success.  Return -1 on failure.  Match a run of
2363:             * white space in str with a run of white space in text.
2364:             */
2365:            static final int match(String text, int pos, String str) {
2366:                for (int i = 0; i < str.length() && pos >= 0;) {
2367:                    int ch = UTF16.charAt(str, i);
2368:                    i += UTF16.getCharCount(ch);
2369:                    pos = match(text, pos, ch);
2370:                    if (UCharacterProperty.isRuleWhiteSpace(ch)) {
2371:                        i = skipRuleWhiteSpace(str, i);
2372:                    }
2373:                }
2374:                return pos;
2375:            }
2376:
2377:            /**
2378:             * Returns a copy of the decimal format symbols used by this format.
2379:             * @return desired DecimalFormatSymbols
2380:             * @see DecimalFormatSymbols
2381:             * @stable ICU 2.0
2382:             */
2383:            public DecimalFormatSymbols getDecimalFormatSymbols() {
2384:                try {
2385:                    // don't allow multiple references
2386:                    return (DecimalFormatSymbols) symbols.clone();
2387:                } catch (Exception foo) {
2388:                    return null; // should never happen
2389:                }
2390:            }
2391:
2392:            /**
2393:             * Sets the decimal format symbols used by this format.  The
2394:             * format uses a copy of the provided symbols.
2395:             * @param newSymbols desired DecimalFormatSymbols
2396:             * @see DecimalFormatSymbols
2397:             * @stable ICU 2.0
2398:             */
2399:            public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
2400:                symbols = (DecimalFormatSymbols) newSymbols.clone();
2401:                setCurrencyForSymbols();
2402:                expandAffixes();
2403:            }
2404:
2405:            /**
2406:             * Update the currency object to match the symbols.  This method
2407:             * is used only when the caller has passed in a symbols object
2408:             * that may not be the default object for its locale.
2409:             */
2410:            private void setCurrencyForSymbols() {
2411:                /*Bug 4212072
2412:                  Update the affix strings accroding to symbols in order to keep
2413:                  the affix strings up to date.
2414:                  [Richard/GCL]
2415:                 */
2416:
2417:                // With the introduction of the Currency object, the currency
2418:                // symbols in the DFS object are ignored.  For backward
2419:                // compatibility, we check any explicitly set DFS object.  If it
2420:                // is a default symbols object for its locale, we change the
2421:                // currency object to one for that locale.  If it is custom,
2422:                // we set the currency to null.
2423:                DecimalFormatSymbols def = new DecimalFormatSymbols(symbols
2424:                        .getLocale());
2425:
2426:                if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())
2427:                        && symbols.getInternationalCurrencySymbol().equals(
2428:                                def.getInternationalCurrencySymbol())) {
2429:                    setCurrency(Currency.getInstance(symbols.getLocale()));
2430:                } else {
2431:                    setCurrency(null);
2432:                }
2433:            }
2434:
2435:            /**
2436:             * Get the positive prefix.
2437:             * <P>Examples: +123, $123, sFr123
2438:             * @stable ICU 2.0
2439:             */
2440:            public String getPositivePrefix() {
2441:                return positivePrefix;
2442:            }
2443:
2444:            /**
2445:             * Set the positive prefix.
2446:             * <P>Examples: +123, $123, sFr123
2447:             * @stable ICU 2.0
2448:             */
2449:            public void setPositivePrefix(String newValue) {
2450:                positivePrefix = newValue;
2451:                posPrefixPattern = null;
2452:            }
2453:
2454:            /**
2455:             * Get the negative prefix.
2456:             * <P>Examples: -123, ($123) (with negative suffix), sFr-123
2457:             * @stable ICU 2.0
2458:             */
2459:            public String getNegativePrefix() {
2460:                return negativePrefix;
2461:            }
2462:
2463:            /**
2464:             * Set the negative prefix.
2465:             * <P>Examples: -123, ($123) (with negative suffix), sFr-123
2466:             * @stable ICU 2.0
2467:             */
2468:            public void setNegativePrefix(String newValue) {
2469:                negativePrefix = newValue;
2470:                negPrefixPattern = null;
2471:            }
2472:
2473:            /**
2474:             * Get the positive suffix.
2475:             * <P>Example: 123%
2476:             * @stable ICU 2.0
2477:             */
2478:            public String getPositiveSuffix() {
2479:                return positiveSuffix;
2480:            }
2481:
2482:            /**
2483:             * Set the positive suffix.
2484:             * <P>Example: 123%
2485:             * @stable ICU 2.0
2486:             */
2487:            public void setPositiveSuffix(String newValue) {
2488:                positiveSuffix = newValue;
2489:                posSuffixPattern = null;
2490:            }
2491:
2492:            /**
2493:             * Get the negative suffix.
2494:             * <P>Examples: -123%, ($123) (with positive suffixes)
2495:             * @stable ICU 2.0
2496:             */
2497:            public String getNegativeSuffix() {
2498:                return negativeSuffix;
2499:            }
2500:
2501:            /**
2502:             * Set the positive suffix.
2503:             * <P>Examples: 123%
2504:             * @stable ICU 2.0
2505:             */
2506:            public void setNegativeSuffix(String newValue) {
2507:                negativeSuffix = newValue;
2508:                negSuffixPattern = null;
2509:            }
2510:
2511:            /**
2512:             * Get the multiplier for use in percent, permill, etc.
2513:             * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
2514:             * (For Arabic, use arabic percent symbol).
2515:             * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
2516:             * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
2517:             * @stable ICU 2.0
2518:             */
2519:            public int getMultiplier() {
2520:                return multiplier;
2521:            }
2522:
2523:            /**
2524:             * Set the multiplier for use in percent, permill, etc.
2525:             * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
2526:             * (For Arabic, use arabic percent symbol).
2527:             * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
2528:             * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
2529:             * @stable ICU 2.0
2530:             */
2531:            public void setMultiplier(int newValue) {
2532:                if (newValue <= 0) {
2533:                    throw new IllegalArgumentException("Bad multiplier: "
2534:                            + newValue);
2535:                }
2536:                multiplier = newValue;
2537:            }
2538:
2539:            /**
2540:             * <strong><font face=helvetica color=red>NEW</font></strong>
2541:             * Get the rounding increment.
2542:             * @return A positive rounding increment, or <code>null</code> if rounding
2543:             * is not in effect.
2544:             * @see #setRoundingIncrement
2545:             * @see #getRoundingMode
2546:             * @see #setRoundingMode
2547:             * @stable ICU 2.0
2548:             */
2549:            //#ifndef FOUNDATION
2550:            public java.math.BigDecimal getRoundingIncrement() {
2551:                if (roundingIncrementICU == null)
2552:                    return null;
2553:                return roundingIncrementICU.toBigDecimal();
2554:            }
2555:
2556:            //#else
2557:            //##    public BigDecimal getRoundingIncrement() {
2558:            //##    	if (roundingIncrementICU == null) return null;
2559:            //##        return new BigDecimal(roundingIncrementICU.toString());
2560:            //##    }
2561:            //#endif
2562:
2563:            //#ifndef FOUNDATION
2564:            /**
2565:             * <strong><font face=helvetica color=red>NEW</font></strong>
2566:             * Set the rounding increment.  This method also controls whether
2567:             * rounding is enabled.
2568:             * @param newValue A positive rounding increment, or <code>null</code> or
2569:             * <code>BigDecimal(0.0)</code> to disable rounding.
2570:             * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
2571:             * @see #getRoundingIncrement
2572:             * @see #getRoundingMode
2573:             * @see #setRoundingMode
2574:             * @stable ICU 2.0
2575:             */
2576:            public void setRoundingIncrement(java.math.BigDecimal newValue) {
2577:                if (newValue == null) {
2578:                    setRoundingIncrement((BigDecimal) null);
2579:                } else {
2580:                    setRoundingIncrement(new BigDecimal(newValue));
2581:                }
2582:            }
2583:
2584:            //#endif
2585:
2586:            /**
2587:             * <strong><font face=helvetica color=red>NEW</font></strong>
2588:             * Set the rounding increment.  This method also controls whether
2589:             * rounding is enabled.
2590:             * @param newValue A positive rounding increment, or <code>null</code> or
2591:             * <code>BigDecimal(0.0)</code> to disable rounding.
2592:             * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
2593:             * @see #getRoundingIncrement
2594:             * @see #getRoundingMode
2595:             * @see #setRoundingMode
2596:             * @draft ICU 3.4.2
2597:             * @provisional This API might change or be removed in a future release.
2598:             */
2599:            public void setRoundingIncrement(BigDecimal newValue) {
2600:                int i = newValue == null ? 0 : newValue
2601:                        .compareTo(BigDecimal.ZERO);
2602:                if (i < 0) {
2603:                    throw new IllegalArgumentException(
2604:                            "Illegal rounding increment");
2605:                }
2606:                if (i == 0) {
2607:                    setInternalRoundingIncrement(null);
2608:                } else {
2609:                    setInternalRoundingIncrement(newValue);
2610:                }
2611:                setRoundingDouble();
2612:            }
2613:
2614:            /**
2615:             * <strong><font face=helvetica color=red>NEW</font></strong>
2616:             * Set the rounding increment.  This method also controls whether
2617:             * rounding is enabled.
2618:             * @param newValue A positive rounding increment, or 0.0 to disable
2619:             * rounding.
2620:             * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
2621:             * @see #getRoundingIncrement
2622:             * @see #getRoundingMode
2623:             * @see #setRoundingMode
2624:             * @stable ICU 2.0
2625:             */
2626:            public void setRoundingIncrement(double newValue) {
2627:                if (newValue < 0.0) {
2628:                    throw new IllegalArgumentException(
2629:                            "Illegal rounding increment");
2630:                }
2631:                roundingDouble = newValue;
2632:                roundingDoubleReciprocal = 0.0d;
2633:                if (newValue == 0.0d) {
2634:                    setRoundingIncrement((BigDecimal) null);
2635:                } else {
2636:                    roundingDouble = newValue;
2637:                    if (roundingDouble < 1.0d) {
2638:                        double rawRoundedReciprocal = 1.0d / roundingDouble;
2639:                        setRoundingDoubleReciprocal(rawRoundedReciprocal);
2640:                    }
2641:                    setInternalRoundingIncrement(new BigDecimal(newValue));
2642:                }
2643:            }
2644:
2645:            private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {
2646:                roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
2647:                if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
2648:                    roundingDoubleReciprocal = 0.0d;
2649:                }
2650:            }
2651:
2652:            static final double roundingIncrementEpsilon = 0.000000001;
2653:
2654:            /**
2655:             * <strong><font face=helvetica color=red>NEW</font></strong>
2656:             * Get the rounding mode.
2657:             * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
2658:             * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
2659:             * @see #setRoundingIncrement
2660:             * @see #getRoundingIncrement
2661:             * @see #setRoundingMode
2662:             * @see java.math.BigDecimal
2663:             * @stable ICU 2.0
2664:             */
2665:            public int getRoundingMode() {
2666:                return roundingMode;
2667:            }
2668:
2669:            /**
2670:             * <strong><font face=helvetica color=red>NEW</font></strong>
2671:             * Set the rounding mode.  This has no effect unless the rounding
2672:             * increment is greater than zero.
2673:             * @param roundingMode A rounding mode, between
2674:             * <code>BigDecimal.ROUND_UP</code> and
2675:             * <code>BigDecimal.ROUND_UNNECESSARY</code>.
2676:             * @exception IllegalArgumentException if <code>roundingMode</code>
2677:             * is unrecognized.
2678:             * @see #setRoundingIncrement
2679:             * @see #getRoundingIncrement
2680:             * @see #getRoundingMode
2681:             * @see java.math.BigDecimal
2682:             * @stable ICU 2.0
2683:             */
2684:            public void setRoundingMode(int roundingMode) {
2685:                if (roundingMode < BigDecimal.ROUND_UP
2686:                        || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
2687:                    throw new IllegalArgumentException(
2688:                            "Invalid rounding mode: " + roundingMode);
2689:                }
2690:                this .roundingMode = roundingMode;
2691:            }
2692:
2693:            /**
2694:             * <strong><font face=helvetica color=red>NEW</font></strong>
2695:             * Get the width to which the output of <code>format()</code> is padded.
2696:             * The width is counted in 16-bit code units.
2697:             * @return the format width, or zero if no padding is in effect
2698:             * @see #setFormatWidth
2699:             * @see #getPadCharacter
2700:             * @see #setPadCharacter
2701:             * @see #getPadPosition
2702:             * @see #setPadPosition
2703:             * @stable ICU 2.0
2704:             */
2705:            public int getFormatWidth() {
2706:                return formatWidth;
2707:            }
2708:
2709:            /**
2710:             * <strong><font face=helvetica color=red>NEW</font></strong>
2711:             * Set the width to which the output of <code>format()</code> is padded.
2712:             * The width is counted in 16-bit code units.
2713:             * This method also controls whether padding is enabled.
2714:             * @param width the width to which to pad the result of
2715:             * <code>format()</code>, or zero to disable padding
2716:             * @exception IllegalArgumentException if <code>width</code> is < 0
2717:             * @see #getFormatWidth
2718:             * @see #getPadCharacter
2719:             * @see #setPadCharacter
2720:             * @see #getPadPosition
2721:             * @see #setPadPosition
2722:             * @stable ICU 2.0
2723:             */
2724:            public void setFormatWidth(int width) {
2725:                if (width < 0) {
2726:                    throw new IllegalArgumentException("Illegal format width");
2727:                }
2728:                formatWidth = width;
2729:            }
2730:
2731:            /**
2732:             * <strong><font face=helvetica color=red>NEW</font></strong>
2733:             * Get the character used to pad to the format width.  The default is ' '.
2734:             * @return the pad character
2735:             * @see #setFormatWidth
2736:             * @see #getFormatWidth
2737:             * @see #setPadCharacter
2738:             * @see #getPadPosition
2739:             * @see #setPadPosition
2740:             * @stable ICU 2.0
2741:             */
2742:            public char getPadCharacter() {
2743:                return pad;
2744:            }
2745:
2746:            /**
2747:             * <strong><font face=helvetica color=red>NEW</font></strong>
2748:             * Set the character used to pad to the format width.  If padding
2749:             * is not enabled, then this will take effect if padding is later
2750:             * enabled.
2751:             * @param padChar the pad character
2752:             * @see #setFormatWidth
2753:             * @see #getFormatWidth
2754:             * @see #getPadCharacter
2755:             * @see #getPadPosition
2756:             * @see #setPadPosition
2757:             * @stable ICU 2.0
2758:             */
2759:            public void setPadCharacter(char padChar) {
2760:                pad = padChar;
2761:            }
2762:
2763:            /**
2764:             * <strong><font face=helvetica color=red>NEW</font></strong>
2765:             * Get the position at which padding will take place.  This is the location
2766:             * at which padding will be inserted if the result of <code>format()</code>
2767:             * is shorter than the format width.
2768:             * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
2769:             * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
2770:             * <code>PAD_AFTER_SUFFIX</code>.
2771:             * @see #setFormatWidth
2772:             * @see #getFormatWidth
2773:             * @see #setPadCharacter
2774:             * @see #getPadCharacter
2775:             * @see #setPadPosition
2776:             * @see #PAD_BEFORE_PREFIX
2777:             * @see #PAD_AFTER_PREFIX
2778:             * @see #PAD_BEFORE_SUFFIX
2779:             * @see #PAD_AFTER_SUFFIX
2780:             * @stable ICU 2.0
2781:             */
2782:            public int getPadPosition() {
2783:                return padPosition;
2784:            }
2785:
2786:            /**
2787:             * <strong><font face=helvetica color=red>NEW</font></strong>
2788:             * Set the position at which padding will take place.  This is the location
2789:             * at which padding will be inserted if the result of <code>format()</code>
2790:             * is shorter than the format width.  This has no effect unless padding is
2791:             * enabled.
2792:             * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
2793:             * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
2794:             * <code>PAD_AFTER_SUFFIX</code>.
2795:             * @exception IllegalArgumentException if the pad position in
2796:             * unrecognized
2797:             * @see #setFormatWidth
2798:             * @see #getFormatWidth
2799:             * @see #setPadCharacter
2800:             * @see #getPadCharacter
2801:             * @see #getPadPosition
2802:             * @see #PAD_BEFORE_PREFIX
2803:             * @see #PAD_AFTER_PREFIX
2804:             * @see #PAD_BEFORE_SUFFIX
2805:             * @see #PAD_AFTER_SUFFIX
2806:             * @stable ICU 2.0
2807:             */
2808:            public void setPadPosition(int padPos) {
2809:                if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
2810:                    throw new IllegalArgumentException("Illegal pad position");
2811:                }
2812:                padPosition = padPos;
2813:            }
2814:
2815:            /**
2816:             * <strong><font face=helvetica color=red>NEW</font></strong>
2817:             * Return whether or not scientific notation is used.
2818:             * @return true if this object formats and parses scientific notation
2819:             * @see #setScientificNotation
2820:             * @see #getMinimumExponentDigits
2821:             * @see #setMinimumExponentDigits
2822:             * @see #isExponentSignAlwaysShown
2823:             * @see #setExponentSignAlwaysShown
2824:             * @stable ICU 2.0
2825:             */
2826:            public boolean isScientificNotation() {
2827:                return useExponentialNotation;
2828:            }
2829:
2830:            /**
2831:             * <strong><font face=helvetica color=red>NEW</font></strong>
2832:             * Set whether or not scientific notation is used.  When scientific notation
2833:             * is used, the effective maximum number of integer digits is <= 8.  If the
2834:             * maximum number of integer digits is set to more than 8, the effective
2835:             * maximum will be 1.  This allows this call to generate a 'default' scientific
2836:             * number format without additional changes.
2837:             * @param useScientific true if this object formats and parses scientific
2838:             * notation
2839:             * @see #isScientificNotation
2840:             * @see #getMinimumExponentDigits
2841:             * @see #setMinimumExponentDigits
2842:             * @see #isExponentSignAlwaysShown
2843:             * @see #setExponentSignAlwaysShown
2844:             * @stable ICU 2.0
2845:             */
2846:            public void setScientificNotation(boolean useScientific) {
2847:                useExponentialNotation = useScientific;
2848:            }
2849:
2850:            /**
2851:             * <strong><font face=helvetica color=red>NEW</font></strong>
2852:             * Return the minimum exponent digits that will be shown.
2853:             * @return the minimum exponent digits that will be shown
2854:             * @see #setScientificNotation
2855:             * @see #isScientificNotation
2856:             * @see #setMinimumExponentDigits
2857:             * @see #isExponentSignAlwaysShown
2858:             * @see #setExponentSignAlwaysShown
2859:             * @stable ICU 2.0
2860:             */
2861:            public byte getMinimumExponentDigits() {
2862:                return minExponentDigits;
2863:            }
2864:
2865:            /**
2866:             * <strong><font face=helvetica color=red>NEW</font></strong>
2867:             * Set the minimum exponent digits that will be shown.  This has no
2868:             * effect unless scientific notation is in use.
2869:             * @param minExpDig a value >= 1 indicating the fewest exponent digits
2870:             * that will be shown
2871:             * @exception IllegalArgumentException if <code>minExpDig</code> < 1
2872:             * @see #setScientificNotation
2873:             * @see #isScientificNotation
2874:             * @see #getMinimumExponentDigits
2875:             * @see #isExponentSignAlwaysShown
2876:             * @see #setExponentSignAlwaysShown
2877:             * @stable ICU 2.0
2878:             */
2879:            public void setMinimumExponentDigits(byte minExpDig) {
2880:                if (minExpDig < 1) {
2881:                    throw new IllegalArgumentException(
2882:                            "Exponent digits must be >= 1");
2883:                }
2884:                minExponentDigits = minExpDig;
2885:            }
2886:
2887:            /**
2888:             * <strong><font face=helvetica color=red>NEW</font></strong>
2889:             * Return whether the exponent sign is always shown.
2890:             * @return true if the exponent is always prefixed with either the
2891:             * localized minus sign or the localized plus sign, false if only negative
2892:             * exponents are prefixed with the localized minus sign.
2893:             * @see #setScientificNotation
2894:             * @see #isScientificNotation
2895:             * @see #setMinimumExponentDigits
2896:             * @see #getMinimumExponentDigits
2897:             * @see #setExponentSignAlwaysShown
2898:             * @stable ICU 2.0
2899:             */
2900:            public boolean isExponentSignAlwaysShown() {
2901:                return exponentSignAlwaysShown;
2902:            }
2903:
2904:            /**
2905:             * <strong><font face=helvetica color=red>NEW</font></strong>
2906:             * Set whether the exponent sign is always shown.  This has no effect
2907:             * unless scientific notation is in use.
2908:             * @param expSignAlways true if the exponent is always prefixed with either
2909:             * the localized minus sign or the localized plus sign, false if only
2910:             * negative exponents are prefixed with the localized minus sign.
2911:             * @see #setScientificNotation
2912:             * @see #isScientificNotation
2913:             * @see #setMinimumExponentDigits
2914:             * @see #getMinimumExponentDigits
2915:             * @see #isExponentSignAlwaysShown
2916:             * @stable ICU 2.0
2917:             */
2918:            public void setExponentSignAlwaysShown(boolean expSignAlways) {
2919:                exponentSignAlwaysShown = expSignAlways;
2920:            }
2921:
2922:            /**
2923:             * Return the grouping size. Grouping size is the number of digits between
2924:             * grouping separators in the integer portion of a number.  For example,
2925:             * in the number "123,456.78", the grouping size is 3.
2926:             * @see #setGroupingSize
2927:             * @see NumberFormat#isGroupingUsed
2928:             * @see DecimalFormatSymbols#getGroupingSeparator
2929:             * @stable ICU 2.0
2930:             */
2931:            public int getGroupingSize() {
2932:                return groupingSize;
2933:            }
2934:
2935:            /**
2936:             * Set the grouping size. Grouping size is the number of digits between
2937:             * grouping separators in the integer portion of a number.  For example,
2938:             * in the number "123,456.78", the grouping size is 3.
2939:             * @see #getGroupingSize
2940:             * @see NumberFormat#setGroupingUsed
2941:             * @see DecimalFormatSymbols#setGroupingSeparator
2942:             * @stable ICU 2.0
2943:             */
2944:            public void setGroupingSize(int newValue) {
2945:                groupingSize = (byte) newValue;
2946:            }
2947:
2948:            /**
2949:             * Return the secondary grouping size. In some locales one
2950:             * grouping interval is used for the least significant integer
2951:             * digits (the primary grouping size), and another is used for all
2952:             * others (the secondary grouping size).  A formatter supporting a
2953:             * secondary grouping size will return a positive integer unequal
2954:             * to the primary grouping size returned by
2955:             * <code>getGroupingSize()</code>.  For example, if the primary
2956:             * grouping size is 4, and the secondary grouping size is 2, then
2957:             * the number 123456789 formats as "1,23,45,6789", and the pattern
2958:             * appears as "#,##,###0".
2959:             * [NEW]
2960:             * @return the secondary grouping size, or a value less than
2961:             * one if there is none
2962:             * @see #setSecondaryGroupingSize
2963:             * @see NumberFormat#isGroupingUsed
2964:             * @see DecimalFormatSymbols#getGroupingSeparator
2965:             * @stable ICU 2.0
2966:             */
2967:            public int getSecondaryGroupingSize() {
2968:                return groupingSize2;
2969:            }
2970:
2971:            /**
2972:             * Set the secondary grouping size. If set to a value less than 1,
2973:             * then secondary grouping is turned off, and the primary grouping
2974:             * size is used for all intervals, not just the least significant.
2975:             * [NEW]
2976:             * @see #getSecondaryGroupingSize
2977:             * @see NumberFormat#setGroupingUsed
2978:             * @see DecimalFormatSymbols#setGroupingSeparator
2979:             * @stable ICU 2.0
2980:             */
2981:            public void setSecondaryGroupingSize(int newValue) {
2982:                groupingSize2 = (byte) newValue;
2983:            }
2984:
2985:            /**
2986:             * Allows you to get the behavior of the decimal separator with integers.
2987:             * (The decimal separator will always appear with decimals.)
2988:             * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
2989:             * @stable ICU 2.0
2990:             */
2991:            public boolean isDecimalSeparatorAlwaysShown() {
2992:                return decimalSeparatorAlwaysShown;
2993:            }
2994:
2995:            /**
2996:             * Allows you to set the behavior of the decimal separator with integers.
2997:             * (The decimal separator will always appear with decimals.)
2998:             *
2999:             * <p>This only affects formatting, and only where
3000:             * there might be no digits after the decimal point, e.g.,
3001:             * if true,  3456.00 -> "3,456."
3002:             * if false, 3456.00 -> "3456"
3003:             * This is independent of parsing.  If you want parsing to stop at the decimal
3004:             * point, use setParseIntegerOnly.
3005:             *
3006:             * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
3007:             * @stable ICU 2.0
3008:             */
3009:            public void setDecimalSeparatorAlwaysShown(boolean newValue) {
3010:                decimalSeparatorAlwaysShown = newValue;
3011:            }
3012:
3013:            /**
3014:             * Standard override; no change in semantics.
3015:             * @stable ICU 2.0
3016:             */
3017:            public Object clone() {
3018:                try {
3019:                    DecimalFormat other = (DecimalFormat) super .clone();
3020:                    other.symbols = (DecimalFormatSymbols) symbols.clone();
3021:                    other.digitList = new DigitList(); // fix for JB#5358
3022:                    /*
3023:                     * TODO: We need to figure out whether we share a single copy
3024:                     * of DigitList by multiple cloned copies.  format/subformat
3025:                     * are designed to use a single instance, but parse/subparse
3026:                     * implementation is not. 
3027:                     */
3028:                    return other;
3029:                } catch (Exception e) {
3030:                    throw new IllegalStateException();
3031:                }
3032:            }
3033:
3034:            /**
3035:             * Overrides equals
3036:             * @stable ICU 2.0
3037:             */
3038:            public boolean equals(Object obj) {
3039:                if (obj == null)
3040:                    return false;
3041:                if (!super .equals(obj))
3042:                    return false; // super does class check
3043:
3044:                DecimalFormat other = (DecimalFormat) obj;
3045:                /* Add the comparison of the four new added fields ,they are
3046:                 * posPrefixPattern, posSuffixPattern, negPrefixPattern, negSuffixPattern.
3047:                 * [Richard/GCL]
3048:                 */
3049:                return (posPrefixPattern != null && equals(posPrefixPattern,
3050:                        other.posPrefixPattern))
3051:                        && (posSuffixPattern != null && equals(
3052:                                posSuffixPattern, other.posSuffixPattern))
3053:                        && (negPrefixPattern != null && equals(
3054:                                negPrefixPattern, other.negPrefixPattern))
3055:                        && (negSuffixPattern != null && equals(
3056:                                negSuffixPattern, other.negSuffixPattern))
3057:                        && multiplier == other.multiplier
3058:                        && groupingSize == other.groupingSize
3059:                        && groupingSize2 == other.groupingSize2
3060:                        && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
3061:                        && useExponentialNotation == other.useExponentialNotation
3062:                        && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
3063:                        && useSignificantDigits == other.useSignificantDigits
3064:                        && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
3065:                                && maxSignificantDigits == other.maxSignificantDigits)
3066:                        && symbols.equals(other.symbols);
3067:            }
3068:
3069:            //method to unquote the strings and compare
3070:            private boolean equals(String pat1, String pat2) {
3071:                //fast path
3072:                if (pat1.equals(pat2)) {
3073:                    return true;
3074:                }
3075:                return unquote(pat1).equals(unquote(pat2));
3076:            }
3077:
3078:            private String unquote(String pat) {
3079:                StringBuffer buf = new StringBuffer(pat.length());
3080:                int i = 0;
3081:                while (i < pat.length()) {
3082:                    char ch = pat.charAt(i++);
3083:                    if (ch != QUOTE) {
3084:                        buf.append(ch);
3085:                    }
3086:                }
3087:                return buf.toString();
3088:            }
3089:
3090:            //      protected void handleToString(StringBuffer buf) {
3091:            //          buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
3092:            //          buf.append("positivePrefix: '" + positivePrefix + "'\n");
3093:            //          buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
3094:            //          buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
3095:            //          buf.append("negPrefixPattern: '" + com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
3096:            //          buf.append("negativePrefix: '" + com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
3097:            //          buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
3098:            //          buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
3099:            //          buf.append("multiplier: '" + multiplier + "'\n");
3100:            //          buf.append("groupingSize: '" + groupingSize + "'\n");
3101:            //          buf.append("groupingSize2: '" + groupingSize2 + "'\n");
3102:            //          buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
3103:            //          buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
3104:            //          buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
3105:            //          buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
3106:            //          buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
3107:            //          buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");           
3108:            //          buf.append("symbols: '" + symbols + "'");
3109:            //      }
3110:
3111:            /**
3112:             * Overrides hashCode
3113:             * @stable ICU 2.0
3114:             */
3115:            public int hashCode() {
3116:                return super .hashCode() * 37 + positivePrefix.hashCode();
3117:                // just enough fields for a reasonable distribution
3118:            }
3119:
3120:            /**
3121:             * Synthesizes a pattern string that represents the current state
3122:             * of this Format object.
3123:             * @see #applyPattern
3124:             * @stable ICU 2.0
3125:             */
3126:            public String toPattern() {
3127:                return toPattern(false);
3128:            }
3129:
3130:            /**
3131:             * Synthesizes a localized pattern string that represents the current
3132:             * state of this Format object.
3133:             * @see #applyPattern
3134:             * @stable ICU 2.0
3135:             */
3136:            public String toLocalizedPattern() {
3137:                return toPattern(true);
3138:            }
3139:
3140:            /**
3141:             * Expand the affix pattern strings into the expanded affix strings.  If any
3142:             * affix pattern string is null, do not expand it.  This method should be
3143:             * called any time the symbols or the affix patterns change in order to keep
3144:             * the expanded affix strings up to date.
3145:             */
3146:            //Bug 4212072 [Richard/GCL]
3147:            private void expandAffixes() {
3148:                // expandAffix() will set currencyChoice to a non-null value if
3149:                // appropriate AND if it is null.
3150:                currencyChoice = null;
3151:
3152:                // Reuse one StringBuffer for better performance
3153:                StringBuffer buffer = new StringBuffer();
3154:                if (posPrefixPattern != null) {
3155:                    expandAffix(posPrefixPattern, buffer, false);
3156:                    positivePrefix = buffer.toString();
3157:                }
3158:                if (posSuffixPattern != null) {
3159:                    expandAffix(posSuffixPattern, buffer, false);
3160:                    positiveSuffix = buffer.toString();
3161:                }
3162:                if (negPrefixPattern != null) {
3163:                    expandAffix(negPrefixPattern, buffer, false);
3164:                    negativePrefix = buffer.toString();
3165:                }
3166:                if (negSuffixPattern != null) {
3167:                    expandAffix(negSuffixPattern, buffer, false);
3168:                    negativeSuffix = buffer.toString();
3169:                }
3170:            }
3171:
3172:            /**
3173:             * Expand an affix pattern into an affix string.  All characters in
3174:             * the pattern are literal unless bracketed by QUOTEs.  The
3175:             * following characters outside QUOTE are recognized:
3176:             * PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
3177:             * CURRENCY_SIGN.  If CURRENCY_SIGN is doubled, it is interpreted as
3178:             * an international currency sign.  Any other character outside
3179:             * QUOTE represents itself.  Quoted text must be well-formed.
3180:             *
3181:             * This method is used in two distinct ways.  First, it is used to expand
3182:             * the stored affix patterns into actual affixes.  For this usage, doFormat
3183:             * must be false.  Second, it is used to expand the stored affix patterns
3184:             * given a specific number (doFormat == true), for those rare cases in
3185:             * which a currency format references a ChoiceFormat (e.g., en_IN display
3186:             * name for INR).  The number itself is taken from digitList.
3187:             *
3188:             * When used in the first way, this method has a side effect: It sets
3189:             * currencyChoice to a ChoiceFormat object, if the currency's display name
3190:             * in this locale is a ChoiceFormat pattern (very rare).  It only does this
3191:             * if currencyChoice is null to start with.
3192:             *
3193:             * @param pattern the non-null, possibly empty pattern
3194:             * @param buffer a scratch StringBuffer; its contents will be lost
3195:             * @param doFormat if false, then the pattern will be expanded, and if a
3196:             * currency symbol is encountered that expands to a ChoiceFormat, the
3197:             * currencyChoice member variable will be initialized if it is null.  If
3198:             * doFormat is true, then it is assumed that the currencyChoice has been
3199:             * created, and it will be used to format the value in digitList.
3200:             * @return the expanded equivalent of pattern
3201:             */
3202:            //Bug 4212072 [Richard/GCL]
3203:            private void expandAffix(String pattern, StringBuffer buffer,
3204:                    boolean doFormat) {
3205:                buffer.setLength(0);
3206:                for (int i = 0; i < pattern.length();) {
3207:                    char c = pattern.charAt(i++);
3208:                    if (c == QUOTE) {
3209:                        for (;;) {
3210:                            int j = pattern.indexOf(QUOTE, i);
3211:                            if (j == i) {
3212:                                buffer.append(QUOTE);
3213:                                i = j + 1;
3214:                                break;
3215:                            } else if (j > i) {
3216:                                buffer.append(pattern.substring(i, j));
3217:                                i = j + 1;
3218:                                if (i < pattern.length()
3219:                                        && pattern.charAt(i) == QUOTE) {
3220:                                    buffer.append(QUOTE);
3221:                                    ++i;
3222:                                    // loop again
3223:                                } else {
3224:                                    break;
3225:                                }
3226:                            } else {
3227:                                // Unterminated quote; should be caught by apply
3228:                                // pattern.
3229:                                throw new RuntimeException();
3230:                            }
3231:                        }
3232:                        continue;
3233:                    }
3234:
3235:                    switch (c) {
3236:                    case CURRENCY_SIGN:
3237:                        // As of ICU 2.2 we use the currency object, and
3238:                        // ignore the currency symbols in the DFS, unless
3239:                        // we have a null currency object.  This occurs if
3240:                        // resurrecting a pre-2.2 object or if the user
3241:                        // sets a custom DFS.
3242:                        boolean intl = i < pattern.length()
3243:                                && pattern.charAt(i) == CURRENCY_SIGN;
3244:                        if (intl) {
3245:                            ++i;
3246:                        }
3247:                        String s = null;
3248:                        Currency currency = getCurrency();
3249:                        if (currency != null) {
3250:                            if (!intl) {
3251:                                boolean isChoiceFormat[] = new boolean[1];
3252:                                s = currency.getName(symbols.getULocale(),
3253:                                        Currency.SYMBOL_NAME, isChoiceFormat);
3254:                                if (isChoiceFormat[0]) {
3255:                                    // Two modes here: If doFormat is false, we set up
3256:                                    // currencyChoice.  If doFormat is true, we use the
3257:                                    // previously created currencyChoice to format the
3258:                                    // value in digitList.
3259:                                    if (!doFormat) {
3260:                                        // If the currency is handled by a ChoiceFormat,
3261:                                        // then we're not going to use the expanded
3262:                                        // patterns.  Instantiate the ChoiceFormat and
3263:                                        // return.
3264:                                        if (currencyChoice == null) {
3265:                                            currencyChoice = new ChoiceFormat(s);
3266:                                        }
3267:                                        // We could almost return null or "" here, since the
3268:                                        // expanded affixes are almost not used at all
3269:                                        // in this situation.  However, one method --
3270:                                        // toPattern() -- still does use the expanded
3271:                                        // affixes, in order to set up a padding
3272:                                        // pattern.  We use the CURRENCY_SIGN as a
3273:                                        // placeholder.
3274:                                        s = String.valueOf(CURRENCY_SIGN);
3275:                                    } else {
3276:                                        FieldPosition pos = new FieldPosition(0); // ignored
3277:                                        currencyChoice.format(digitList
3278:                                                .getDouble(), buffer, pos);
3279:                                        continue;
3280:                                    }
3281:                                }
3282:                            } else {
3283:                                s = currency.getCurrencyCode();
3284:                            }
3285:                        } else {
3286:                            s = intl ? symbols.getInternationalCurrencySymbol()
3287:                                    : symbols.getCurrencySymbol();
3288:                        }
3289:                        buffer.append(s);
3290:                        continue;
3291:                    case PATTERN_PERCENT:
3292:                        c = symbols.getPercent();
3293:                        break;
3294:                    case PATTERN_PER_MILLE:
3295:                        c = symbols.getPerMill();
3296:                        break;
3297:                    case PATTERN_MINUS:
3298:                        c = symbols.getMinusSign();
3299:                        break;
3300:                    }
3301:                    buffer.append(c);
3302:                }
3303:            }
3304:
3305:            /**
3306:             * Append an affix to the given StringBuffer.
3307:             * @param buf buffer to append to
3308:             * @param isNegative
3309:             * @param isPrefix
3310:             */
3311:            private int appendAffix(StringBuffer buf, boolean isNegative,
3312:                    boolean isPrefix, boolean parseAttr) {
3313:                if (currencyChoice != null) {
3314:                    String affixPat = null;
3315:                    if (isPrefix) {
3316:                        affixPat = isNegative ? negPrefixPattern
3317:                                : posPrefixPattern;
3318:                    } else {
3319:                        affixPat = isNegative ? negSuffixPattern
3320:                                : posSuffixPattern;
3321:                    }
3322:                    StringBuffer affixBuf = new StringBuffer();
3323:                    expandAffix(affixPat, affixBuf, true);
3324:                    buf.append(affixBuf.toString());
3325:                    return affixBuf.length();
3326:                }
3327:
3328:                String affix = null;
3329:                if (isPrefix) {
3330:                    affix = isNegative ? negativePrefix : positivePrefix;
3331:                } else {
3332:                    affix = isNegative ? negativeSuffix : positiveSuffix;
3333:                }
3334:                //#ifndef FOUNDATION
3335:                // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
3336:                if (parseAttr) {
3337:                    int offset = affix.indexOf(symbols.getCurrencySymbol());
3338:                    if (-1 == offset) {
3339:                        offset = affix.indexOf(symbols.getPercent());
3340:                        if (-1 == offset) {
3341:                            offset = 0;
3342:                        }
3343:                    }
3344:                    formatAffix2Attribute(affix, buf.length() + offset, buf
3345:                            .length()
3346:                            + affix.length());
3347:                }
3348:                //#endif
3349:                buf.append(affix);
3350:                return affix.length();
3351:            }
3352:
3353:            //#ifndef FOUNDATION
3354:            /*
3355:             * [Spark/CDL] This is a newly added method, used to add attributes for
3356:             * prefix and suffix.
3357:             */
3358:            private void formatAffix2Attribute(String affix, int begin, int end) {
3359:                // [Spark/CDL] It is the invoker's responsibility to ensure that, before
3360:                // the invocation of
3361:                // this method, attributes is not null.
3362:                // if( attributes == null ) return;
3363:                if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
3364:                    addAttribute(Field.CURRENCY, begin, end);
3365:                } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
3366:                    addAttribute(Field.SIGN, begin, end);
3367:                } else if (affix.indexOf(symbols.getPercent()) > -1) {
3368:                    addAttribute(Field.PERCENT, begin, end);
3369:                } else if (affix.indexOf(symbols.getPerMill()) > -1) {
3370:                    addAttribute(Field.PERMILLE, begin, end);
3371:                }
3372:            }
3373:
3374:            //#endif
3375:
3376:            //#ifndef FOUNDATION
3377:            /*
3378:             * [Spark/CDL] Use this method to add attribute.
3379:             */
3380:            private void addAttribute(Field field, int begin, int end) {
3381:                FieldPosition pos = new FieldPosition(field);
3382:                pos.setBeginIndex(begin);
3383:                pos.setEndIndex(end);
3384:                attributes.add(pos);
3385:            }
3386:
3387:            //#endif
3388:
3389:            //#ifndef FOUNDATION
3390:            /**
3391:             * Format the object to an attributed string, and return the corresponding iterator
3392:             * Overrides superclass method.
3393:             * @stable ICU 3.6
3394:             */
3395:            // [Spark/CDL] 
3396:            public AttributedCharacterIterator formatToCharacterIterator(
3397:                    Object obj) {
3398:                if (!(obj instanceof  Number))
3399:                    throw new IllegalArgumentException();
3400:                Number number = (Number) obj;
3401:                StringBuffer text = null;
3402:                attributes.clear();
3403:                if (obj instanceof  BigInteger) {
3404:                    text = format((BigInteger) number, new StringBuffer(),
3405:                            new FieldPosition(0), true);
3406:                } else if (obj instanceof  java.math.BigDecimal) {
3407:                    text = format((java.math.BigDecimal) number,
3408:                            new StringBuffer(), new FieldPosition(0), true);
3409:                } else if (obj instanceof  Double) {
3410:                    text = format(number.doubleValue(), new StringBuffer(),
3411:                            new FieldPosition(0), true);
3412:                } else if (obj instanceof  Integer || obj instanceof  Long) {
3413:                    text = format(number.longValue(), new StringBuffer(),
3414:                            new FieldPosition(0), true);
3415:                }
3416:
3417:                AttributedString as = new AttributedString(text.toString());
3418:
3419:                // add NumberFormat field attributes to the AttributedString
3420:                for (int i = 0; i < attributes.size(); i++) {
3421:                    FieldPosition pos = (FieldPosition) attributes.get(i);
3422:                    Format.Field attribute = pos.getFieldAttribute();
3423:                    as.addAttribute(attribute, attribute, pos.getBeginIndex(),
3424:                            pos.getEndIndex());
3425:                }
3426:
3427:                // return the CharacterIterator from AttributedString
3428:                return as.getIterator();
3429:            }
3430:
3431:            //#endif
3432:            /**
3433:             * Append an affix pattern to the given StringBuffer.  Localize unquoted
3434:             * specials.
3435:             */
3436:            private void appendAffixPattern(StringBuffer buffer,
3437:                    boolean isNegative, boolean isPrefix, boolean localized) {
3438:                String affixPat = null;
3439:                if (isPrefix) {
3440:                    affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
3441:                } else {
3442:                    affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
3443:                }
3444:
3445:                // When there is a null affix pattern, we use the affix itself.
3446:                if (affixPat == null) {
3447:                    String affix = null;
3448:                    if (isPrefix) {
3449:                        affix = isNegative ? negativePrefix : positivePrefix;
3450:                    } else {
3451:                        affix = isNegative ? negativeSuffix : positiveSuffix;
3452:                    }
3453:                    // Do this crudely for now:  Wrap everything in quotes.
3454:                    buffer.append(QUOTE);
3455:                    for (int i = 0; i < affix.length(); ++i) {
3456:                        char ch = affix.charAt(i);
3457:                        if (ch == QUOTE) {
3458:                            buffer.append(ch);
3459:                        }
3460:                        buffer.append(ch);
3461:                    }
3462:                    buffer.append(QUOTE);
3463:                    return;
3464:                }
3465:
3466:                if (!localized) {
3467:                    buffer.append(affixPat);
3468:                } else {
3469:                    int i, j;
3470:                    for (i = 0; i < affixPat.length(); ++i) {
3471:                        char ch = affixPat.charAt(i);
3472:                        switch (ch) {
3473:                        case QUOTE:
3474:                            j = affixPat.indexOf(QUOTE, i + 1);
3475:                            if (j < 0) {
3476:                                throw new IllegalArgumentException(
3477:                                        "Malformed affix pattern: " + affixPat);
3478:                            }
3479:                            buffer.append(affixPat.substring(i, j + 1));
3480:                            i = j;
3481:                            continue;
3482:                        case PATTERN_PER_MILLE:
3483:                            ch = symbols.getPerMill();
3484:                            break;
3485:                        case PATTERN_PERCENT:
3486:                            ch = symbols.getPercent();
3487:                            break;
3488:                        case PATTERN_MINUS:
3489:                            ch = symbols.getMinusSign();
3490:                            break;
3491:                        }
3492:                        //check if char is same as any other symbol
3493:                        if (ch == symbols.getDecimalSeparator()
3494:                                || ch == symbols.getGroupingSeparator()) {
3495:                            buffer.append(QUOTE);
3496:                            buffer.append(ch);
3497:                            buffer.append(QUOTE);
3498:                        } else {
3499:                            buffer.append(ch);
3500:                        }
3501:                    }
3502:                }
3503:            }
3504:
3505:            /**
3506:             * <strong><font face=helvetica color=red>CHANGED</font></strong>
3507:             * Does the real work of generating a pattern.
3508:             */
3509:            private String toPattern(boolean localized) {
3510:                StringBuffer result = new StringBuffer();
3511:                char zero = localized ? symbols.getZeroDigit()
3512:                        : PATTERN_ZERO_DIGIT;
3513:                char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
3514:                char sigDigit = 0;
3515:                boolean useSigDig = areSignificantDigitsUsed();
3516:                if (useSigDig) {
3517:                    sigDigit = localized ? symbols.getSignificantDigit()
3518:                            : PATTERN_SIGNIFICANT_DIGIT;
3519:                }
3520:                char group = localized ? symbols.getGroupingSeparator()
3521:                        : PATTERN_GROUPING_SEPARATOR;
3522:                int i;
3523:                int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
3524:                String roundingDigits = null;
3525:                int padPos = (formatWidth > 0) ? padPosition : -1;
3526:                String padSpec = (formatWidth > 0) ? new StringBuffer(2)
3527:                        .append(
3528:                                localized ? symbols.getPadEscape()
3529:                                        : PATTERN_PAD_ESCAPE).append(pad)
3530:                        .toString() : null;
3531:                if (roundingIncrementICU != null) {
3532:                    i = roundingIncrementICU.scale();
3533:                    roundingDigits = roundingIncrementICU.movePointRight(i)
3534:                            .toString();
3535:                    roundingDecimalPos = roundingDigits.length() - i;
3536:                }
3537:                for (int part = 0; part < 2; ++part) {
3538:                    // variable not used int partStart = result.length();
3539:                    if (padPos == PAD_BEFORE_PREFIX) {
3540:                        result.append(padSpec);
3541:                    }
3542:                    /* Use original symbols read from resources in pattern
3543:                     * eg. use "\u00A4" instead of "$" in Locale.US [Richard/GCL]
3544:                     */
3545:                    appendAffixPattern(result, part != 0, true, localized);
3546:                    if (padPos == PAD_AFTER_PREFIX) {
3547:                        result.append(padSpec);
3548:                    }
3549:                    int sub0Start = result.length();
3550:                    int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
3551:                    if (g > 0 && groupingSize2 > 0
3552:                            && groupingSize2 != groupingSize) {
3553:                        g += groupingSize2;
3554:                    }
3555:                    int maxDig = 0, minDig = 0, maxSigDig = 0;
3556:                    if (useSigDig) {
3557:                        minDig = getMinimumSignificantDigits();
3558:                        maxDig = maxSigDig = getMaximumSignificantDigits();
3559:                    } else {
3560:                        minDig = getMinimumIntegerDigits();
3561:                        maxDig = getMaximumIntegerDigits();
3562:                    }
3563:                    if (useExponentialNotation) {
3564:                        if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
3565:                            maxDig = 1;
3566:                        }
3567:                    } else if (useSigDig) {
3568:                        maxDig = Math.max(maxDig, g + 1);
3569:                    } else {
3570:                        maxDig = Math.max(Math
3571:                                .max(g, getMinimumIntegerDigits()),
3572:                                roundingDecimalPos) + 1;
3573:                    }
3574:                    for (i = maxDig; i > 0; --i) {
3575:                        if (!useExponentialNotation && i < maxDig
3576:                                && isGroupingPosition(i)) {
3577:                            result.append(group);
3578:                        }
3579:                        if (useSigDig) {
3580:                            //  #@,@###   (maxSigDig == 5, minSigDig == 2)
3581:                            //  65 4321   (1-based pos, count from the right)
3582:                            // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
3583:                            // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
3584:                            result
3585:                                    .append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit
3586:                                            : digit);
3587:                        } else {
3588:                            if (roundingDigits != null) {
3589:                                int pos = roundingDecimalPos - i;
3590:                                if (pos >= 0 && pos < roundingDigits.length()) {
3591:                                    result.append((char) (roundingDigits
3592:                                            .charAt(pos) - '0' + zero));
3593:                                    continue;
3594:                                }
3595:                            }
3596:                            result.append(i <= minDig ? zero : digit);
3597:                        }
3598:                    }
3599:                    if (!useSigDig) {
3600:                        if (getMaximumFractionDigits() > 0
3601:                                || decimalSeparatorAlwaysShown) {
3602:                            result.append(localized ? symbols
3603:                                    .getDecimalSeparator()
3604:                                    : PATTERN_DECIMAL_SEPARATOR);
3605:                        }
3606:                        int pos = roundingDecimalPos;
3607:                        for (i = 0; i < getMaximumFractionDigits(); ++i) {
3608:                            if (roundingDigits != null
3609:                                    && pos < roundingDigits.length()) {
3610:                                result
3611:                                        .append(pos < 0 ? zero
3612:                                                : (char) (roundingDigits
3613:                                                        .charAt(pos) - '0' + zero));
3614:                                ++pos;
3615:                                continue;
3616:                            }
3617:                            result.append(i < getMinimumFractionDigits() ? zero
3618:                                    : digit);
3619:                        }
3620:                    }
3621:                    if (useExponentialNotation) {
3622:                        if (localized) {
3623:                            result.append(symbols.getExponentSeparator());
3624:                        } else {
3625:                            result.append(PATTERN_EXPONENT);
3626:                        }
3627:                        if (exponentSignAlwaysShown) {
3628:                            result.append(localized ? symbols.getPlusSign()
3629:                                    : PATTERN_PLUS_SIGN);
3630:                        }
3631:                        for (i = 0; i < minExponentDigits; ++i) {
3632:                            result.append(zero);
3633:                        }
3634:                    }
3635:                    if (padSpec != null && !useExponentialNotation) {
3636:                        int add = formatWidth
3637:                                - result.length()
3638:                                + sub0Start
3639:                                - ((part == 0) ? positivePrefix.length()
3640:                                        + positiveSuffix.length()
3641:                                        : negativePrefix.length()
3642:                                                + negativeSuffix.length());
3643:                        while (add > 0) {
3644:                            result.insert(sub0Start, digit);
3645:                            ++maxDig;
3646:                            --add;
3647:                            // Only add a grouping separator if we have at least
3648:                            // 2 additional characters to be added, so we don't
3649:                            // end up with ",###".
3650:                            if (add > 1 && isGroupingPosition(maxDig)) {
3651:                                result.insert(sub0Start, group);
3652:                                --add;
3653:                            }
3654:                        }
3655:                    }
3656:                    if (padPos == PAD_BEFORE_SUFFIX) {
3657:                        result.append(padSpec);
3658:                    }
3659:                    /* Use original symbols read from resources in pattern
3660:                     * eg. use "\u00A4" instead of "$" in Locale.US [Richard/GCL]
3661:                     */
3662:                    appendAffixPattern(result, part != 0, false, localized);
3663:                    if (padPos == PAD_AFTER_SUFFIX) {
3664:                        result.append(padSpec);
3665:                    }
3666:                    if (part == 0) {
3667:                        if (negativeSuffix.equals(positiveSuffix)
3668:                                && negativePrefix.equals(PATTERN_MINUS
3669:                                        + positivePrefix)) {
3670:                            break;
3671:                        } else {
3672:                            result.append(localized ? symbols
3673:                                    .getPatternSeparator() : PATTERN_SEPARATOR);
3674:                        }
3675:                    }
3676:                }
3677:                return result.toString();
3678:            }
3679:
3680:            /**
3681:             * Apply the given pattern to this Format object.  A pattern is a
3682:             * short-hand specification for the various formatting properties.
3683:             * These properties can also be changed individually through the
3684:             * various setter methods.
3685:             * <p>
3686:             * There is no limit to integer digits are set
3687:             * by this routine, since that is the typical end-user desire;
3688:             * use setMaximumInteger if you want to set a real value.
3689:             * For negative numbers, use a second pattern, separated by a semicolon
3690:             * <P>Example "#,#00.0#" -> 1,234.56
3691:             * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
3692:             * a maximum of 2 fraction digits.
3693:             * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
3694:             * <p>In negative patterns, the minimum and maximum counts are ignored;
3695:             * these are presumed to be set in the positive pattern.
3696:             * @stable ICU 2.0
3697:             */
3698:            public void applyPattern(String pattern) {
3699:                applyPattern(pattern, false);
3700:            }
3701:
3702:            /**
3703:             * Apply the given pattern to this Format object.  The pattern
3704:             * is assumed to be in a localized notation. A pattern is a
3705:             * short-hand specification for the various formatting properties.
3706:             * These properties can also be changed individually through the
3707:             * various setter methods.
3708:             * <p>
3709:             * There is no limit to integer digits are set
3710:             * by this routine, since that is the typical end-user desire;
3711:             * use setMaximumInteger if you want to set a real value.
3712:             * For negative numbers, use a second pattern, separated by a semicolon
3713:             * <P>Example "#,#00.0#" -> 1,234.56
3714:             * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
3715:             * a maximum of 2 fraction digits.
3716:             * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
3717:             * <p>In negative patterns, the minimum and maximum counts are ignored;
3718:             * these are presumed to be set in the positive pattern.
3719:             * @stable ICU 2.0
3720:             */
3721:            public void applyLocalizedPattern(String pattern) {
3722:                applyPattern(pattern, true);
3723:            }
3724:
3725:            /**
3726:             * <strong><font face=helvetica color=red>CHANGED</font></strong>
3727:             * Does the real work of applying a pattern.
3728:             */
3729:            private void applyPattern(String pattern, boolean localized) {
3730:                char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
3731:                char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
3732:                char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
3733:                char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
3734:                char percent = PATTERN_PERCENT;
3735:                char perMill = PATTERN_PER_MILLE;
3736:                char digit = PATTERN_DIGIT; // '#'
3737:                char separator = PATTERN_SEPARATOR;
3738:                String exponent = String.valueOf(PATTERN_EXPONENT);
3739:                char plus = PATTERN_PLUS_SIGN;
3740:                char padEscape = PATTERN_PAD_ESCAPE;
3741:                char minus = PATTERN_MINUS; //Bug 4212072 [Richard/GCL]
3742:                if (localized) {
3743:                    zeroDigit = symbols.getZeroDigit();
3744:                    sigDigit = symbols.getSignificantDigit();
3745:                    groupingSeparator = symbols.getGroupingSeparator();
3746:                    decimalSeparator = symbols.getDecimalSeparator();
3747:                    percent = symbols.getPercent();
3748:                    perMill = symbols.getPerMill();
3749:                    digit = symbols.getDigit();
3750:                    separator = symbols.getPatternSeparator();
3751:                    exponent = symbols.getExponentSeparator();
3752:                    plus = symbols.getPlusSign();
3753:                    padEscape = symbols.getPadEscape();
3754:                    minus = symbols.getMinusSign(); //Bug 4212072 [Richard/GCL]
3755:                }
3756:                char nineDigit = (char) (zeroDigit + 9);
3757:
3758:                boolean gotNegative = false;
3759:
3760:                int pos = 0;
3761:                // Part 0 is the positive pattern.  Part 1, if present, is the negative
3762:                // pattern.
3763:                for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
3764:                    // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
3765:                    // 2=suffix, 3=prefix in quote, 4=suffix in quote.  Subpart 0 is
3766:                    // between the prefix and suffix, and consists of pattern
3767:                    // characters.  In the prefix and suffix, percent, permille, and
3768:                    // currency symbols are recognized and translated.
3769:                    int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
3770:
3771:                    // It's important that we don't change any fields of this object
3772:                    // prematurely.  We set the following variables for the multiplier,
3773:                    // grouping, etc., and then only change the actual object fields if
3774:                    // everything parses correctly.  This also lets us register
3775:                    // the data from part 0 and ignore the part 1, except for the
3776:                    // prefix and suffix.
3777:                    StringBuffer prefix = new StringBuffer();
3778:                    StringBuffer suffix = new StringBuffer();
3779:                    int decimalPos = -1;
3780:                    int multiplier = 1;
3781:                    int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
3782:                    byte groupingCount = -1;
3783:                    byte groupingCount2 = -1;
3784:                    int padPos = -1;
3785:                    char padChar = 0;
3786:                    int incrementPos = -1;
3787:                    long incrementVal = 0;
3788:                    byte expDigits = -1;
3789:                    boolean expSignAlways = false;
3790:                    boolean isCurrency = false;
3791:
3792:                    // The affix is either the prefix or the suffix.
3793:                    StringBuffer affix = prefix;
3794:
3795:                    int start = pos;
3796:
3797:                    PARTLOOP: for (; pos < pattern.length(); ++pos) {
3798:                        char ch = pattern.charAt(pos);
3799:                        switch (subpart) {
3800:                        case 0: // Pattern proper subpart (between prefix & suffix)
3801:                            // Process the digits, decimal, and grouping characters.  We
3802:                            // record five pieces of information.  We expect the digits
3803:                            // to occur in the pattern ####00.00####, and we record the
3804:                            // number of left digits, zero (central) digits, and right
3805:                            // digits.  The position of the last grouping character is
3806:                            // recorded (should be somewhere within the first two blocks
3807:                            // of characters), as is the position of the decimal point,
3808:                            // if any (should be in the zero digits).  If there is no
3809:                            // decimal point, then there should be no right digits.
3810:                            if (ch == digit) {
3811:                                if (zeroDigitCount > 0 || sigDigitCount > 0) {
3812:                                    ++digitRightCount;
3813:                                } else {
3814:                                    ++digitLeftCount;
3815:                                }
3816:                                if (groupingCount >= 0 && decimalPos < 0) {
3817:                                    ++groupingCount;
3818:                                }
3819:                            } else if ((ch >= zeroDigit && ch <= nineDigit)
3820:                                    || ch == sigDigit) {
3821:                                if (digitRightCount > 0) {
3822:                                    patternError("Unexpected '" + ch + '\'',
3823:                                            pattern);
3824:                                }
3825:                                if (ch == sigDigit) {
3826:                                    ++sigDigitCount;
3827:                                } else {
3828:                                    ++zeroDigitCount;
3829:                                    if (ch != zeroDigit) {
3830:                                        int p = digitLeftCount + zeroDigitCount
3831:                                                + digitRightCount;
3832:                                        if (incrementPos >= 0) {
3833:                                            while (incrementPos < p) {
3834:                                                incrementVal *= 10;
3835:                                                ++incrementPos;
3836:                                            }
3837:                                        } else {
3838:                                            incrementPos = p;
3839:                                        }
3840:                                        incrementVal += ch - zeroDigit;
3841:                                    }
3842:                                }
3843:                                if (groupingCount >= 0 && decimalPos < 0) {
3844:                                    ++groupingCount;
3845:                                }
3846:                            } else if (ch == groupingSeparator) {
3847:                                /*Bug 4212072
3848:                                  process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
3849:                                  (Locale="CH", groupingSeparator == QUOTE)                          
3850:                                  [Richard/GCL]
3851:                                 */
3852:                                if (ch == QUOTE && (pos + 1) < pattern.length()) {
3853:                                    char after = pattern.charAt(pos + 1);
3854:                                    if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
3855:                                        // A quote outside quotes indicates either the opening
3856:                                        // quote or two quotes, which is a quote literal.  That is,
3857:                                        // we have the first quote in 'do' or o''clock.
3858:                                        if (after == QUOTE) {
3859:                                            ++pos;
3860:                                            // Fall through to append(ch)
3861:                                        } else {
3862:                                            if (groupingCount < 0) {
3863:                                                subpart = 3; // quoted prefix subpart
3864:                                            } else {
3865:                                                // Transition to suffix subpart
3866:                                                subpart = 2; // suffix subpart
3867:                                                affix = suffix;
3868:                                                sub0Limit = pos--;
3869:                                            }
3870:                                            continue;
3871:                                        }
3872:                                    }
3873:                                }
3874:
3875:                                if (decimalPos >= 0) {
3876:                                    patternError(
3877:                                            "Grouping separator after decimal",
3878:                                            pattern);
3879:                                }
3880:                                groupingCount2 = groupingCount;
3881:                                groupingCount = 0;
3882:                            } else if (ch == decimalSeparator) {
3883:                                if (decimalPos >= 0) {
3884:                                    patternError("Multiple decimal separators",
3885:                                            pattern);
3886:                                }
3887:                                // Intentionally incorporate the digitRightCount,
3888:                                // even though it is illegal for this to be > 0
3889:                                // at this point.  We check pattern syntax below.
3890:                                decimalPos = digitLeftCount + zeroDigitCount
3891:                                        + digitRightCount;
3892:                            } else {
3893:                                if (pattern.regionMatches(pos, exponent, 0,
3894:                                        exponent.length())) {
3895:                                    if (expDigits >= 0) {
3896:                                        patternError(
3897:                                                "Multiple exponential symbols",
3898:                                                pattern);
3899:                                    }
3900:                                    if (groupingCount >= 0) {
3901:                                        patternError(
3902:                                                "Grouping separator in exponential",
3903:                                                pattern);
3904:                                    }
3905:                                    pos += exponent.length();
3906:                                    // Check for positive prefix
3907:                                    if (pos < pattern.length()
3908:                                            && pattern.charAt(pos) == plus) {
3909:                                        expSignAlways = true;
3910:                                        ++pos;
3911:                                    }
3912:                                    // Use lookahead to parse out the exponential part of the
3913:                                    // pattern, then jump into suffix subpart.
3914:                                    expDigits = 0;
3915:                                    while (pos < pattern.length()
3916:                                            && pattern.charAt(pos) == zeroDigit) {
3917:                                        ++expDigits;
3918:                                        ++pos;
3919:                                    }
3920:
3921:                                    // 1. Require at least one mantissa pattern digit
3922:                                    // 2. Disallow "#+ @" in mantissa
3923:                                    // 3. Require at least one exponent pattern digit
3924:                                    if (((digitLeftCount + zeroDigitCount) < 1 && (sigDigitCount + digitRightCount) < 1)
3925:                                            || (sigDigitCount > 0 && digitLeftCount > 0)
3926:                                            || expDigits < 1) {
3927:                                        patternError("Malformed exponential",
3928:                                                pattern);
3929:                                    }
3930:                                }
3931:                                // Transition to suffix subpart
3932:                                subpart = 2; // suffix subpart
3933:                                affix = suffix;
3934:                                sub0Limit = pos--; // backup: for() will increment
3935:                                continue;
3936:                            }
3937:                            break;
3938:                        case 1: // Prefix subpart
3939:                        case 2: // Suffix subpart
3940:                            // Process the prefix / suffix characters
3941:                            // Process unquoted characters seen in prefix or suffix
3942:                            // subpart.
3943:
3944:                            // Several syntax characters implicitly begins the
3945:                            // next subpart if we are in the prefix; otherwise
3946:                            // they are illegal if unquoted.
3947:                            if (ch == digit || ch == groupingSeparator
3948:                                    || ch == decimalSeparator
3949:                                    || (ch >= zeroDigit && ch <= nineDigit)
3950:                                    || ch == sigDigit) {
3951:                                // Any of these characters implicitly begins the
3952:                                // next subpart if we are in the prefix
3953:                                if (subpart == 1) { // prefix subpart
3954:                                    subpart = 0; // pattern proper subpart
3955:                                    sub0Start = pos--; // Reprocess this character
3956:                                    continue;
3957:                                } else if (ch == QUOTE) {
3958:                                    /*Bug 4212072
3959:                                      process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
3960:                                      (Locale="CH", groupingSeparator == QUOTE)                          
3961:                                      [Richard/GCL]
3962:                                     */
3963:                                    // A quote outside quotes indicates either the opening
3964:                                    // quote or two quotes, which is a quote literal.  That is,
3965:                                    // we have the first quote in 'do' or o''clock.
3966:                                    if ((pos + 1) < pattern.length()
3967:                                            && pattern.charAt(pos + 1) == QUOTE) {
3968:                                        ++pos;
3969:                                        affix.append(ch);
3970:                                    } else {
3971:                                        subpart += 2; // open quote
3972:                                    }
3973:                                    continue;
3974:                                }
3975:                                patternError("Unquoted special character '"
3976:                                        + ch + '\'', pattern);
3977:                            } else if (ch == CURRENCY_SIGN) {
3978:                                // Use lookahead to determine if the currency sign is
3979:                                // doubled or not.
3980:                                boolean doubled = (pos + 1) < pattern.length()
3981:                                        && pattern.charAt(pos + 1) == CURRENCY_SIGN;
3982:                                /*Bug 4212072
3983:                                 To meet the need of expandAffix(String, StirngBuffer)
3984:                                 [Richard/GCL]
3985:                                 */
3986:                                if (doubled) {
3987:                                    ++pos; // Skip over the doubled character
3988:                                    affix.append(ch); // append two: one here, one below
3989:                                }
3990:                                isCurrency = true;
3991:                                // Fall through to append(ch)
3992:                            } else if (ch == QUOTE) {
3993:                                // A quote outside quotes indicates either the opening
3994:                                // quote or two quotes, which is a quote literal.  That is,
3995:                                // we have the first quote in 'do' or o''clock.
3996:                                if ((pos + 1) < pattern.length()
3997:                                        && pattern.charAt(pos + 1) == QUOTE) {
3998:                                    ++pos;
3999:                                    affix.append(ch); // append two: one here, one below
4000:                                } else {
4001:                                    subpart += 2; // open quote
4002:                                }
4003:                                // Fall through to append(ch)
4004:                            } else if (ch == separator) {
4005:                                // Don't allow separators in the prefix, and don't allow
4006:                                // separators in the second pattern (part == 1).
4007:                                if (subpart == 1 || part == 1) {
4008:                                    patternError("Unquoted special character '"
4009:                                            + ch + '\'', pattern);
4010:                                }
4011:                                sub2Limit = pos++;
4012:                                break PARTLOOP; // Go to next part
4013:                            } else if (ch == percent || ch == perMill) {
4014:                                // Next handle characters which are appended directly.
4015:                                if (multiplier != 1) {
4016:                                    patternError(
4017:                                            "Too many percent/permille characters",
4018:                                            pattern);
4019:                                }
4020:                                multiplier = (ch == percent) ? 100 : 1000;
4021:                                // Convert to non-localized pattern
4022:                                ch = (ch == percent) ? PATTERN_PERCENT
4023:                                        : PATTERN_PER_MILLE;
4024:                                // Fall through to append(ch)
4025:                            } else if (ch == minus) {
4026:                                // Convert to non-localized pattern
4027:                                ch = PATTERN_MINUS;
4028:                                // Fall through to append(ch)
4029:                            } else if (ch == padEscape) {
4030:                                if (padPos >= 0) {
4031:                                    patternError("Multiple pad specifiers",
4032:                                            pattern);
4033:                                }
4034:                                if ((pos + 1) == pattern.length()) {
4035:                                    patternError("Invalid pad specifier",
4036:                                            pattern);
4037:                                }
4038:                                padPos = pos++; // Advance past pad char
4039:                                padChar = pattern.charAt(pos);
4040:                                continue;
4041:                            }
4042:                            affix.append(ch);
4043:                            break;
4044:                        case 3: // Prefix subpart, in quote
4045:                        case 4: // Suffix subpart, in quote
4046:                            // A quote within quotes indicates either the closing
4047:                            // quote or two quotes, which is a quote literal.  That is,
4048:                            // we have the second quote in 'do' or 'don''t'.
4049:                            if (ch == QUOTE) {
4050:                                if ((pos + 1) < pattern.length()
4051:                                        && pattern.charAt(pos + 1) == QUOTE) {
4052:                                    ++pos;
4053:                                    affix.append(ch);
4054:                                } else {
4055:                                    subpart -= 2; // close quote
4056:                                }
4057:                                // Fall through to append(ch)
4058:                            }
4059:                            // NOTE: In ICU 2.2 there was code here to parse quoted
4060:                            // percent and permille characters _within quotes_ and give
4061:                            // them special meaning.  This is incorrect, since quoted
4062:                            // characters are literals without special meaning.
4063:                            affix.append(ch);
4064:                            break;
4065:                        }
4066:                    }
4067:
4068:                    if (subpart == 3 || subpart == 4) {
4069:                        patternError("Unterminated quote", pattern);
4070:                    }
4071:
4072:                    if (sub0Limit == 0) {
4073:                        sub0Limit = pattern.length();
4074:                    }
4075:
4076:                    if (sub2Limit == 0) {
4077:                        sub2Limit = pattern.length();
4078:                    }
4079:
4080:                    /* Handle patterns with no '0' pattern character.  These patterns
4081:                     * are legal, but must be recodified to make sense.  "##.###" ->
4082:                     * "#0.###".  ".###" -> ".0##".
4083:                     *
4084:                     * We allow patterns of the form "####" to produce a zeroDigitCount
4085:                     * of zero (got that?); although this seems like it might make it
4086:                     * possible for format() to produce empty strings, format() checks
4087:                     * for this condition and outputs a zero digit in this situation.
4088:                     * Having a zeroDigitCount of zero yields a minimum integer digits
4089:                     * of zero, which allows proper round-trip patterns.  We don't want
4090:                     * "#" to become "#0" when toPattern() is called (even though that's
4091:                     * what it really is, semantically).
4092:                     */
4093:                    if (zeroDigitCount == 0 && sigDigitCount == 0
4094:                            && digitLeftCount > 0 && decimalPos >= 0) {
4095:                        // Handle "###.###" and "###." and ".###"
4096:                        int n = decimalPos;
4097:                        if (n == 0)
4098:                            ++n; // Handle ".###"
4099:                        digitRightCount = digitLeftCount - n;
4100:                        digitLeftCount = n - 1;
4101:                        zeroDigitCount = 1;
4102:                    }
4103:
4104:                    // Do syntax checking on the digits, decimal points, and quotes.
4105:                    if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)
4106:                            || (decimalPos >= 0 && (sigDigitCount > 0
4107:                                    || decimalPos < digitLeftCount || decimalPos > (digitLeftCount + zeroDigitCount)))
4108:                            || groupingCount == 0
4109:                            || groupingCount2 == 0
4110:                            || (sigDigitCount > 0 && zeroDigitCount > 0)
4111:                            || subpart > 2) { // subpart > 2 == unmatched quote
4112:                        patternError("Malformed pattern", pattern);
4113:                    }
4114:
4115:                    // Make sure pad is at legal position before or after affix.
4116:                    if (padPos >= 0) {
4117:                        if (padPos == start) {
4118:                            padPos = PAD_BEFORE_PREFIX;
4119:                        } else if (padPos + 2 == sub0Start) {
4120:                            padPos = PAD_AFTER_PREFIX;
4121:                        } else if (padPos == sub0Limit) {
4122:                            padPos = PAD_BEFORE_SUFFIX;
4123:                        } else if (padPos + 2 == sub2Limit) {
4124:                            padPos = PAD_AFTER_SUFFIX;
4125:                        } else {
4126:                            patternError("Illegal pad position", pattern);
4127:                        }
4128:                    }
4129:
4130:                    if (part == 0) {
4131:                        // Set negative affixes temporarily to match the positive
4132:                        // affixes.  Fix this up later after processing both parts.
4133:                        /*Bug 4212072
4134:                          To meet the need of expandAffix(String, StirngBuffer)
4135:                          [Richard/GCL]
4136:                         */
4137:                        posPrefixPattern = negPrefixPattern = prefix.toString();
4138:                        posSuffixPattern = negSuffixPattern = suffix.toString();
4139:
4140:                        useExponentialNotation = (expDigits >= 0);
4141:                        if (useExponentialNotation) {
4142:                            minExponentDigits = expDigits;
4143:                            exponentSignAlwaysShown = expSignAlways;
4144:                        }
4145:                        isCurrencyFormat = isCurrency;
4146:                        int digitTotalCount = digitLeftCount + zeroDigitCount
4147:                                + digitRightCount;
4148:                        // The effectiveDecimalPos is the position the decimal is at or
4149:                        // would be at if there is no decimal.  Note that if
4150:                        // decimalPos<0, then digitTotalCount == digitLeftCount +
4151:                        // zeroDigitCount.
4152:                        int effectiveDecimalPos = decimalPos >= 0 ? decimalPos
4153:                                : digitTotalCount;
4154:                        boolean useSigDig = (sigDigitCount > 0);
4155:                        setSignificantDigitsUsed(useSigDig);
4156:                        if (useSigDig) {
4157:                            setMinimumSignificantDigits(sigDigitCount);
4158:                            setMaximumSignificantDigits(sigDigitCount
4159:                                    + digitRightCount);
4160:                        } else {
4161:                            int minInt = effectiveDecimalPos - digitLeftCount;
4162:                            setMinimumIntegerDigits(minInt);
4163:                            /*Upper limit on integer and fraction digits for a Java double
4164:                              [Richard/GCL]
4165:                             */
4166:                            setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount
4167:                                    + minInt
4168:                                    : DOUBLE_INTEGER_DIGITS);
4169:                            setMaximumFractionDigits(decimalPos >= 0 ? (digitTotalCount - decimalPos)
4170:                                    : 0);
4171:                            setMinimumFractionDigits(decimalPos >= 0 ? (digitLeftCount
4172:                                    + zeroDigitCount - decimalPos)
4173:                                    : 0);
4174:                        }
4175:                        setGroupingUsed(groupingCount > 0);
4176:                        this .groupingSize = (groupingCount > 0) ? groupingCount
4177:                                : 0;
4178:                        this .groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) ? groupingCount2
4179:                                : 0;
4180:                        this .multiplier = multiplier;
4181:                        setDecimalSeparatorAlwaysShown(decimalPos == 0
4182:                                || decimalPos == digitTotalCount);
4183:                        if (padPos >= 0) {
4184:                            padPosition = padPos;
4185:                            formatWidth = sub0Limit - sub0Start; // to be fixed up below
4186:                            pad = padChar;
4187:                        } else {
4188:                            formatWidth = 0;
4189:                        }
4190:                        if (incrementVal != 0) {
4191:                            // BigDecimal scale cannot be negative (even though
4192:                            // this makes perfect sense), so we need to handle this.
4193:                            int scale = incrementPos - effectiveDecimalPos;
4194:                            roundingIncrementICU = BigDecimal.valueOf(
4195:                                    incrementVal, scale > 0 ? scale : 0);
4196:                            if (scale < 0) {
4197:                                roundingIncrementICU = roundingIncrementICU
4198:                                        .movePointRight(-scale);
4199:                            }
4200:                            setRoundingDouble();
4201:                            roundingMode = BigDecimal.ROUND_HALF_EVEN;
4202:                        } else {
4203:                            setRoundingIncrement((BigDecimal) null);
4204:                        }
4205:                    } else {
4206:                        /*Bug 4212072
4207:                          To meet the need of expandAffix(String, StirngBuffer)
4208:                          [Richard/GCL]
4209:                         */
4210:                        negPrefixPattern = prefix.toString();
4211:                        negSuffixPattern = suffix.toString();
4212:                        gotNegative = true;
4213:                    }
4214:                }
4215:
4216:                /*Bug 4140009
4217:                  Process the empty pattern
4218:                  [Richard/GCL]
4219:                 */
4220:                if (pattern.length() == 0) {
4221:                    posPrefixPattern = posSuffixPattern = "";
4222:                    setMinimumIntegerDigits(0);
4223:                    setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
4224:                    setMinimumFractionDigits(0);
4225:                    setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
4226:                }
4227:
4228:                // If there was no negative pattern, or if the negative pattern is
4229:                // identical to the positive pattern, then prepend the minus sign to the
4230:                // positive pattern to form the negative pattern.
4231:                /*Bug 4212072
4232:                  To meet the need of expandAffix(String, StirngBuffer)
4233:                  [Richard/GCL]
4234:                 */
4235:                if (!gotNegative
4236:                        || (negPrefixPattern.equals(posPrefixPattern) && negSuffixPattern
4237:                                .equals(posSuffixPattern))) {
4238:                    negSuffixPattern = posSuffixPattern;
4239:                    negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
4240:                }
4241:                /*Bug 4212072
4242:                  Update the affix strings accroding to symbols in order to keep
4243:                  the affix strings up to date.
4244:                  [Richard/GCL]
4245:                 */
4246:                expandAffixes();
4247:
4248:                // Now that we have the actual prefix and suffix, fix up formatWidth
4249:                if (formatWidth > 0) {
4250:                    formatWidth += positivePrefix.length()
4251:                            + positiveSuffix.length();
4252:                }
4253:
4254:                setLocale(null, null);
4255:            }
4256:
4257:            /**
4258:             * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.
4259:             */
4260:            private void setRoundingDouble() {
4261:                if (roundingIncrementICU == null) {
4262:                    roundingDouble = 0.0d;
4263:                    roundingDoubleReciprocal = 0.0d;
4264:                } else {
4265:                    roundingDouble = roundingIncrementICU.doubleValue();
4266:                    setRoundingDoubleReciprocal(BigDecimal.ONE.divide(
4267:                            roundingIncrementICU, BigDecimal.ROUND_HALF_EVEN)
4268:                            .doubleValue());
4269:                }
4270:            }
4271:
4272:            private void patternError(String msg, String pattern) {
4273:                throw new IllegalArgumentException(msg + " in pattern \""
4274:                        + pattern + '"');
4275:            }
4276:
4277:            /*Rewrite the following 4 "set" methods
4278:              Upper limit on integer and fraction digits for a Java double 
4279:              [Richard/GCL]
4280:             */
4281:            /**
4282:             * Sets the maximum number of digits allowed in the integer portion of a
4283:             * number. This override limits the integer digit count to 309.
4284:             * @see NumberFormat#setMaximumIntegerDigits
4285:             * @stable ICU 2.0
4286:             */
4287:            public void setMaximumIntegerDigits(int newValue) {
4288:                super .setMaximumIntegerDigits(Math.min(newValue,
4289:                        DOUBLE_INTEGER_DIGITS));
4290:            }
4291:
4292:            /**
4293:             * Sets the minimum number of digits allowed in the integer portion of a
4294:             * number. This override limits the integer digit count to 309.
4295:             * @see NumberFormat#setMinimumIntegerDigits
4296:             * @stable ICU 2.0
4297:             */
4298:            public void setMinimumIntegerDigits(int newValue) {
4299:                super .setMinimumIntegerDigits(Math.min(newValue,
4300:                        DOUBLE_INTEGER_DIGITS));
4301:            }
4302:
4303:            /**
4304:             * Returns the minimum number of significant digits that will be
4305:             * displayed. This value has no effect unless areSignificantDigitsUsed()
4306:             * returns true.
4307:             * @return the fewest significant digits that will be shown
4308:             * @stable ICU 3.0
4309:             */
4310:            public int getMinimumSignificantDigits() {
4311:                return minSignificantDigits;
4312:            }
4313:
4314:            /**
4315:             * Returns the maximum number of significant digits that will be
4316:             * displayed. This value has no effect unless areSignificantDigitsUsed()
4317:             * returns true.
4318:             * @return the most significant digits that will be shown
4319:             * @stable ICU 3.0
4320:             */
4321:            public int getMaximumSignificantDigits() {
4322:                return maxSignificantDigits;
4323:            }
4324:
4325:            /**
4326:             * Sets the minimum number of significant digits that will be
4327:             * displayed.  If <code>min</code> is less than one then it is set
4328:             * to one.  If the maximum significant digits count is less than
4329:             * <code>min</code>, then it is set to <code>min</code>. This
4330:             * value has no effect unless areSignificantDigitsUsed() returns true.
4331:             * @param min the fewest significant digits to be shown 
4332:             * @stable ICU 3.0
4333:             */
4334:            public void setMinimumSignificantDigits(int min) {
4335:                if (min < 1) {
4336:                    min = 1;
4337:                }
4338:                // pin max sig dig to >= min
4339:                int max = Math.max(maxSignificantDigits, min);
4340:                minSignificantDigits = min;
4341:                maxSignificantDigits = max;
4342:            }
4343:
4344:            /**
4345:             * Sets the maximum number of significant digits that will be
4346:             * displayed.  If <code>max</code> is less than one then it is set
4347:             * to one.  If the minimum significant digits count is greater
4348:             * than <code>max</code>, then it is set to <code>max</code>. This
4349:             * value has no effect unless areSignificantDigitsUsed() returns true.
4350:             * @param max the most significant digits to be shown 
4351:             * @stable ICU 3.0
4352:             */
4353:            public void setMaximumSignificantDigits(int max) {
4354:                if (max < 1) {
4355:                    max = 1;
4356:                }
4357:                // pin min sig dig to 1..max
4358:                int min = Math.min(minSignificantDigits, max);
4359:                minSignificantDigits = min;
4360:                maxSignificantDigits = max;
4361:            }
4362:
4363:            /**
4364:             * Returns true if significant digits are in use or false if
4365:             * integer and fraction digit counts are in use.
4366:             * @return true if significant digits are in use
4367:             * @stable ICU 3.0
4368:             */
4369:            public boolean areSignificantDigitsUsed() {
4370:                return useSignificantDigits;
4371:            }
4372:
4373:            /**
4374:             * Sets whether significant digits are in use, or integer and
4375:             * fraction digit counts are in use.
4376:             * @param useSignificantDigits true to use significant digits, or
4377:             * false to use integer and fraction digit counts
4378:             * @stable ICU 3.0
4379:             */
4380:            public void setSignificantDigitsUsed(boolean useSignificantDigits) {
4381:                this .useSignificantDigits = useSignificantDigits;
4382:            }
4383:
4384:            /**
4385:             * Sets the <tt>Currency</tt> object used to display currency
4386:             * amounts.  This takes effect immediately, if this format is a
4387:             * currency format.  If this format is not a currency format, then
4388:             * the currency object is used if and when this object becomes a
4389:             * currency format through the application of a new pattern.
4390:             * @param theCurrency new currency object to use.  Must not be
4391:             * null.
4392:             * @stable ICU 2.2
4393:             */
4394:            public void setCurrency(Currency theCurrency) {
4395:                // If we are a currency format, then modify our affixes to
4396:                // encode the currency symbol for the given currency in our
4397:                // locale, and adjust the decimal digits and rounding for the
4398:                // given currency.
4399:
4400:                super .setCurrency(theCurrency);
4401:                if (theCurrency != null) {
4402:                    boolean[] isChoiceFormat = new boolean[1];
4403:                    String s = theCurrency.getName(symbols.getULocale(),
4404:                            Currency.SYMBOL_NAME, isChoiceFormat);
4405:                    symbols.setCurrencySymbol(s);
4406:                    symbols.setInternationalCurrencySymbol(theCurrency
4407:                            .getCurrencyCode());
4408:                }
4409:
4410:                if (isCurrencyFormat) {
4411:                    if (theCurrency != null) {
4412:                        setRoundingIncrement(theCurrency.getRoundingIncrement());
4413:
4414:                        int d = theCurrency.getDefaultFractionDigits();
4415:                        setMinimumFractionDigits(d);
4416:                        setMaximumFractionDigits(d);
4417:                    }
4418:                    expandAffixes();
4419:                }
4420:            }
4421:
4422:            /**
4423:             * Returns the currency in effect for this formatter.  Subclasses
4424:             * should override this method as needed.  Unlike getCurrency(),
4425:             * this method should never return null.
4426:             * @internal
4427:             * @deprecated This API is ICU internal only.
4428:             */
4429:            protected Currency getEffectiveCurrency() {
4430:                Currency c = getCurrency();
4431:                if (c == null) {
4432:                    c = Currency.getInstance(symbols
4433:                            .getInternationalCurrencySymbol());
4434:                }
4435:                return c;
4436:            }
4437:
4438:            /**
4439:             * Sets the maximum number of digits allowed in the fraction portion of a
4440:             * number. This override limits the fraction digit count to 340.
4441:             * @see NumberFormat#setMaximumFractionDigits
4442:             * @stable ICU 2.0
4443:             */
4444:            public void setMaximumFractionDigits(int newValue) {
4445:                super .setMaximumFractionDigits(Math.min(newValue,
4446:                        DOUBLE_FRACTION_DIGITS));
4447:            }
4448:
4449:            /**
4450:             * Sets the minimum number of digits allowed in the fraction portion of a
4451:             * number. This override limits the fraction digit count to 340.
4452:             * @see NumberFormat#setMinimumFractionDigits
4453:             * @stable ICU 2.0
4454:             */
4455:            public void setMinimumFractionDigits(int newValue) {
4456:                super .setMinimumFractionDigits(Math.min(newValue,
4457:                        DOUBLE_FRACTION_DIGITS));
4458:            }
4459:
4460:            /**
4461:             * Sets whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
4462:             * The default value is false.
4463:             * @param value true if {@link #parse(String, ParsePosition)} method returns
4464:             * BigDecimal.
4465:             * @stable ICU 3.6
4466:             */
4467:            public void setParseBigDecimal(boolean value) {
4468:                parseBigDecimal = value;
4469:            }
4470:
4471:            /**
4472:             * Returns whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
4473:             * @return true if {@link #parse(String, ParsePosition)} method returns BigDecimal.
4474:             * @stable ICU 3.6
4475:             */
4476:            public boolean isParseBigDecimal() {
4477:                return parseBigDecimal;
4478:            }
4479:
4480:            //#ifndef FOUNDATION
4481:            private void writeObject(ObjectOutputStream stream)
4482:                    throws IOException, ClassNotFoundException {
4483:                // Doug, do we need this anymore?
4484:                //            if (roundingIncrementICU != null) {
4485:                //                roundingIncrement = roundingIncrementICU.toBigDecimal();
4486:                //            }
4487:
4488:                stream.defaultWriteObject();
4489:            }
4490:
4491:            //#endif
4492:
4493:            /**
4494:             * First, read the default serializable fields from the stream.  Then
4495:             * if <code>serialVersionOnStream</code> is less than 1, indicating that
4496:             * the stream was written by JDK 1.1, initialize <code>useExponentialNotation</code>
4497:             * to false, since it was not present in JDK 1.1.
4498:             * Finally, set serialVersionOnStream back to the maximum allowed value so that
4499:             * default serialization will work properly if this object is streamed out again.
4500:             */
4501:            private void readObject(ObjectInputStream stream)
4502:                    throws IOException, ClassNotFoundException {
4503:                stream.defaultReadObject();
4504:                /*Bug 4185761 validate fields
4505:                  [Richard/GCL]
4506:                 */
4507:                // We only need to check the maximum counts because NumberFormat
4508:                // .readObject has already ensured that the maximum is greater than the
4509:                // minimum count.
4510:                /*Commented for compatibility with previous version, and reserved for further use
4511:                if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
4512:                    getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
4513:                    throw new InvalidObjectException("Digit count out of range");
4514:                }*/
4515:                /* Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and maximumFractionDigits
4516:                 * to DOUBLE_FRACTION_DIGITS
4517:                 */
4518:                if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
4519:                    setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
4520:                }
4521:                if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
4522:                    setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
4523:                }
4524:                if (serialVersionOnStream < 2) {
4525:                    exponentSignAlwaysShown = false;
4526:                    setInternalRoundingIncrement(null);
4527:                    setRoundingDouble();
4528:                    roundingMode = BigDecimal.ROUND_HALF_EVEN;
4529:                    formatWidth = 0;
4530:                    pad = ' ';
4531:                    padPosition = PAD_BEFORE_PREFIX;
4532:                    if (serialVersionOnStream < 1) {
4533:                        // Didn't have exponential fields
4534:                        useExponentialNotation = false;
4535:                    }
4536:                }
4537:                if (serialVersionOnStream < 3) {
4538:                    // Versions prior to 3 do not store a currency object.
4539:                    // Create one to match the DecimalFormatSymbols object.
4540:                    setCurrencyForSymbols();
4541:                }
4542:                serialVersionOnStream = currentSerialVersion;
4543:                digitList = new DigitList();
4544:
4545:                //#ifndef FOUNDATION
4546:                if (roundingIncrement != null) {
4547:                    setInternalRoundingIncrement(new BigDecimal(
4548:                            roundingIncrement));
4549:                    setRoundingDouble();
4550:                }
4551:                //#endif
4552:            }
4553:
4554:            private void setInternalRoundingIncrement(BigDecimal value) {
4555:                roundingIncrementICU = value;
4556:                //#ifndef FOUNDATION
4557:                roundingIncrement = value == null ? null : value.toBigDecimal();
4558:                //#endif
4559:            }
4560:
4561:            //----------------------------------------------------------------------
4562:            // INSTANCE VARIABLES
4563:            //----------------------------------------------------------------------
4564:
4565:            private transient DigitList digitList = new DigitList();
4566:
4567:            /**
4568:             * The symbol used as a prefix when formatting positive numbers, e.g. "+".
4569:             *
4570:             * @serial
4571:             * @see #getPositivePrefix
4572:             */
4573:            private String positivePrefix = "";
4574:
4575:            /**
4576:             * The symbol used as a suffix when formatting positive numbers.
4577:             * This is often an empty string.
4578:             *
4579:             * @serial
4580:             * @see #getPositiveSuffix
4581:             */
4582:            private String positiveSuffix = "";
4583:
4584:            /**
4585:             * The symbol used as a prefix when formatting negative numbers, e.g. "-".
4586:             *
4587:             * @serial
4588:             * @see #getNegativePrefix
4589:             */
4590:            private String negativePrefix = "-";
4591:
4592:            /**
4593:             * The symbol used as a suffix when formatting negative numbers.
4594:             * This is often an empty string.
4595:             *
4596:             * @serial
4597:             * @see #getNegativeSuffix
4598:             */
4599:            private String negativeSuffix = "";
4600:
4601:            /**
4602:             * The prefix pattern for non-negative numbers.  This variable corresponds
4603:             * to <code>positivePrefix</code>.
4604:             *
4605:             * <p>This pattern is expanded by the method <code>expandAffix()</code> to
4606:             * <code>positivePrefix</code> to update the latter to reflect changes in
4607:             * <code>symbols</code>.  If this variable is <code>null</code> then
4608:             * <code>positivePrefix</code> is taken as a literal value that does not
4609:             * change when <code>symbols</code> changes.  This variable is always
4610:             * <code>null</code> for <code>DecimalFormat</code> objects older than
4611:             * stream version 2 restored from stream.
4612:             *
4613:             * @serial
4614:             */
4615:            //[Richard/GCL]
4616:            private String posPrefixPattern;
4617:
4618:            /**
4619:             * The suffix pattern for non-negative numbers.  This variable corresponds
4620:             * to <code>positiveSuffix</code>.  This variable is analogous to
4621:             * <code>posPrefixPattern</code>; see that variable for further
4622:             * documentation.
4623:             *
4624:             * @serial
4625:             */
4626:            //[Richard/GCL]
4627:            private String posSuffixPattern;
4628:
4629:            /**
4630:             * The prefix pattern for negative numbers.  This variable corresponds
4631:             * to <code>negativePrefix</code>.  This variable is analogous to
4632:             * <code>posPrefixPattern</code>; see that variable for further
4633:             * documentation.
4634:             *
4635:             * @serial
4636:             */
4637:            //[Richard/GCL]
4638:            private String negPrefixPattern;
4639:
4640:            /**
4641:             * The suffix pattern for negative numbers.  This variable corresponds
4642:             * to <code>negativeSuffix</code>.  This variable is analogous to
4643:             * <code>posPrefixPattern</code>; see that variable for further
4644:             * documentation.
4645:             *
4646:             * @serial
4647:             */
4648:            //[Richard/GCL]
4649:            private String negSuffixPattern;
4650:
4651:            /**
4652:             * Formatter for ChoiceFormat-based currency names.  If this field
4653:             * is not null, then delegate to it to format currency symbols.
4654:             * @since ICU 2.6
4655:             */
4656:            private ChoiceFormat currencyChoice;
4657:
4658:            /**
4659:             * The multiplier for use in percent, permill, etc.
4660:             *
4661:             * @serial
4662:             * @see #getMultiplier
4663:             */
4664:            private int multiplier = 1;
4665:
4666:            /**
4667:             * The number of digits between grouping separators in the integer
4668:             * portion of a number.  Must be greater than 0 if
4669:             * <code>NumberFormat.groupingUsed</code> is true.
4670:             *
4671:             * @serial
4672:             * @see #getGroupingSize
4673:             * @see NumberFormat#isGroupingUsed
4674:             */
4675:            private byte groupingSize = 3; // invariant, > 0 if useThousands
4676:
4677:            /**
4678:             * The secondary grouping size.  This is only used for Hindi
4679:             * numerals, which use a primary grouping of 3 and a secondary
4680:             * grouping of 2, e.g., "12,34,567".  If this value is less than
4681:             * 1, then secondary grouping is equal to the primary grouping.
4682:             * [NEW]
4683:             */
4684:            private byte groupingSize2 = 0;
4685:
4686:            /**
4687:             * If true, forces the decimal separator to always appear in a formatted
4688:             * number, even if the fractional part of the number is zero.
4689:             *
4690:             * @serial
4691:             * @see #isDecimalSeparatorAlwaysShown
4692:             */
4693:            private boolean decimalSeparatorAlwaysShown = false;
4694:
4695:            /**
4696:             * True if this object represents a currency format.  This determines
4697:             * whether the monetary decimal separator is used instead of the normal one.
4698:             */
4699:            private transient boolean isCurrencyFormat = false;
4700:
4701:            /**
4702:             * The <code>DecimalFormatSymbols</code> object used by this format.
4703:             * It contains the symbols used to format numbers, e.g. the grouping separator,
4704:             * decimal separator, and so on.
4705:             *
4706:             * @serial
4707:             * @see #setDecimalFormatSymbols
4708:             * @see DecimalFormatSymbols
4709:             */
4710:            private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
4711:
4712:            /**
4713:             * True to use significant digits rather than integer and fraction
4714:             * digit counts.
4715:             * @serial
4716:             * @since ICU 3.0
4717:             */
4718:            private boolean useSignificantDigits = false;
4719:
4720:            /**
4721:             * The minimum number of significant digits to show.  Must be >= 1
4722:             * and <= maxSignificantDigits.  Ignored unless
4723:             * useSignificantDigits == true.
4724:             * @serial
4725:             * @since ICU 3.0
4726:             */
4727:            private int minSignificantDigits = 1;
4728:
4729:            /**
4730:             * The maximum number of significant digits to show.  Must be >=
4731:             * minSignficantDigits.  Ignored unless useSignificantDigits ==
4732:             * true.
4733:             * @serial
4734:             * @since ICU 3.0
4735:             */
4736:            private int maxSignificantDigits = 6;
4737:
4738:            /**
4739:             * True to force the use of exponential (i.e. scientific) notation when formatting
4740:             * numbers.
4741:             * <p>
4742:             * Note that the JDK 1.2 public API provides no way to set this field,
4743:             * even though it is supported by the implementation and the stream format.
4744:             * The intent is that this will be added to the API in the future.
4745:             *
4746:             * @serial
4747:             */
4748:            private boolean useExponentialNotation; // Newly persistent in JDK 1.2
4749:
4750:            /**
4751:             * The minimum number of digits used to display the exponent when a number is
4752:             * formatted in exponential notation.  This field is ignored if
4753:             * <code>useExponentialNotation</code> is not true.
4754:             * <p>
4755:             * Note that the JDK 1.2 public API provides no way to set this field,
4756:             * even though it is supported by the implementation and the stream format.
4757:             * The intent is that this will be added to the API in the future.
4758:             *
4759:             * @serial
4760:             */
4761:            private byte minExponentDigits; // Newly persistent in JDK 1.2
4762:
4763:            /**
4764:             * <strong><font face=helvetica color=red>NEW</font></strong>
4765:             * If true, the exponent is always prefixed with either the plus
4766:             * sign or the minus sign.  Otherwise, only negative exponents are
4767:             * prefixed with the minus sign.  This has no effect unless
4768:             * <code>useExponentialNotation</code> is true.
4769:             * @serial
4770:             * @since AlphaWorks NumberFormat
4771:             */
4772:            private boolean exponentSignAlwaysShown = false;
4773:
4774:            //#ifndef FOUNDATION
4775:            /**
4776:             * <strong><font face=helvetica color=red>NEW</font></strong>
4777:             * The value to which numbers are rounded during formatting.  For example,
4778:             * if the rounding increment is 0.05, then 13.371 would be formatted as
4779:             * 13.350, assuming 3 fraction digits.  Has the value <code>null</code> if
4780:             * rounding is not in effect, or a positive value if rounding is in effect.
4781:             * Default value <code>null</code>.
4782:             * @serial
4783:             * @since AlphaWorks NumberFormat
4784:             */
4785:            // Note: this is kept in sync with roundingIncrementICU.
4786:            // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
4787:            private java.math.BigDecimal roundingIncrement = null;
4788:            //#endif
4789:
4790:            /**
4791:             * <strong><font face=helvetica color=red>NEW</font></strong>
4792:             * The value to which numbers are rounded during formatting.  For example,
4793:             * if the rounding increment is 0.05, then 13.371 would be formatted as
4794:             * 13.350, assuming 3 fraction digits.  Has the value <code>null</code> if
4795:             * rounding is not in effect, or a positive value if rounding is in effect.
4796:             * Default value <code>null</code>.
4797:             * WARNING: the roundingIncrement value is the one serialized.
4798:             * @serial
4799:             * @since AlphaWorks NumberFormat
4800:             */
4801:            private transient BigDecimal roundingIncrementICU = null;
4802:
4803:            /**
4804:             * <strong><font face=helvetica color=red>NEW</font></strong>
4805:             * The rounding increment as a double.  If this value is <= 0, then no
4806:             * rounding is done.  This value is
4807:             * <code>roundingIncrementICU.doubleValue()</code>.  Default value 0.0.
4808:             */
4809:            private transient double roundingDouble = 0.0;
4810:
4811:            /**
4812:             * <strong><font face=helvetica color=red>NEW</font></strong>
4813:             * If the roundingDouble is the reciprocal of an integer (the most common case!),
4814:             * this is set to be that integer. Otherwise it is 0.0.
4815:             */
4816:            private transient double roundingDoubleReciprocal = 0.0;
4817:
4818:            /**
4819:             * <strong><font face=helvetica color=red>NEW</font></strong>
4820:             * The rounding mode.  This value controls any rounding operations which
4821:             * occur when applying a rounding increment or when reducing the number of
4822:             * fraction digits to satisfy a maximum fraction digits limit.  The value
4823:             * may assume any of the <code>BigDecimal</code> rounding mode values.
4824:             * Default value <code>BigDecimal.ROUND_HALF_EVEN</code>.
4825:             * @serial
4826:             * @since AlphaWorks NumberFormat
4827:             */
4828:            private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
4829:
4830:            /**
4831:             * <strong><font face=helvetica color=red>NEW</font></strong>
4832:             * The padded format width, or zero if there is no padding.  Must
4833:             * be >= 0.  Default value zero.
4834:             * @serial
4835:             * @since AlphaWorks NumberFormat
4836:             */
4837:            private int formatWidth = 0;
4838:
4839:            /**
4840:             * <strong><font face=helvetica color=red>NEW</font></strong>
4841:             * The character used to pad the result of format to
4842:             * <code>formatWidth</code>, if padding is in effect.  Default value ' '.
4843:             * @serial
4844:             * @since AlphaWorks NumberFormat
4845:             */
4846:            private char pad = ' ';
4847:
4848:            /**
4849:             * <strong><font face=helvetica color=red>NEW</font></strong>
4850:             * The position in the string at which the <code>pad</code> character
4851:             * will be inserted, if padding is in effect.  Must have a value from
4852:             * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>.
4853:             * Default value <code>PAD_BEFORE_PREFIX</code>.
4854:             * @serial
4855:             * @since AlphaWorks NumberFormat
4856:             */
4857:            private int padPosition = PAD_BEFORE_PREFIX;
4858:
4859:            /**
4860:             * True if {@link #parse(String, ParsePosition)} to return BigDecimal
4861:             * rather than Long, Double or BigDecimal except special values.
4862:             * This property is introduced for J2SE 5 compatibility support.
4863:             * @serial
4864:             * @since ICU 3.6
4865:             * @see #setParseBigDecimal(boolean)
4866:             * @see #isParseBigDecimal()
4867:             */
4868:            private boolean parseBigDecimal = false;
4869:
4870:            //----------------------------------------------------------------------
4871:
4872:            static final int currentSerialVersion = 3;
4873:
4874:            /**
4875:             * The internal serial version which says which version was written
4876:             * Possible values are:
4877:             * <ul>
4878:             * <li><b>0</b> (default): versions before JDK 1.2
4879:             * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
4880:             *      <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
4881:             * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth,
4882:             *      pad, padPosition, exponentSignAlwaysShown, roundingIncrement.
4883:             * <li><b>3</b>: ICU 2.2.  Adds currency object.
4884:             * </ul>
4885:             * @serial */
4886:            private int serialVersionOnStream = currentSerialVersion;
4887:
4888:            //----------------------------------------------------------------------
4889:            // CONSTANTS
4890:            //----------------------------------------------------------------------
4891:
4892:            /**
4893:             * <strong><font face=helvetica color=red>NEW</font></strong>
4894:             * Constant for <code>getPadPosition()</code> and
4895:             * <code>setPadPosition()</code> specifying pad characters inserted before
4896:             * the prefix.
4897:             * @see #setPadPosition
4898:             * @see #getPadPosition
4899:             * @see #PAD_AFTER_PREFIX
4900:             * @see #PAD_BEFORE_SUFFIX
4901:             * @see #PAD_AFTER_SUFFIX
4902:             * @stable ICU 2.0
4903:             */
4904:            public static final int PAD_BEFORE_PREFIX = 0;
4905:
4906:            /**
4907:             * <strong><font face=helvetica color=red>NEW</font></strong>
4908:             * Constant for <code>getPadPosition()</code> and
4909:             * <code>setPadPosition()</code> specifying pad characters inserted after
4910:             * the prefix.
4911:             * @see #setPadPosition
4912:             * @see #getPadPosition
4913:             * @see #PAD_BEFORE_PREFIX
4914:             * @see #PAD_BEFORE_SUFFIX
4915:             * @see #PAD_AFTER_SUFFIX
4916:             * @stable ICU 2.0
4917:             */
4918:            public static final int PAD_AFTER_PREFIX = 1;
4919:
4920:            /**
4921:             * <strong><font face=helvetica color=red>NEW</font></strong>
4922:             * Constant for <code>getPadPosition()</code> and
4923:             * <code>setPadPosition()</code> specifying pad characters inserted before
4924:             * the suffix.
4925:             * @see #setPadPosition
4926:             * @see #getPadPosition
4927:             * @see #PAD_BEFORE_PREFIX
4928:             * @see #PAD_AFTER_PREFIX
4929:             * @see #PAD_AFTER_SUFFIX
4930:             * @stable ICU 2.0
4931:             */
4932:            public static final int PAD_BEFORE_SUFFIX = 2;
4933:
4934:            /**
4935:             * <strong><font face=helvetica color=red>NEW</font></strong>
4936:             * Constant for <code>getPadPosition()</code> and
4937:             * <code>setPadPosition()</code> specifying pad characters inserted after
4938:             * the suffix.
4939:             * @see #setPadPosition
4940:             * @see #getPadPosition
4941:             * @see #PAD_BEFORE_PREFIX
4942:             * @see #PAD_AFTER_PREFIX
4943:             * @see #PAD_BEFORE_SUFFIX
4944:             * @stable ICU 2.0
4945:             */
4946:            public static final int PAD_AFTER_SUFFIX = 3;
4947:
4948:            // Constants for characters used in programmatic (unlocalized) patterns.
4949:            private static final char PATTERN_ZERO_DIGIT = '0';
4950:            private static final char PATTERN_GROUPING_SEPARATOR = ',';
4951:            private static final char PATTERN_DECIMAL_SEPARATOR = '.';
4952:            private static final char PATTERN_DIGIT = '#';
4953:            static final char PATTERN_SIGNIFICANT_DIGIT = '@';
4954:            static final char PATTERN_EXPONENT = 'E'; // [NEW]
4955:            static final char PATTERN_PLUS_SIGN = '+'; // [NEW]
4956:
4957:            // Affix
4958:            private static final char PATTERN_PER_MILLE = '\u2030';
4959:            private static final char PATTERN_PERCENT = '%';
4960:            static final char PATTERN_PAD_ESCAPE = '*'; // [NEW]
4961:            /*Bug 4212072
4962:              To meet the need of expandAffix(String, StirngBuffer)
4963:              [Richard/GCL]
4964:             */
4965:            private static final char PATTERN_MINUS = '-'; //[Richard/GCL]
4966:
4967:            // Other    
4968:            private static final char PATTERN_SEPARATOR = ';';
4969:
4970:            // Pad escape is package private to allow access by DecimalFormatSymbols.
4971:            // Also plus sign.  Also exponent.
4972:
4973:            /**
4974:             * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
4975:             * is used in patterns and substitued with either the currency symbol,
4976:             * or if it is doubled, with the international currency symbol.  If the
4977:             * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
4978:             * replaced with the monetary decimal separator.
4979:             *
4980:             * The CURRENCY_SIGN is not localized.
4981:             */
4982:            private static final char CURRENCY_SIGN = '\u00A4';
4983:
4984:            private static final char QUOTE = '\'';
4985:
4986:            /* Upper limit on integer and fraction digits for a Java double
4987:               [Richard/GCL]
4988:             */
4989:            static final int DOUBLE_INTEGER_DIGITS = 309;
4990:            static final int DOUBLE_FRACTION_DIGITS = 340;
4991:
4992:            /**
4993:             * When someone turns on scientific mode, we assume that more than this
4994:             * number of digits is due to flipping from some other mode that didn't
4995:             * restrict the maximum, and so we force 1 integer digit.  We don't bother
4996:             * to track and see if someone is using exponential notation with more than
4997:             * this number, it wouldn't make sense anyway, and this is just to make sure
4998:             * that someone turning on scientific mode with default settings doesn't
4999:             * end up with lots of zeroes.
5000:             */
5001:            static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
5002:
5003:            //#ifdef FOUNDATION
5004:            //##	// we're not compatible with other versions, since we have no java.math.BigDecimal field
5005:            //##	private static final long serialVersionUID = 2;
5006:            //#else
5007:            // Proclaim JDK 1.1 serial compatibility.
5008:            private static final long serialVersionUID = 864413376551465018L;
5009:            //#endif
5010:            private ArrayList attributes = new ArrayList();
5011:        }
5012:
5013:        //eof
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.