Source Code Cross Referenced for DecimalFormat.java in  » 6.0-JDK-Modules » j2me » java » 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 » 6.0 JDK Modules » j2me » java.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * 
0003:         * @(#)DecimalFormat.java	1.71 06/10/10
0004:         * 
0005:         * Portions Copyright  2000-2006 Sun Microsystems, Inc. All Rights
0006:         * Reserved.  Use is subject to license terms.
0007:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0008:         * 
0009:         * This program is free software; you can redistribute it and/or
0010:         * modify it under the terms of the GNU General Public License version
0011:         * 2 only, as published by the Free Software Foundation.
0012:         * 
0013:         * This program is distributed in the hope that it will be useful, but
0014:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0016:         * General Public License version 2 for more details (a copy is
0017:         * included at /legal/license.txt).
0018:         * 
0019:         * You should have received a copy of the GNU General Public License
0020:         * version 2 along with this work; if not, write to the Free Software
0021:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0022:         * 02110-1301 USA
0023:         * 
0024:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0025:         * Clara, CA 95054 or visit www.sun.com if you need additional
0026:         * information or have any questions.
0027:         */
0028:
0029:        /*
0030:         * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
0031:         * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
0032:         *
0033:         *   The original version of this source code and documentation is copyrighted
0034:         * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
0035:         * materials are provided under terms of a License Agreement between Taligent
0036:         * and Sun. This technology is protected by multiple US and International
0037:         * patents. This notice and attribution to Taligent may not be removed.
0038:         *   Taligent is a registered trademark of Taligent, Inc.
0039:         *
0040:         */
0041:
0042:        package java.text;
0043:
0044:        import java.io.InvalidObjectException;
0045:        import java.io.IOException;
0046:        import java.io.ObjectInputStream;
0047:        import java.math.BigInteger;
0048:        import java.util.ArrayList;
0049:        import java.util.Currency;
0050:        import java.util.Hashtable;
0051:        import java.util.Locale;
0052:        import java.util.ResourceBundle;
0053:        import sun.text.resources.LocaleData;
0054:
0055:        /**
0056:         * <code>DecimalFormat</code> is a concrete subclass of
0057:         * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
0058:         * features designed to make it possible to parse and format numbers in any
0059:         * locale, including support for Western, Arabic, and Indic digits.  It also
0060:         * supports different kinds of numbers, including integers (123), fixed-point
0061:         * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
0062:         * currency amounts ($123).  All of these can be localized.
0063:         *
0064:         * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
0065:         * default locale, call one of <code>NumberFormat</code>'s factory methods, such
0066:         * as <code>getInstance()</code>.  In general, do not call the
0067:         * <code>DecimalFormat</code> constructors directly, since the
0068:         * <code>NumberFormat</code> factory methods may return subclasses other than
0069:         * <code>DecimalFormat</code>. If you need to customize the format object, do
0070:         * something like this:
0071:         *
0072:         * <blockquote><pre>
0073:         * NumberFormat f = NumberFormat.getInstance(loc);
0074:         * if (f instanceof DecimalFormat) {
0075:         *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
0076:         * }
0077:         * </pre></blockquote>
0078:         *
0079:         * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
0080:         * <em>symbols</em>.  The pattern may be set directly using
0081:         * <code>applyPattern()</code>, or indirectly using the API methods.  The
0082:         * symbols are stored in a <code>DecimalFormatSymbols</code> object.  When using
0083:         * the <code>NumberFormat</code> factory methods, the pattern and symbols are
0084:         * read from localized <code>ResourceBundle</code>s.
0085:         *
0086:         * <h4>Patterns</h4>
0087:         *
0088:         * <code>DecimalFormat</code> patterns have the following syntax:
0089:         * <blockquote><pre>
0090:         * <i>Pattern:</i>
0091:         *         <i>PositivePattern</i>
0092:         *         <i>PositivePattern</i> ; <i>NegativePattern</i>
0093:         * <i>PositivePattern:</i>
0094:         *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
0095:         * <i>NegativePattern:</i>
0096:         *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
0097:         * <i>Prefix:</i>
0098:         *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
0099:         * <i>Suffix:</i>
0100:         *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
0101:         * <i>Number:</i>
0102:         *         <i>Integer</i> <i>Exponent<sub>opt</sub></i>
0103:         *         <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
0104:         * <i>Integer:</i>
0105:         *         <i>MinimumInteger</i>
0106:         *         #
0107:         *         # <i>Integer</i>
0108:         *         # , <i>Integer</i>
0109:         * <i>MinimumInteger:</i>
0110:         *         0
0111:         *         0 <i>MinimumInteger</i>
0112:         *         0 , <i>MinimumInteger</i>
0113:         * <i>Fraction:</i>
0114:         *         <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
0115:         * <i>MinimumFraction:</i>
0116:         *         0 <i>MinimumFraction<sub>opt</sub></i>
0117:         * <i>OptionalFraction:</i>
0118:         *         # <i>OptionalFraction<sub>opt</sub></i>
0119:         * <i>Exponent:</i>
0120:         *         E <i>MinimumExponent</i>
0121:         * <i>MinimumExponent:</i>
0122:         *         0 <i>MinimumExponent<sub>opt</sub></i>
0123:         * </pre></blockquote>
0124:         *
0125:         * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
0126:         * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>.  Each
0127:         * subpattern has a prefix, numeric part, and suffix. The negative subpattern
0128:         * is optional; if absent, then the positive subpattern prefixed with the
0129:         * localized minus sign (code>'-'</code> in most locales) is used as the
0130:         * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
0131:         * <code>"0.00;-0.00"</code>.  If there is an explicit negative subpattern, it
0132:         * serves only to specify the negative prefix and suffix; the number of digits,
0133:         * minimal digits, and other characteristics are all the same as the positive
0134:         * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
0135:         * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
0136:         *
0137:         * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
0138:         * thousands separators, decimal separators, etc. may be set to arbitrary
0139:         * values, and they will appear properly during formatting.  However, care must
0140:         * be taken that the symbols and strings do not conflict, or parsing will be
0141:         * unreliable.  For example, either the positive and negative prefixes or the
0142:         * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
0143:         * to distinguish positive from negative values.  (If they are identical, then
0144:         * <code>DecimalFormat</code> will behave as if no negative subpattern was
0145:         * specified.)  Another example is that the decimal separator and thousands
0146:         * separator should be distinct characters, or parsing will be impossible.
0147:         *
0148:         * <p>The grouping separator is commonly used for thousands, but in some
0149:         * countries it separates ten-thousands. The grouping size is a constant number
0150:         * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
0151:         * 1,0000,0000.  If you supply a pattern with multiple grouping characters, the
0152:         * interval between the last one and the end of the integer is the one that is
0153:         * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
0154:         * <code>"##,####,####"</code>.
0155:         *
0156:         * <h4>Special Pattern Characters</h4>
0157:         *
0158:         * <p>Many characters in a pattern are taken literally; they are matched during
0159:         * parsing and output unchanged during formatting.  Special characters, on the
0160:         * other hand, stand for other characters, strings, or classes of characters.
0161:         * They must be quoted, unless noted otherwise, if they are to appear in the
0162:         * prefix or suffix as literals.
0163:         *
0164:         * <p>The characters listed here are used in non-localized patterns.  Localized
0165:         * patterns use the corresponding characters taken from this formatter's
0166:         * <code>DecimalFormatSymbols</code> object instead, and these characters lose
0167:         * their special status.  Two exceptions are the currency sign and quote, which
0168:         * are not localized.
0169:         *
0170:         * <blockquote>
0171:         * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
0172:         *  location, localized, and meaning.">
0173:         *     <tr bgcolor="#ccccff">
0174:         *          <th align=left>Symbol
0175:         *          <th align=left>Location
0176:         *          <th align=left>Localized?
0177:         *          <th align=left>Meaning
0178:         *     <tr valign=top>
0179:         *          <td><code>0</code>
0180:         *          <td>Number
0181:         *          <td>Yes
0182:         *          <td>Digit
0183:         *     <tr valign=top bgcolor="#eeeeff">
0184:         *          <td><code>#</code>
0185:         *          <td>Number
0186:         *          <td>Yes
0187:         *          <td>Digit, zero shows as absent
0188:         *     <tr valign=top>
0189:         *          <td><code>.</code>
0190:         *          <td>Number
0191:         *          <td>Yes
0192:         *          <td>Decimal separator or monetary decimal separator
0193:         *     <tr valign=top bgcolor="#eeeeff">
0194:         *          <td><code>-</code>
0195:         *          <td>Number
0196:         *          <td>Yes
0197:         *          <td>Minus sign
0198:         *     <tr valign=top>
0199:         *          <td><code>,</code>
0200:         *          <td>Number
0201:         *          <td>Yes
0202:         *          <td>Grouping separator
0203:         *     <tr valign=top bgcolor="#eeeeff">
0204:         *          <td><code>E</code>
0205:         *          <td>Number
0206:         *          <td>Yes
0207:         *          <td>Separates mantissa and exponent in scientific notation.
0208:         *              <em>Need not be quoted in prefix or suffix.</em>
0209:         *     <tr valign=top>
0210:         *          <td><code>;</code>
0211:         *          <td>Subpattern boundary
0212:         *          <td>Yes
0213:         *          <td>Separates positive and negative subpatterns
0214:         *     <tr valign=top bgcolor="#eeeeff">
0215:         *          <td><code>%</code>
0216:         *          <td>Prefix or suffix
0217:         *          <td>Yes
0218:         *          <td>Multiply by 100 and show as percentage
0219:         *     <tr valign=top>
0220:         *          <td><code>&#92;u2030</code>
0221:         *          <td>Prefix or suffix
0222:         *          <td>Yes
0223:         *          <td>Multiply by 1000 and show as per mille
0224:         *     <tr valign=top bgcolor="#eeeeff">
0225:         *          <td><code>&#164;</code> (<code>&#92;u00A4</code>)
0226:         *          <td>Prefix or suffix
0227:         *          <td>No
0228:         *          <td>Currency sign, replaced by currency symbol.  If
0229:         *              doubled, replaced by international currency symbol.
0230:         *              If present in a pattern, the monetary decimal separator
0231:         *              is used instead of the decimal separator.
0232:         *     <tr valign=top>
0233:         *          <td><code>'</code>
0234:         *          <td>Prefix or suffix
0235:         *          <td>No
0236:         *          <td>Used to quote special characters in a prefix or suffix,
0237:         *              for example, <code>"'#'#"</code> formats 123 to
0238:         *              <code>"#123"</code>.  To create a single quote
0239:         *              itself, use two in a row: <code>"# o''clock"</code>.
0240:         * </table>
0241:         * </blockquote>
0242:         *
0243:         * <h4>Scientific Notation</h4>
0244:         *
0245:         * <p>Numbers in scientific notation are expressed as the product of a mantissa
0246:         * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3.  The
0247:         * mantissa is often in the range 1.0 <= x < 10.0, but it need not be.
0248:         * <code>DecimalFormat</code> can be instructed to format and parse scientific
0249:         * notation <em>only via a pattern</em>; there is currently no factory method
0250:         * that creates a scientific notation format.  In a pattern, the exponent
0251:         * character immediately followed by one or more digit characters indicates
0252:         * scientific notation.  Example: <code>"0.###E0"</code> formats the number
0253:         * 1234 as <code>"1.234E3"</code>.
0254:         *
0255:         * <ul>
0256:         * <li>The number of digit characters after the exponent character gives the
0257:         * minimum exponent digit count.  There is no maximum.  Negative exponents are
0258:         * formatted using the localized minus sign, <em>not</em> the prefix and suffix
0259:         * from the pattern.  This allows patterns such as <code>"0.###E0 m/s"</code>.
0260:         *
0261:         * <li>The minimum and maximum number of integer digits are interpreted
0262:         * together:
0263:         *
0264:         * <ul>
0265:         * <li>If the maximum number of integer digits is greater than their minimum number
0266:         * and greater than 1, it forces the exponent to be a multiple of the maximum
0267:         * number of integer digits, and the minimum number of integer digits to be
0268:         * interpreted as 1.  The most common use of this is to generate
0269:         * <em>engineering notation</em>, in which the exponent is a multiple of three,
0270:         * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
0271:         * formats to <code>"12.345E3"</code>, and 123456 formats to
0272:         * <code>"123.456E3"</code>.
0273:         *
0274:         * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
0275:         * exponent.  Example: 0.00123 formatted with <code>"00.###E0"</code> yields
0276:         * <code>"12.3E-4"</code>.
0277:         * </ul>
0278:         *
0279:         * <li>The number of significant digits in the mantissa is the sum of the
0280:         * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
0281:         * unaffected by the maximum integer digits.  For example, 12345 formatted with
0282:         * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
0283:         * the significant digits count to zero.  The number of significant digits
0284:         * does not affect parsing.
0285:         *
0286:         * <li>Exponential patterns may not contain grouping separators.
0287:         * </ul>
0288:         *
0289:         * <h4>Rounding</h4>
0290:         *
0291:         * <code>DecimalFormat</code> uses half-even rounding (see
0292:         * {@link java.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for
0293:         * formatting.
0294:         * 
0295:         * <h4>Digits</h4>
0296:         *
0297:         * For formatting, <code>DecimalFormat</code> uses the ten consecutive
0298:         * characters starting with the localized zero digit defined in the
0299:         * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
0300:         * digits as well as all Unicode decimal digits, as defined by
0301:         * {@link Character#digit Character.digit}, are recognized.
0302:         *
0303:         * <h4>Special Values</h4>
0304:         *
0305:         * <p><code>NaN</code> is formatted as a single character, typically
0306:         * <code>&#92;uFFFD</code>.  This character is determined by the
0307:         * <code>DecimalFormatSymbols</code> object.  This is the only value for which
0308:         * the prefixes and suffixes are not used.
0309:         *
0310:         * <p>Infinity is formatted as a single character, typically
0311:         * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
0312:         * applied.  The infinity character is determined by the
0313:         * <code>DecimalFormatSymbols</code> object.
0314:         *
0315:         * <p>Negative zero (<code>"-0"</code>) parses to <code>Double(-0.0)</code>,
0316:         * unless <code>isParseIntegerOnly()</code> is true, in which case it parses to
0317:         * <code>Long(0)</code>.
0318:         *
0319:         * <h4><a name="synchronization">Synchronization</a></h4>
0320:         *
0321:         * <p>
0322:         * Decimal formats are generally not synchronized.
0323:         * It is recommended to create separate format instances for each thread.
0324:         * If multiple threads access a format concurrently, it must be synchronized
0325:         * externally.
0326:         *
0327:         * <h4>Example</h4>
0328:         *
0329:         * <blockquote><pre>
0330:         * <strong>// Print out a number using the localized number, integer, currency,
0331:         * // and percent format for each locale</strong>
0332:         * Locale[] locales = NumberFormat.getAvailableLocales();
0333:         * double myNumber = -1234.56;
0334:         * NumberFormat form;
0335:         * for (int j=0; j<4; ++j) {
0336:         *     System.out.println("FORMAT");
0337:         *     for (int i = 0; i < locales.length; ++i) {
0338:         *         if (locales[i].getCountry().length() == 0) {
0339:         *            continue; // Skip language-only locales
0340:         *         }
0341:         *         System.out.print(locales[i].getDisplayName());
0342:         *         switch (j) {
0343:         *         case 0:
0344:         *             form = NumberFormat.getInstance(locales[i]); break;
0345:         *         case 1:
0346:         *             form = NumberFormat.getIntegerInstance(locales[i]); break;
0347:         *         case 2:
0348:         *             form = NumberFormat.getCurrencyInstance(locales[i]); break;
0349:         *         default:
0350:         *             form = NumberFormat.getPercentInstance(locales[i]); break;
0351:         *         }
0352:         *         if (form instanceof DecimalFormat) {
0353:         *             System.out.print(": " + ((DecimalFormat) form).toPattern());
0354:         *         }
0355:         *         System.out.print(" -> " + form.format(myNumber));
0356:         *         try {
0357:         *             System.out.println(" -> " + form.parse(form.format(myNumber)));
0358:         *         } catch (ParseException e) {}
0359:         *     }
0360:         * }
0361:         * </pre></blockquote>
0362:         *
0363:         * @see          <a href="http://java.sun.com/docs/books/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
0364:         * @see          NumberFormat
0365:         * @see          DecimalFormatSymbols
0366:         * @see          ParsePosition
0367:         * @version      1.65, 01/12/04
0368:         * @author       Mark Davis
0369:         * @author       Alan Liu
0370:         */
0371:        public class DecimalFormat extends NumberFormat {
0372:
0373:            /**
0374:             * Creates a DecimalFormat using the default pattern and symbols
0375:             * for the default locale. This is a convenient way to obtain a
0376:             * DecimalFormat when internationalization is not the main concern.
0377:             * <p>
0378:             * To obtain standard formats for a given locale, use the factory methods
0379:             * on NumberFormat such as getNumberInstance. These factories will
0380:             * return the most appropriate sub-class of NumberFormat for a given
0381:             * locale.
0382:             *
0383:             * @see java.text.NumberFormat#getInstance
0384:             * @see java.text.NumberFormat#getNumberInstance
0385:             * @see java.text.NumberFormat#getCurrencyInstance
0386:             * @see java.text.NumberFormat#getPercentInstance
0387:             */
0388:            public DecimalFormat() {
0389:                Locale def = Locale.getDefault();
0390:                // try to get the pattern from the cache
0391:                String pattern = (String) cachedLocaleData.get(def);
0392:                if (pattern == null) { /* cache miss */
0393:                    // Get the pattern for the default locale.
0394:                    ResourceBundle rb = LocaleData.getLocaleElements(def);
0395:                    String[] all = rb.getStringArray("NumberPatterns");
0396:                    pattern = all[0];
0397:                    /* update cache */
0398:                    cachedLocaleData.put(def, pattern);
0399:                }
0400:
0401:                // Always applyPattern after the symbols are set
0402:                this .symbols = new DecimalFormatSymbols(def);
0403:                applyPattern(pattern, false);
0404:            }
0405:
0406:            /**
0407:             * Creates a DecimalFormat using the given pattern and the symbols
0408:             * for the default locale. This is a convenient way to obtain a
0409:             * DecimalFormat when internationalization is not the main concern.
0410:             * <p>
0411:             * To obtain standard formats for a given locale, use the factory methods
0412:             * on NumberFormat such as getNumberInstance. These factories will
0413:             * return the most appropriate sub-class of NumberFormat for a given
0414:             * locale.
0415:             *
0416:             * @param pattern A non-localized pattern string.
0417:             * @exception NullPointerException if <code>pattern</code> is null
0418:             * @exception IllegalArgumentException if the given pattern is invalid.
0419:             * @see java.text.NumberFormat#getInstance
0420:             * @see java.text.NumberFormat#getNumberInstance
0421:             * @see java.text.NumberFormat#getCurrencyInstance
0422:             * @see java.text.NumberFormat#getPercentInstance
0423:             */
0424:            public DecimalFormat(String pattern) {
0425:                // Always applyPattern after the symbols are set
0426:                this .symbols = new DecimalFormatSymbols(Locale.getDefault());
0427:                applyPattern(pattern, false);
0428:            }
0429:
0430:            /**
0431:             * Creates a DecimalFormat using the given pattern and symbols.
0432:             * Use this constructor when you need to completely customize the
0433:             * behavior of the format.
0434:             * <p>
0435:             * To obtain standard formats for a given
0436:             * locale, use the factory methods on NumberFormat such as
0437:             * getInstance or getCurrencyInstance. If you need only minor adjustments
0438:             * to a standard format, you can modify the format returned by
0439:             * a NumberFormat factory method.
0440:             *
0441:             * @param pattern a non-localized pattern string
0442:             * @param symbols the set of symbols to be used
0443:             * @exception NullPointerException if any of the given arguments is null
0444:             * @exception IllegalArgumentException if the given pattern is invalid
0445:             * @see java.text.NumberFormat#getInstance
0446:             * @see java.text.NumberFormat#getNumberInstance
0447:             * @see java.text.NumberFormat#getCurrencyInstance
0448:             * @see java.text.NumberFormat#getPercentInstance
0449:             * @see java.text.DecimalFormatSymbols
0450:             */
0451:            public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
0452:                // Always applyPattern after the symbols are set
0453:                this .symbols = (DecimalFormatSymbols) symbols.clone();
0454:                applyPattern(pattern, false);
0455:            }
0456:
0457:            // Overrides
0458:            /**
0459:             * Formats a double to produce a string.
0460:             * @param number    The double to format
0461:             * @param result    where the text is to be appended
0462:             * @param fieldPosition    On input: an alignment field, if desired.
0463:             * On output: the offsets of the alignment field.
0464:             * @return The formatted number string
0465:             * @see java.text.FieldPosition
0466:             */
0467:            public StringBuffer format(double number, StringBuffer result,
0468:                    FieldPosition fieldPosition) {
0469:                fieldPosition.setBeginIndex(0);
0470:                fieldPosition.setEndIndex(0);
0471:                return format(number, result, fieldPosition.getFieldDelegate());
0472:            }
0473:
0474:            /**
0475:             * Formats a double to produce a string.
0476:             * @param number    The double to format
0477:             * @param result    where the text is to be appended
0478:             * @param delegate notified of locations of sub fields
0479:             * @return The formatted number string
0480:             */
0481:            private StringBuffer format(double number, StringBuffer result,
0482:                    FieldDelegate delegate) {
0483:                if (Double.isNaN(number)) {
0484:                    int iFieldStart = result.length();
0485:
0486:                    result.append(symbols.getNaN());
0487:
0488:                    delegate
0489:                            .formatted(INTEGER_FIELD, Field.INTEGER,
0490:                                    Field.INTEGER, iFieldStart,
0491:                                    result.length(), result);
0492:                    return result;
0493:                }
0494:
0495:                /* Detecting whether a double is negative is easy with the exception of
0496:                 * the value -0.0.  This is a double which has a zero mantissa (and
0497:                 * exponent), but a negative sign bit.  It is semantically distinct from
0498:                 * a zero with a positive sign bit, and this distinction is important
0499:                 * to certain kinds of computations.  However, it's a little tricky to
0500:                 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0).  How then, you may
0501:                 * ask, does it behave distinctly from +0.0?  Well, 1/(-0.0) ==
0502:                 * -Infinity.  Proper detection of -0.0 is needed to deal with the
0503:                 * issues raised by bugs 4106658, 4106667, and 4147706.  Liu 7/6/98.
0504:                 */
0505:                boolean isNegative = (number < 0.0)
0506:                        || (number == 0.0 && 1 / number < 0.0);
0507:                if (isNegative)
0508:                    number = -number;
0509:
0510:                // Do this BEFORE checking to see if value is infinite!
0511:                if (multiplier != 1)
0512:                    number *= multiplier;
0513:
0514:                if (Double.isInfinite(number)) {
0515:                    if (isNegative) {
0516:                        append(result, negativePrefix, delegate,
0517:                                getNegativePrefixFieldPositions(), Field.SIGN);
0518:                    } else {
0519:                        append(result, positivePrefix, delegate,
0520:                                getPositivePrefixFieldPositions(), Field.SIGN);
0521:                    }
0522:                    int iFieldStart = result.length();
0523:
0524:                    result.append(symbols.getInfinity());
0525:
0526:                    delegate
0527:                            .formatted(INTEGER_FIELD, Field.INTEGER,
0528:                                    Field.INTEGER, iFieldStart,
0529:                                    result.length(), result);
0530:
0531:                    if (isNegative) {
0532:                        append(result, negativeSuffix, delegate,
0533:                                getNegativeSuffixFieldPositions(), Field.SIGN);
0534:                    } else {
0535:                        append(result, positiveSuffix, delegate,
0536:                                getPositiveSuffixFieldPositions(), Field.SIGN);
0537:                    }
0538:                    return result;
0539:                }
0540:
0541:                // At this point we are guaranteed a nonnegative finite
0542:                // number.
0543:                synchronized (digitList) {
0544:                    digitList.set(number,
0545:                            useExponentialNotation ? getMaximumIntegerDigits()
0546:                                    + getMaximumFractionDigits()
0547:                                    : getMaximumFractionDigits(),
0548:                            !useExponentialNotation);
0549:
0550:                    return subformat(result, delegate, isNegative, false);
0551:                }
0552:            }
0553:
0554:            /**
0555:             * Format a long to produce a string.
0556:             * @param number    The long to format
0557:             * @param result    where the text is to be appended
0558:             * @param fieldPosition    On input: an alignment field, if desired.
0559:             * On output: the offsets of the alignment field.
0560:             * @return The formatted number string
0561:             * @see java.text.FieldPosition
0562:             */
0563:            public StringBuffer format(long number, StringBuffer result,
0564:                    FieldPosition fieldPosition) {
0565:                fieldPosition.setBeginIndex(0);
0566:                fieldPosition.setEndIndex(0);
0567:
0568:                return format(number, result, fieldPosition.getFieldDelegate());
0569:            }
0570:
0571:            /**
0572:             * Format a long to produce a string.
0573:             * @param number    The long to format
0574:             * @param result    where the text is to be appended
0575:             * @param delegate notified of locations of sub fields
0576:             * @return The formatted number string
0577:             * @see java.text.FieldPosition
0578:             */
0579:            private StringBuffer format(long number, StringBuffer result,
0580:                    FieldDelegate delegate) {
0581:                boolean isNegative = (number < 0);
0582:                if (isNegative)
0583:                    number = -number;
0584:
0585:                // In general, long values always represent real finite numbers, so
0586:                // we don't have to check for +/- Infinity or NaN.  However, there
0587:                // is one case we have to be careful of:  The multiplier can push
0588:                // a number near MIN_VALUE or MAX_VALUE outside the legal range.  We
0589:                // check for this before multiplying, and if it happens we use doubles
0590:                // instead, trading off accuracy for range.
0591:                if (multiplier != 1 && multiplier != 0) {
0592:                    boolean useDouble = false;
0593:
0594:                    if (number < 0) // This can only happen if number == Long.MIN_VALUE
0595:                    {
0596:                        long cutoff = Long.MIN_VALUE / multiplier;
0597:                        useDouble = (number < cutoff);
0598:                    } else {
0599:                        long cutoff = Long.MAX_VALUE / multiplier;
0600:                        useDouble = (number > cutoff);
0601:                    }
0602:
0603:                    if (useDouble) {
0604:                        double dnumber = (double) (isNegative ? -number
0605:                                : number);
0606:                        return format(dnumber, result, delegate);
0607:                    }
0608:                }
0609:
0610:                number *= multiplier;
0611:                synchronized (digitList) {
0612:                    digitList.set(number,
0613:                            useExponentialNotation ? getMaximumIntegerDigits()
0614:                                    + getMaximumFractionDigits() : 0);
0615:
0616:                    return subformat(result, delegate, isNegative, true);
0617:                }
0618:            }
0619:
0620:            /**
0621:             * Formats an Object producing an <code>AttributedCharacterIterator</code>.
0622:             * You can use the returned <code>AttributedCharacterIterator</code>
0623:             * to build the resulting String, as well as to determine information
0624:             * about the resulting String.
0625:             * <p>
0626:             * Each attribute key of the AttributedCharacterIterator will be of type
0627:             * <code>NumberFormat.Field</code>, with the attribute value being the
0628:             * same as the attribute key.
0629:             *
0630:             * @exception NullPointerException if obj is null.
0631:             * @exception IllegalArgumentException when the Format cannot format the
0632:             *            given object.
0633:             * @param obj The object to format
0634:             * @return AttributedCharacterIterator describing the formatted value.
0635:             * @since 1.4
0636:             */
0637:            public AttributedCharacterIterator formatToCharacterIterator(
0638:                    Object obj) {
0639:                CharacterIteratorFieldDelegate delegate = new CharacterIteratorFieldDelegate();
0640:                StringBuffer sb = new StringBuffer();
0641:
0642:                if (obj instanceof  Long
0643:                        || (obj instanceof  BigInteger && ((BigInteger) obj)
0644:                                .bitLength() < 64)) {
0645:                    format(((Number) obj).longValue(), sb, delegate);
0646:                } else if (obj == null) {
0647:                    throw new NullPointerException(
0648:                            "formatToCharacterIterator must be passed non-null object");
0649:                } else if (obj instanceof  Number) {
0650:                    format(((Number) obj).doubleValue(), sb, delegate);
0651:                } else {
0652:                    throw new IllegalArgumentException(
0653:                            "Cannot format given Object as a Number");
0654:                }
0655:                return delegate.getIterator(sb.toString());
0656:            }
0657:
0658:            /**
0659:             * Complete the formatting of a finite number.  On entry, the digitList must
0660:             * be filled in with the correct digits.
0661:             */
0662:            private StringBuffer subformat(StringBuffer result,
0663:                    FieldDelegate delegate, boolean isNegative,
0664:                    boolean isInteger) {
0665:                // NOTE: This isn't required anymore because DigitList takes care of this.
0666:                //
0667:                //  // The negative of the exponent represents the number of leading
0668:                //  // zeros between the decimal and the first non-zero digit, for
0669:                //  // a value < 0.1 (e.g., for 0.00123, -fExponent == 2).  If this
0670:                //  // is more than the maximum fraction digits, then we have an underflow
0671:                //  // for the printed representation.  We recognize this here and set
0672:                //  // the DigitList representation to zero in this situation.
0673:                //
0674:                //  if (-digitList.decimalAt >= getMaximumFractionDigits())
0675:                //  {
0676:                //      digitList.count = 0;
0677:                //  }
0678:
0679:                char zero = symbols.getZeroDigit();
0680:                int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
0681:                char grouping = symbols.getGroupingSeparator();
0682:                char decimal = isCurrencyFormat ? symbols
0683:                        .getMonetaryDecimalSeparator() : symbols
0684:                        .getDecimalSeparator();
0685:
0686:                /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
0687:                 * format as zero.  This allows sensible computations and preserves
0688:                 * relations such as signum(1/x) = signum(x), where x is +Infinity or
0689:                 * -Infinity.  Prior to this fix, we always formatted zero values as if
0690:                 * they were positive.  Liu 7/6/98.
0691:                 */
0692:                if (digitList.isZero()) {
0693:                    digitList.decimalAt = 0; // Normalize
0694:                }
0695:
0696:                int fieldStart = result.length();
0697:
0698:                if (isNegative) {
0699:                    append(result, negativePrefix, delegate,
0700:                            getNegativePrefixFieldPositions(), Field.SIGN);
0701:                } else {
0702:                    append(result, positivePrefix, delegate,
0703:                            getPositivePrefixFieldPositions(), Field.SIGN);
0704:                }
0705:
0706:                if (useExponentialNotation) {
0707:                    int iFieldStart = result.length();
0708:                    int iFieldEnd = -1;
0709:                    int fFieldStart = -1;
0710:
0711:                    // Minimum integer digits are handled in exponential format by
0712:                    // adjusting the exponent.  For example, 0.01234 with 3 minimum
0713:                    // integer digits is "123.4E-4".
0714:
0715:                    // Maximum integer digits are interpreted as indicating the
0716:                    // repeating range.  This is useful for engineering notation, in
0717:                    // which the exponent is restricted to a multiple of 3.  For
0718:                    // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
0719:                    // If maximum integer digits are > 1 and are larger than
0720:                    // minimum integer digits, then minimum integer digits are
0721:                    // ignored.
0722:                    int exponent = digitList.decimalAt;
0723:                    int repeat = getMaximumIntegerDigits();
0724:                    int minimumIntegerDigits = getMinimumIntegerDigits();
0725:                    if (repeat > 1 && repeat > minimumIntegerDigits) {
0726:                        // A repeating range is defined; adjust to it as follows.
0727:                        // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
0728:                        // -3,-4,-5=>-6, etc. This takes into account that the
0729:                        // exponent we have here is off by one from what we expect;
0730:                        // it is for the format 0.MMMMMx10^n.
0731:                        if (exponent >= 1) {
0732:                            exponent = ((exponent - 1) / repeat) * repeat;
0733:                        } else {
0734:                            // integer division rounds towards 0
0735:                            exponent = ((exponent - repeat) / repeat) * repeat;
0736:                        }
0737:                        minimumIntegerDigits = 1;
0738:                    } else {
0739:                        // No repeating range is defined; use minimum integer digits.
0740:                        exponent -= minimumIntegerDigits;
0741:                    }
0742:
0743:                    // We now output a minimum number of digits, and more if there
0744:                    // are more digits, up to the maximum number of digits.  We
0745:                    // place the decimal point after the "integer" digits, which
0746:                    // are the first (decimalAt - exponent) digits.
0747:                    int minimumDigits = getMinimumIntegerDigits()
0748:                            + getMinimumFractionDigits();
0749:                    // The number of integer digits is handled specially if the number
0750:                    // is zero, since then there may be no digits.
0751:                    int integerDigits = digitList.isZero() ? minimumIntegerDigits
0752:                            : digitList.decimalAt - exponent;
0753:                    if (minimumDigits < integerDigits) {
0754:                        minimumDigits = integerDigits;
0755:                    }
0756:                    int totalDigits = digitList.count;
0757:                    if (minimumDigits > totalDigits)
0758:                        totalDigits = minimumDigits;
0759:                    boolean addedDecimalSeparator = false;
0760:
0761:                    for (int i = 0; i < totalDigits; ++i) {
0762:                        if (i == integerDigits) {
0763:                            // Record field information for caller.
0764:                            iFieldEnd = result.length();
0765:
0766:                            result.append(decimal);
0767:                            addedDecimalSeparator = true;
0768:
0769:                            // Record field information for caller.
0770:                            fFieldStart = result.length();
0771:
0772:                        }
0773:                        result
0774:                                .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta)
0775:                                        : zero);
0776:                    }
0777:
0778:                    // Record field information
0779:                    if (iFieldEnd == -1) {
0780:                        iFieldEnd = result.length();
0781:                    }
0782:                    delegate.formatted(INTEGER_FIELD, Field.INTEGER,
0783:                            Field.INTEGER, iFieldStart, iFieldEnd, result);
0784:                    if (addedDecimalSeparator) {
0785:                        delegate.formatted(Field.DECIMAL_SEPARATOR,
0786:                                Field.DECIMAL_SEPARATOR, iFieldEnd,
0787:                                fFieldStart, result);
0788:                    }
0789:                    if (fFieldStart == -1) {
0790:                        fFieldStart = result.length();
0791:                    }
0792:                    delegate.formatted(FRACTION_FIELD, Field.FRACTION,
0793:                            Field.FRACTION, fFieldStart, result.length(),
0794:                            result);
0795:
0796:                    // The exponent is output using the pattern-specified minimum
0797:                    // exponent digits.  There is no maximum limit to the exponent
0798:                    // digits, since truncating the exponent would result in an
0799:                    // unacceptable inaccuracy.
0800:                    fieldStart = result.length();
0801:
0802:                    result.append(symbols.getExponentialSymbol());
0803:
0804:                    delegate.formatted(Field.EXPONENT_SYMBOL,
0805:                            Field.EXPONENT_SYMBOL, fieldStart, result.length(),
0806:                            result);
0807:
0808:                    // For zero values, we force the exponent to zero.  We
0809:                    // must do this here, and not earlier, because the value
0810:                    // is used to determine integer digit count above.
0811:                    if (digitList.isZero())
0812:                        exponent = 0;
0813:
0814:                    boolean negativeExponent = exponent < 0;
0815:                    if (negativeExponent) {
0816:                        exponent = -exponent;
0817:                        append(result, negativePrefix, delegate,
0818:                                getNegativePrefixFieldPositions(),
0819:                                Field.EXPONENT_SIGN);
0820:                    } else {
0821:                        append(result, positivePrefix, delegate,
0822:                                getPositivePrefixFieldPositions(),
0823:                                Field.EXPONENT_SIGN);
0824:                    }
0825:                    digitList.set(exponent);
0826:
0827:                    int eFieldStart = result.length();
0828:
0829:                    for (int i = digitList.decimalAt; i < minExponentDigits; ++i)
0830:                        result.append(zero);
0831:                    for (int i = 0; i < digitList.decimalAt; ++i) {
0832:                        result
0833:                                .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta)
0834:                                        : zero);
0835:                    }
0836:                    delegate.formatted(Field.EXPONENT, Field.EXPONENT,
0837:                            eFieldStart, result.length(), result);
0838:                    fieldStart = result.length();
0839:                    if (negativeExponent) {
0840:                        append(result, negativeSuffix, delegate,
0841:                                getNegativeSuffixFieldPositions(),
0842:                                Field.EXPONENT_SIGN);
0843:                    } else {
0844:                        append(result, positiveSuffix, delegate,
0845:                                getPositiveSuffixFieldPositions(),
0846:                                Field.EXPONENT_SIGN);
0847:                    }
0848:                } else {
0849:                    int iFieldStart = result.length();
0850:
0851:                    // Output the integer portion.  Here 'count' is the total
0852:                    // number of integer digits we will display, including both
0853:                    // leading zeros required to satisfy getMinimumIntegerDigits,
0854:                    // and actual digits present in the number.
0855:                    int count = getMinimumIntegerDigits();
0856:                    int digitIndex = 0; // Index into digitList.fDigits[]
0857:                    if (digitList.decimalAt > 0 && count < digitList.decimalAt)
0858:                        count = digitList.decimalAt;
0859:
0860:                    // Handle the case where getMaximumIntegerDigits() is smaller
0861:                    // than the real number of integer digits.  If this is so, we
0862:                    // output the least significant max integer digits.  For example,
0863:                    // the value 1997 printed with 2 max integer digits is just "97".
0864:
0865:                    if (count > getMaximumIntegerDigits()) {
0866:                        count = getMaximumIntegerDigits();
0867:                        digitIndex = digitList.decimalAt - count;
0868:                    }
0869:
0870:                    int sizeBeforeIntegerPart = result.length();
0871:                    for (int i = count - 1; i >= 0; --i) {
0872:                        if (i < digitList.decimalAt
0873:                                && digitIndex < digitList.count) {
0874:                            // Output a real digit
0875:                            result
0876:                                    .append((char) (digitList.digits[digitIndex++] + zeroDelta));
0877:                        } else {
0878:                            // Output a leading zero
0879:                            result.append(zero);
0880:                        }
0881:
0882:                        // Output grouping separator if necessary.  Don't output a
0883:                        // grouping separator if i==0 though; that's at the end of
0884:                        // the integer part.
0885:                        if (isGroupingUsed() && i > 0 && (groupingSize != 0)
0886:                                && (i % groupingSize == 0)) {
0887:                            int gStart = result.length();
0888:                            result.append(grouping);
0889:                            delegate.formatted(Field.GROUPING_SEPARATOR,
0890:                                    Field.GROUPING_SEPARATOR, gStart, result
0891:                                            .length(), result);
0892:                        }
0893:                    }
0894:
0895:                    // Determine whether or not there are any printable fractional
0896:                    // digits.  If we've used up the digits we know there aren't.
0897:                    boolean fractionPresent = (getMinimumFractionDigits() > 0)
0898:                            || (!isInteger && digitIndex < digitList.count);
0899:
0900:                    // If there is no fraction present, and we haven't printed any
0901:                    // integer digits, then print a zero.  Otherwise we won't print
0902:                    // _any_ digits, and we won't be able to parse this string.
0903:                    if (!fractionPresent
0904:                            && result.length() == sizeBeforeIntegerPart) {
0905:                        result.append(zero);
0906:                    }
0907:
0908:                    delegate
0909:                            .formatted(INTEGER_FIELD, Field.INTEGER,
0910:                                    Field.INTEGER, iFieldStart,
0911:                                    result.length(), result);
0912:
0913:                    // Output the decimal separator if we always do so.
0914:                    int sStart = result.length();
0915:                    if (decimalSeparatorAlwaysShown || fractionPresent)
0916:                        result.append(decimal);
0917:
0918:                    if (sStart != result.length()) {
0919:                        delegate.formatted(Field.DECIMAL_SEPARATOR,
0920:                                Field.DECIMAL_SEPARATOR, sStart, result
0921:                                        .length(), result);
0922:                    }
0923:                    int fFieldStart = result.length();
0924:
0925:                    for (int i = 0; i < getMaximumFractionDigits(); ++i) {
0926:                        // Here is where we escape from the loop.  We escape if we've output
0927:                        // the maximum fraction digits (specified in the for expression above).
0928:                        // We also stop when we've output the minimum digits and either:
0929:                        // we have an integer, so there is no fractional stuff to display,
0930:                        // or we're out of significant digits.
0931:                        if (i >= getMinimumFractionDigits()
0932:                                && (isInteger || digitIndex >= digitList.count))
0933:                            break;
0934:
0935:                        // Output leading fractional zeros.  These are zeros that come after
0936:                        // the decimal but before any significant digits.  These are only
0937:                        // output if abs(number being formatted) < 1.0.
0938:                        if (-1 - i > (digitList.decimalAt - 1)) {
0939:                            result.append(zero);
0940:                            continue;
0941:                        }
0942:
0943:                        // Output a digit, if we have any precision left, or a
0944:                        // zero if we don't.  We don't want to output noise digits.
0945:                        if (!isInteger && digitIndex < digitList.count) {
0946:                            result
0947:                                    .append((char) (digitList.digits[digitIndex++] + zeroDelta));
0948:                        } else {
0949:                            result.append(zero);
0950:                        }
0951:                    }
0952:
0953:                    // Record field information for caller.
0954:                    delegate.formatted(FRACTION_FIELD, Field.FRACTION,
0955:                            Field.FRACTION, fFieldStart, result.length(),
0956:                            result);
0957:                }
0958:
0959:                if (isNegative) {
0960:                    append(result, negativeSuffix, delegate,
0961:                            getNegativeSuffixFieldPositions(), Field.SIGN);
0962:                } else {
0963:                    append(result, positiveSuffix, delegate,
0964:                            getPositiveSuffixFieldPositions(), Field.SIGN);
0965:                }
0966:
0967:                return result;
0968:            }
0969:
0970:            /**
0971:             * Appends the String <code>string</code> to <code>result</code>.
0972:             * <code>delegate</code> is notified of all  the
0973:             * <code>FieldPosition</code>s in <code>positions</code>.
0974:             * <p>
0975:             * If one of the <code>FieldPosition</code>s in <code>positions</code>
0976:             * identifies a <code>SIGN</code> attribute, it is mapped to
0977:             * <code>signAttribute</code>. This is used
0978:             * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
0979:             * attribute as necessary.
0980:             * <p>
0981:             * This is used by <code>subformat</code> to add the prefix/suffix.
0982:             */
0983:            private void append(StringBuffer result, String string,
0984:                    FieldDelegate delegate, FieldPosition[] positions,
0985:                    Format.Field signAttribute) {
0986:                int start = result.length();
0987:
0988:                if (string.length() > 0) {
0989:                    result.append(string);
0990:                    for (int counter = 0, max = positions.length; counter < max; counter++) {
0991:                        FieldPosition fp = positions[counter];
0992:                        Format.Field attribute = fp.getFieldAttribute();
0993:
0994:                        if (attribute == Field.SIGN) {
0995:                            attribute = signAttribute;
0996:                        }
0997:                        delegate.formatted(attribute, attribute, start
0998:                                + fp.getBeginIndex(), start + fp.getEndIndex(),
0999:                                result);
1000:                    }
1001:                }
1002:            }
1003:
1004:            /**
1005:             * Parses text from a string to produce a <code>Number</code>.
1006:             * <p>
1007:             * The method attempts to parse text starting at the index given by
1008:             * <code>pos</code>.
1009:             * If parsing succeeds, then the index of <code>pos</code> is updated
1010:             * to the index after the last character used (parsing does not necessarily
1011:             * use all characters up to the end of the string), and the parsed
1012:             * number is returned. The updated <code>pos</code> can be used to
1013:             * indicate the starting point for the next call to this method.
1014:             * If an error occurs, then the index of <code>pos</code> is not
1015:             * changed, the error index of <code>pos</code> is set to the index of
1016:             * the character where the error occurred, and null is returned.
1017:             * <p>
1018:             * The most economical subclass that can represent the number given by the
1019:             * string is chosen. Most integer values are returned as <code>Long</code>
1020:             * objects, no matter how they are written: <code>"17"</code> and
1021:             * <code>"17.000"</code> both parse to <code>Long(17)</code>. Values that
1022:             * cannot fit into a <code>Long</code> are returned as
1023:             * <code>Double</code>s. This includes values with a fractional part,
1024:             * infinite values, <code>NaN</code>, and the value -0.0.
1025:             * <code>DecimalFormat</code> does <em>not</em> decide whether to return
1026:             * a <code>Double</code> or a <code>Long</code> based on the presence of a
1027:             * decimal separator in the source string. Doing so would prevent integers
1028:             * that overflow the mantissa of a double, such as
1029:             * <code>"10,000,000,000,000,000.00"</code>, from being parsed accurately.
1030:             * Currently, the only classes that <code>parse</code> returns are
1031:             * <code>Long</code> and <code>Double</code>, but callers should not rely
1032:             * on this. Callers may use the <code>Number</code> methods
1033:             * <code>doubleValue</code>, <code>longValue</code>, etc., to obtain the
1034:             * type they want.
1035:             * <p>
1036:             * <code>DecimalFormat</code> parses all Unicode characters that represent
1037:             * decimal digits, as defined by <code>Character.digit()</code>. In
1038:             * addition, <code>DecimalFormat</code> also recognizes as digits the ten
1039:             * consecutive characters starting with the localized zero digit defined in
1040:             * the <code>DecimalFormatSymbols</code> object.
1041:             *
1042:             * @param text the string to be parsed
1043:             * @param pos A <code>ParsePosition</code> object with index and error
1044:             *            index information as described above.
1045:             * @return the parsed value, or <code>null</code> if the parse fails
1046:             * @exception NullPointerException if <code>text</code> or
1047:             *            <code>pos</code> is null.
1048:             */
1049:            public Number parse(String text, ParsePosition pos) {
1050:                // special case NaN
1051:                if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols
1052:                        .getNaN().length())) {
1053:                    pos.index = pos.index + symbols.getNaN().length();
1054:                    return new Double(Double.NaN);
1055:                }
1056:
1057:                boolean[] status = new boolean[STATUS_LENGTH];
1058:
1059:                if (!subparse(text, pos, digitList, false, status))
1060:                    return null;
1061:
1062:                double doubleResult = 0.0;
1063:                long longResult = 0;
1064:                boolean gotDouble = true;
1065:
1066:                // Finally, have DigitList parse the digits into a value.
1067:                if (status[STATUS_INFINITE]) {
1068:                    doubleResult = Double.POSITIVE_INFINITY;
1069:                } else if (digitList.fitsIntoLong(status[STATUS_POSITIVE],
1070:                        isParseIntegerOnly())) {
1071:                    gotDouble = false;
1072:                    longResult = digitList.getLong();
1073:                } else
1074:                    doubleResult = digitList.getDouble();
1075:
1076:                // Divide by multiplier. We have to be careful here not to do unneeded
1077:                // conversions between double and long.
1078:                if (multiplier != 1) {
1079:                    if (gotDouble)
1080:                        doubleResult /= multiplier;
1081:                    else {
1082:                        // Avoid converting to double if we can
1083:                        if (longResult % multiplier == 0) {
1084:                            longResult /= multiplier;
1085:                        } else {
1086:                            doubleResult = ((double) longResult) / multiplier;
1087:                            if (doubleResult < 0)
1088:                                doubleResult = -doubleResult;
1089:                            gotDouble = true;
1090:                        }
1091:                    }
1092:                }
1093:
1094:                if (!status[STATUS_POSITIVE]) {
1095:                    doubleResult = -doubleResult;
1096:                    // If longResult was Long.MIN_VALUE or a divisor of it (if
1097:                    // multiplier != 1) then don't negate it.
1098:                    if (longResult > 0) {
1099:                        longResult = -longResult;
1100:                    }
1101:                }
1102:
1103:                // At this point, if we divided the result by the multiplier, the result may
1104:                // fit into a long.  We check for this case and return a long if possible.
1105:                // We must do this AFTER applying the negative (if appropriate) in order to
1106:                // handle the case of LONG_MIN; otherwise, if we do this with a positive value
1107:                // -LONG_MIN, the double is > 0, but the long is < 0.  This is a C++-specific
1108:                // situation.  We also must retain a double in the case of -0.0, which will
1109:                // compare as == to a long 0 cast to a double (bug 4162852).
1110:                if (multiplier != 1 && gotDouble) {
1111:                    longResult = (long) doubleResult;
1112:                    gotDouble = (doubleResult != (double) longResult)
1113:                            || (doubleResult == 0.0 && !status[STATUS_POSITIVE] && !isParseIntegerOnly());
1114:                }
1115:
1116:                return gotDouble ? (Number) new Double(doubleResult)
1117:                        : (Number) new Long(longResult);
1118:            }
1119:
1120:            private static final int STATUS_INFINITE = 0;
1121:            private static final int STATUS_POSITIVE = 1;
1122:            private static final int STATUS_LENGTH = 2;
1123:
1124:            /**
1125:             * Parse the given text into a number.  The text is parsed beginning at
1126:             * parsePosition, until an unparseable character is seen.
1127:             * @param text The string to parse.
1128:             * @param parsePosition The position at which to being parsing.  Upon
1129:             * return, the first unparseable character.
1130:             * @param digits The DigitList to set to the parsed value.
1131:             * @param isExponent If true, parse an exponent.  This means no
1132:             * infinite values and integer only.
1133:             * @param status Upon return contains boolean status flags indicating
1134:             * whether the value was infinite and whether it was positive.
1135:             */
1136:            private final boolean subparse(String text,
1137:                    ParsePosition parsePosition, DigitList digits,
1138:                    boolean isExponent, boolean status[]) {
1139:                int position = parsePosition.index;
1140:                int oldStart = parsePosition.index;
1141:                int backup;
1142:
1143:                // check for positivePrefix; take longest
1144:                boolean gotPositive = text.regionMatches(position,
1145:                        positivePrefix, 0, positivePrefix.length());
1146:                boolean gotNegative = text.regionMatches(position,
1147:                        negativePrefix, 0, negativePrefix.length());
1148:                if (gotPositive && gotNegative) {
1149:                    if (positivePrefix.length() > negativePrefix.length())
1150:                        gotNegative = false;
1151:                    else if (positivePrefix.length() < negativePrefix.length())
1152:                        gotPositive = false;
1153:                }
1154:                if (gotPositive) {
1155:                    position += positivePrefix.length();
1156:                } else if (gotNegative) {
1157:                    position += negativePrefix.length();
1158:                } else {
1159:                    parsePosition.errorIndex = position;
1160:                    return false;
1161:                }
1162:                // process digits or Inf, find decimal position
1163:                status[STATUS_INFINITE] = false;
1164:                if (!isExponent
1165:                        && text.regionMatches(position, symbols.getInfinity(),
1166:                                0, symbols.getInfinity().length())) {
1167:                    position += symbols.getInfinity().length();
1168:                    status[STATUS_INFINITE] = true;
1169:                } else {
1170:                    // We now have a string of digits, possibly with grouping symbols,
1171:                    // and decimal points.  We want to process these into a DigitList.
1172:                    // We don't want to put a bunch of leading zeros into the DigitList
1173:                    // though, so we keep track of the location of the decimal point,
1174:                    // put only significant digits into the DigitList, and adjust the
1175:                    // exponent as needed.
1176:
1177:                    digits.decimalAt = digits.count = 0;
1178:                    char zero = symbols.getZeroDigit();
1179:                    char decimal = isCurrencyFormat ? symbols
1180:                            .getMonetaryDecimalSeparator() : symbols
1181:                            .getDecimalSeparator();
1182:                    char grouping = symbols.getGroupingSeparator();
1183:                    char exponentChar = symbols.getExponentialSymbol();
1184:                    boolean sawDecimal = false;
1185:                    boolean sawExponent = false;
1186:                    boolean sawDigit = false;
1187:                    int exponent = 0; // Set to the exponent value, if any
1188:
1189:                    // We have to track digitCount ourselves, because digits.count will
1190:                    // pin when the maximum allowable digits is reached.
1191:                    int digitCount = 0;
1192:
1193:                    backup = -1;
1194:                    for (; position < text.length(); ++position) {
1195:                        char ch = text.charAt(position);
1196:
1197:                        /* We recognize all digit ranges, not only the Latin digit range
1198:                         * '0'..'9'.  We do so by using the Character.digit() method,
1199:                         * which converts a valid Unicode digit to the range 0..9.
1200:                         *
1201:                         * The character 'ch' may be a digit.  If so, place its value
1202:                         * from 0 to 9 in 'digit'.  First try using the locale digit,
1203:                         * which may or MAY NOT be a standard Unicode digit range.  If
1204:                         * this fails, try using the standard Unicode digit ranges by
1205:                         * calling Character.digit().  If this also fails, digit will
1206:                         * have a value outside the range 0..9.
1207:                         */
1208:                        int digit = ch - zero;
1209:                        if (digit < 0 || digit > 9)
1210:                            digit = Character.digit(ch, 10);
1211:
1212:                        if (digit == 0) {
1213:                            // Cancel out backup setting (see grouping handler below)
1214:                            backup = -1; // Do this BEFORE continue statement below!!!
1215:                            sawDigit = true;
1216:
1217:                            // Handle leading zeros
1218:                            if (digits.count == 0) {
1219:                                // Ignore leading zeros in integer part of number.
1220:                                if (!sawDecimal)
1221:                                    continue;
1222:
1223:                                // If we have seen the decimal, but no significant digits yet,
1224:                                // then we account for leading zeros by decrementing the
1225:                                // digits.decimalAt into negative values.
1226:                                --digits.decimalAt;
1227:                            } else {
1228:                                ++digitCount;
1229:                                digits.append((char) (digit + '0'));
1230:                            }
1231:                        } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
1232:                        {
1233:                            sawDigit = true;
1234:                            ++digitCount;
1235:                            digits.append((char) (digit + '0'));
1236:
1237:                            // Cancel out backup setting (see grouping handler below)
1238:                            backup = -1;
1239:                        } else if (!isExponent && ch == decimal) {
1240:                            // If we're only parsing integers, or if we ALREADY saw the
1241:                            // decimal, then don't parse this one.
1242:                            if (isParseIntegerOnly() || sawDecimal)
1243:                                break;
1244:                            digits.decimalAt = digitCount; // Not digits.count!
1245:                            sawDecimal = true;
1246:                        } else if (!isExponent && ch == grouping
1247:                                && isGroupingUsed()) {
1248:                            if (sawDecimal) {
1249:                                break;
1250:                            }
1251:                            // Ignore grouping characters, if we are using them, but require
1252:                            // that they be followed by a digit.  Otherwise we backup and
1253:                            // reprocess them.
1254:                            backup = position;
1255:                        } else if (!isExponent && ch == exponentChar
1256:                                && !sawExponent) {
1257:                            // Process the exponent by recursively calling this method.
1258:                            ParsePosition pos = new ParsePosition(position + 1);
1259:                            boolean[] stat = new boolean[STATUS_LENGTH];
1260:                            DigitList exponentDigits = new DigitList();
1261:
1262:                            if (subparse(text, pos, exponentDigits, true, stat)
1263:                                    && exponentDigits.fitsIntoLong(
1264:                                            stat[STATUS_POSITIVE], true)) {
1265:                                position = pos.index; // Advance past the exponent
1266:                                exponent = (int) exponentDigits.getLong();
1267:                                if (!stat[STATUS_POSITIVE])
1268:                                    exponent = -exponent;
1269:                                sawExponent = true;
1270:                            }
1271:                            break; // Whether we fail or succeed, we exit this loop
1272:                        } else
1273:                            break;
1274:                    }
1275:
1276:                    if (backup != -1)
1277:                        position = backup;
1278:
1279:                    // If there was no decimal point we have an integer
1280:                    if (!sawDecimal)
1281:                        digits.decimalAt = digitCount; // Not digits.count!
1282:
1283:                    // Adjust for exponent, if any
1284:                    digits.decimalAt += exponent;
1285:
1286:                    // If none of the text string was recognized.  For example, parse
1287:                    // "x" with pattern "#0.00" (return index and error index both 0)
1288:                    // parse "$" with pattern "$#0.00". (return index 0 and error index
1289:                    // 1).
1290:                    if (!sawDigit && digitCount == 0) {
1291:                        parsePosition.index = oldStart;
1292:                        parsePosition.errorIndex = oldStart;
1293:                        return false;
1294:                    }
1295:                }
1296:
1297:                // check for positiveSuffix
1298:                if (gotPositive)
1299:                    gotPositive = text.regionMatches(position, positiveSuffix,
1300:                            0, positiveSuffix.length());
1301:                if (gotNegative)
1302:                    gotNegative = text.regionMatches(position, negativeSuffix,
1303:                            0, negativeSuffix.length());
1304:
1305:                // if both match, take longest
1306:                if (gotPositive && gotNegative) {
1307:                    if (positiveSuffix.length() > negativeSuffix.length())
1308:                        gotNegative = false;
1309:                    else if (positiveSuffix.length() < negativeSuffix.length())
1310:                        gotPositive = false;
1311:                }
1312:
1313:                // fail if neither or both
1314:                if (gotPositive == gotNegative) {
1315:                    parsePosition.errorIndex = position;
1316:                    return false;
1317:                }
1318:
1319:                parsePosition.index = position
1320:                        + (gotPositive ? positiveSuffix.length()
1321:                                : negativeSuffix.length()); // mark success!
1322:
1323:                status[STATUS_POSITIVE] = gotPositive;
1324:                if (parsePosition.index == oldStart) {
1325:                    parsePosition.errorIndex = position;
1326:                    return false;
1327:                }
1328:                return true;
1329:            }
1330:
1331:            /**
1332:             * Returns the decimal format symbols, which is generally not changed
1333:             * by the programmer or user.
1334:             * @return desired DecimalFormatSymbols
1335:             * @see java.text.DecimalFormatSymbols
1336:             */
1337:            public DecimalFormatSymbols getDecimalFormatSymbols() {
1338:                try {
1339:                    // don't allow multiple references
1340:                    return (DecimalFormatSymbols) symbols.clone();
1341:                } catch (Exception foo) {
1342:                    return null; // should never happen
1343:                }
1344:            }
1345:
1346:            /**
1347:             * Sets the decimal format symbols, which is generally not changed
1348:             * by the programmer or user.
1349:             * @param newSymbols desired DecimalFormatSymbols
1350:             * @see java.text.DecimalFormatSymbols
1351:             */
1352:            public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
1353:                try {
1354:                    // don't allow multiple references
1355:                    symbols = (DecimalFormatSymbols) newSymbols.clone();
1356:                    expandAffixes();
1357:                } catch (Exception foo) {
1358:                    // should never happen
1359:                }
1360:            }
1361:
1362:            /**
1363:             * Get the positive prefix.
1364:             * <P>Examples: +123, $123, sFr123
1365:             */
1366:            public String getPositivePrefix() {
1367:                return positivePrefix;
1368:            }
1369:
1370:            /**
1371:             * Set the positive prefix.
1372:             * <P>Examples: +123, $123, sFr123
1373:             */
1374:            public void setPositivePrefix(String newValue) {
1375:                positivePrefix = newValue;
1376:                posPrefixPattern = null;
1377:                positivePrefixFieldPositions = null;
1378:            }
1379:
1380:            /**
1381:             * Returns the FieldPositions of the fields in the prefix used for
1382:             * positive numbers. This is not used if the user has explicitly set
1383:             * a positive prefix via <code>setPositivePrefix</code>. This is
1384:             * lazily created.
1385:             *
1386:             * @return FieldPositions in positive prefix
1387:             */
1388:            private FieldPosition[] getPositivePrefixFieldPositions() {
1389:                if (positivePrefixFieldPositions == null) {
1390:                    if (posPrefixPattern != null) {
1391:                        positivePrefixFieldPositions = expandAffix(posPrefixPattern);
1392:                    } else {
1393:                        positivePrefixFieldPositions = EmptyFieldPositionArray;
1394:                    }
1395:                }
1396:                return positivePrefixFieldPositions;
1397:            }
1398:
1399:            /**
1400:             * Get the negative prefix.
1401:             * <P>Examples: -123, ($123) (with negative suffix), sFr-123
1402:             */
1403:            public String getNegativePrefix() {
1404:                return negativePrefix;
1405:            }
1406:
1407:            /**
1408:             * Set the negative prefix.
1409:             * <P>Examples: -123, ($123) (with negative suffix), sFr-123
1410:             */
1411:            public void setNegativePrefix(String newValue) {
1412:                negativePrefix = newValue;
1413:                negPrefixPattern = null;
1414:            }
1415:
1416:            /**
1417:             * Returns the FieldPositions of the fields in the prefix used for
1418:             * negative numbers. This is not used if the user has explicitly set
1419:             * a negative prefix via <code>setNegativePrefix</code>. This is
1420:             * lazily created.
1421:             *
1422:             * @return FieldPositions in positive prefix
1423:             */
1424:            private FieldPosition[] getNegativePrefixFieldPositions() {
1425:                if (negativePrefixFieldPositions == null) {
1426:                    if (negPrefixPattern != null) {
1427:                        negativePrefixFieldPositions = expandAffix(negPrefixPattern);
1428:                    } else {
1429:                        negativePrefixFieldPositions = EmptyFieldPositionArray;
1430:                    }
1431:                }
1432:                return negativePrefixFieldPositions;
1433:            }
1434:
1435:            /**
1436:             * Get the positive suffix.
1437:             * <P>Example: 123%
1438:             */
1439:            public String getPositiveSuffix() {
1440:                return positiveSuffix;
1441:            }
1442:
1443:            /**
1444:             * Set the positive suffix.
1445:             * <P>Example: 123%
1446:             */
1447:            public void setPositiveSuffix(String newValue) {
1448:                positiveSuffix = newValue;
1449:                posSuffixPattern = null;
1450:            }
1451:
1452:            /**
1453:             * Returns the FieldPositions of the fields in the suffix used for
1454:             * positive numbers. This is not used if the user has explicitly set
1455:             * a positive suffix via <code>setPositiveSuffix</code>. This is
1456:             * lazily created.
1457:             *
1458:             * @return FieldPositions in positive prefix
1459:             */
1460:            private FieldPosition[] getPositiveSuffixFieldPositions() {
1461:                if (positiveSuffixFieldPositions == null) {
1462:                    if (posSuffixPattern != null) {
1463:                        positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
1464:                    } else {
1465:                        positiveSuffixFieldPositions = EmptyFieldPositionArray;
1466:                    }
1467:                }
1468:                return positiveSuffixFieldPositions;
1469:            }
1470:
1471:            /**
1472:             * Get the negative suffix.
1473:             * <P>Examples: -123%, ($123) (with positive suffixes)
1474:             */
1475:            public String getNegativeSuffix() {
1476:                return negativeSuffix;
1477:            }
1478:
1479:            /**
1480:             * Set the positive suffix.
1481:             * <P>Examples: 123%
1482:             */
1483:            public void setNegativeSuffix(String newValue) {
1484:                negativeSuffix = newValue;
1485:                negSuffixPattern = null;
1486:            }
1487:
1488:            /**
1489:             * Returns the FieldPositions of the fields in the suffix used for
1490:             * negative numbers. This is not used if the user has explicitly set
1491:             * a negative suffix via <code>setNegativeSuffix</code>. This is
1492:             * lazily created.
1493:             *
1494:             * @return FieldPositions in positive prefix
1495:             */
1496:            private FieldPosition[] getNegativeSuffixFieldPositions() {
1497:                if (negativeSuffixFieldPositions == null) {
1498:                    if (negSuffixPattern != null) {
1499:                        negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
1500:                    } else {
1501:                        negativeSuffixFieldPositions = EmptyFieldPositionArray;
1502:                    }
1503:                }
1504:                return negativeSuffixFieldPositions;
1505:            }
1506:
1507:            /**
1508:             * Get the multiplier for use in percent, permill, etc.
1509:             * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
1510:             * (For Arabic, use arabic percent symbol).
1511:             * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
1512:             * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
1513:             */
1514:            public int getMultiplier() {
1515:                return multiplier;
1516:            }
1517:
1518:            /**
1519:             * Set the multiplier for use in percent, permill, etc.
1520:             * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
1521:             * (For Arabic, use arabic percent symbol).
1522:             * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
1523:             * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
1524:             */
1525:            public void setMultiplier(int newValue) {
1526:                multiplier = newValue;
1527:            }
1528:
1529:            /**
1530:             * Return the grouping size. Grouping size is the number of digits between
1531:             * grouping separators in the integer portion of a number.  For example,
1532:             * in the number "123,456.78", the grouping size is 3.
1533:             * @see #setGroupingSize
1534:             * @see java.text.NumberFormat#isGroupingUsed
1535:             * @see java.text.DecimalFormatSymbols#getGroupingSeparator
1536:             */
1537:            public int getGroupingSize() {
1538:                return groupingSize;
1539:            }
1540:
1541:            /**
1542:             * Set the grouping size. Grouping size is the number of digits between
1543:             * grouping separators in the integer portion of a number.  For example,
1544:             * in the number "123,456.78", the grouping size is 3.
1545:             * @see #getGroupingSize
1546:             * @see java.text.NumberFormat#setGroupingUsed
1547:             * @see java.text.DecimalFormatSymbols#setGroupingSeparator
1548:             */
1549:            public void setGroupingSize(int newValue) {
1550:                groupingSize = (byte) newValue;
1551:            }
1552:
1553:            /**
1554:             * Allows you to get the behavior of the decimal separator with integers.
1555:             * (The decimal separator will always appear with decimals.)
1556:             * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
1557:             */
1558:            public boolean isDecimalSeparatorAlwaysShown() {
1559:                return decimalSeparatorAlwaysShown;
1560:            }
1561:
1562:            /**
1563:             * Allows you to set the behavior of the decimal separator with integers.
1564:             * (The decimal separator will always appear with decimals.)
1565:             * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
1566:             */
1567:            public void setDecimalSeparatorAlwaysShown(boolean newValue) {
1568:                decimalSeparatorAlwaysShown = newValue;
1569:            }
1570:
1571:            /**
1572:             * Standard override; no change in semantics.
1573:             */
1574:            public Object clone() {
1575:                try {
1576:                    DecimalFormat other = (DecimalFormat) super .clone();
1577:                    other.symbols = (DecimalFormatSymbols) symbols.clone();
1578:                    other.digitList = (DigitList) digitList.clone();
1579:                    return other;
1580:                } catch (Exception e) {
1581:                    throw new InternalError();
1582:                }
1583:            }
1584:
1585:            /**
1586:             * Overrides equals
1587:             */
1588:            public boolean equals(Object obj) {
1589:                if (obj == null)
1590:                    return false;
1591:                if (!super .equals(obj))
1592:                    return false; // super does class check
1593:                DecimalFormat other = (DecimalFormat) obj;
1594:                return ((posPrefixPattern == other.posPrefixPattern && positivePrefix
1595:                        .equals(other.positivePrefix)) || (posPrefixPattern != null && posPrefixPattern
1596:                        .equals(other.posPrefixPattern)))
1597:                        && ((posSuffixPattern == other.posSuffixPattern && positiveSuffix
1598:                                .equals(other.positiveSuffix)) || (posSuffixPattern != null && posSuffixPattern
1599:                                .equals(other.posSuffixPattern)))
1600:                        && ((negPrefixPattern == other.negPrefixPattern && negativePrefix
1601:                                .equals(other.negativePrefix)) || (negPrefixPattern != null && negPrefixPattern
1602:                                .equals(other.negPrefixPattern)))
1603:                        && ((negSuffixPattern == other.negSuffixPattern && negativeSuffix
1604:                                .equals(other.negativeSuffix)) || (negSuffixPattern != null && negSuffixPattern
1605:                                .equals(other.negSuffixPattern)))
1606:                        && multiplier == other.multiplier
1607:                        && groupingSize == other.groupingSize
1608:                        && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
1609:                        && useExponentialNotation == other.useExponentialNotation
1610:                        && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
1611:                        && symbols.equals(other.symbols);
1612:            }
1613:
1614:            /**
1615:             * Overrides hashCode
1616:             */
1617:            public int hashCode() {
1618:                return super .hashCode() * 37 + positivePrefix.hashCode();
1619:                // just enough fields for a reasonable distribution
1620:            }
1621:
1622:            /**
1623:             * Synthesizes a pattern string that represents the current state
1624:             * of this Format object.
1625:             * @see #applyPattern
1626:             */
1627:            public String toPattern() {
1628:                return toPattern(false);
1629:            }
1630:
1631:            /**
1632:             * Synthesizes a localized pattern string that represents the current
1633:             * state of this Format object.
1634:             * @see #applyPattern
1635:             */
1636:            public String toLocalizedPattern() {
1637:                return toPattern(true);
1638:            }
1639:
1640:            /**
1641:             * Expand the affix pattern strings into the expanded affix strings.  If any
1642:             * affix pattern string is null, do not expand it.  This method should be
1643:             * called any time the symbols or the affix patterns change in order to keep
1644:             * the expanded affix strings up to date.
1645:             */
1646:            private void expandAffixes() {
1647:                // Reuse one StringBuffer for better performance
1648:                StringBuffer buffer = new StringBuffer();
1649:                if (posPrefixPattern != null) {
1650:                    positivePrefix = expandAffix(posPrefixPattern, buffer);
1651:                    positivePrefixFieldPositions = null;
1652:                }
1653:                if (posSuffixPattern != null) {
1654:                    positiveSuffix = expandAffix(posSuffixPattern, buffer);
1655:                    positiveSuffixFieldPositions = null;
1656:                }
1657:                if (negPrefixPattern != null) {
1658:                    negativePrefix = expandAffix(negPrefixPattern, buffer);
1659:                    negativePrefixFieldPositions = null;
1660:                }
1661:                if (negSuffixPattern != null) {
1662:                    negativeSuffix = expandAffix(negSuffixPattern, buffer);
1663:                    negativeSuffixFieldPositions = null;
1664:                }
1665:            }
1666:
1667:            /**
1668:             * Expand an affix pattern into an affix string.  All characters in the
1669:             * pattern are literal unless prefixed by QUOTE.  The following characters
1670:             * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
1671:             * PATTERN_MINUS, and CURRENCY_SIGN.  If CURRENCY_SIGN is doubled (QUOTE +
1672:             * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
1673:             * currency code.  Any other character after a QUOTE represents itself.
1674:             * QUOTE must be followed by another character; QUOTE may not occur by
1675:             * itself at the end of the pattern.
1676:             *
1677:             * @param pattern the non-null, possibly empty pattern
1678:             * @param buffer a scratch StringBuffer; its contents will be lost
1679:             * @return the expanded equivalent of pattern
1680:             */
1681:            private String expandAffix(String pattern, StringBuffer buffer) {
1682:                buffer.setLength(0);
1683:                for (int i = 0; i < pattern.length();) {
1684:                    char c = pattern.charAt(i++);
1685:                    if (c == QUOTE) {
1686:                        c = pattern.charAt(i++);
1687:                        switch (c) {
1688:                        case CURRENCY_SIGN:
1689:                            if (i < pattern.length()
1690:                                    && pattern.charAt(i) == CURRENCY_SIGN) {
1691:                                ++i;
1692:                                buffer.append(symbols
1693:                                        .getInternationalCurrencySymbol());
1694:                            } else {
1695:                                buffer.append(symbols.getCurrencySymbol());
1696:                            }
1697:                            continue;
1698:                        case PATTERN_PERCENT:
1699:                            c = symbols.getPercent();
1700:                            break;
1701:                        case PATTERN_PER_MILLE:
1702:                            c = symbols.getPerMill();
1703:                            break;
1704:                        case PATTERN_MINUS:
1705:                            c = symbols.getMinusSign();
1706:                            break;
1707:                        }
1708:                    }
1709:                    buffer.append(c);
1710:                }
1711:                return buffer.toString();
1712:            }
1713:
1714:            /**
1715:             * Expand an affix pattern into an array of FieldPositions describing
1716:             * how the pattern would be expanded.
1717:             * All characters in the
1718:             * pattern are literal unless prefixed by QUOTE.  The following characters
1719:             * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
1720:             * PATTERN_MINUS, and CURRENCY_SIGN.  If CURRENCY_SIGN is doubled (QUOTE +
1721:             * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
1722:             * currency code.  Any other character after a QUOTE represents itself.
1723:             * QUOTE must be followed by another character; QUOTE may not occur by
1724:             * itself at the end of the pattern.
1725:             *
1726:             * @param pattern the non-null, possibly empty pattern
1727:             * @return FieldPosition array of the resulting fields.
1728:             */
1729:            private FieldPosition[] expandAffix(String pattern) {
1730:                ArrayList positions = null;
1731:                int stringIndex = 0;
1732:                for (int i = 0; i < pattern.length();) {
1733:                    char c = pattern.charAt(i++);
1734:                    if (c == QUOTE) {
1735:                        int field = -1;
1736:                        Format.Field fieldID = null;
1737:                        c = pattern.charAt(i++);
1738:                        switch (c) {
1739:                        case CURRENCY_SIGN:
1740:                            String string;
1741:                            if (i < pattern.length()
1742:                                    && pattern.charAt(i) == CURRENCY_SIGN) {
1743:                                ++i;
1744:                                string = symbols
1745:                                        .getInternationalCurrencySymbol();
1746:                            } else {
1747:                                string = symbols.getCurrencySymbol();
1748:                            }
1749:                            if (string.length() > 0) {
1750:                                if (positions == null) {
1751:                                    positions = new ArrayList(2);
1752:                                }
1753:                                FieldPosition fp = new FieldPosition(
1754:                                        Field.CURRENCY);
1755:                                fp.setBeginIndex(stringIndex);
1756:                                fp.setEndIndex(stringIndex + string.length());
1757:                                positions.add(fp);
1758:                                stringIndex += string.length();
1759:                            }
1760:                            continue;
1761:                        case PATTERN_PERCENT:
1762:                            c = symbols.getPercent();
1763:                            field = -1;
1764:                            fieldID = Field.PERCENT;
1765:                            break;
1766:                        case PATTERN_PER_MILLE:
1767:                            c = symbols.getPerMill();
1768:                            field = -1;
1769:                            fieldID = Field.PERMILLE;
1770:                            break;
1771:                        case PATTERN_MINUS:
1772:                            c = symbols.getMinusSign();
1773:                            field = -1;
1774:                            fieldID = Field.SIGN;
1775:                            break;
1776:                        }
1777:                        if (fieldID != null) {
1778:                            if (positions == null) {
1779:                                positions = new ArrayList(2);
1780:                            }
1781:                            FieldPosition fp = new FieldPosition(fieldID, field);
1782:                            fp.setBeginIndex(stringIndex);
1783:                            fp.setEndIndex(stringIndex + 1);
1784:                            positions.add(fp);
1785:                        }
1786:                    }
1787:                    stringIndex++;
1788:                }
1789:                if (positions != null) {
1790:                    return (FieldPosition[]) positions
1791:                            .toArray(EmptyFieldPositionArray);
1792:                }
1793:                return EmptyFieldPositionArray;
1794:            }
1795:
1796:            /**
1797:             * Appends an affix pattern to the given StringBuffer, quoting special
1798:             * characters as needed.  Uses the internal affix pattern, if that exists,
1799:             * or the literal affix, if the internal affix pattern is null.  The
1800:             * appended string will generate the same affix pattern (or literal affix)
1801:             * when passed to toPattern().
1802:             * 
1803:             * @param buffer the affix string is appended to this
1804:             * @param affixPattern a pattern such as posPrefixPattern; may be null
1805:             * @param expAffix a corresponding expanded affix, such as positivePrefix.
1806:             * Ignored unless affixPattern is null.  If affixPattern is null, then
1807:             * expAffix is appended as a literal affix.
1808:             * @param localized true if the appended pattern should contain localized
1809:             * pattern characters; otherwise, non-localized pattern chars are appended
1810:             */
1811:            private void appendAffix(StringBuffer buffer, String affixPattern,
1812:                    String expAffix, boolean localized) {
1813:                if (affixPattern == null) {
1814:                    appendAffix(buffer, expAffix, localized);
1815:                } else {
1816:                    int i;
1817:                    for (int pos = 0; pos < affixPattern.length(); pos = i) {
1818:                        i = affixPattern.indexOf(QUOTE, pos);
1819:                        if (i < 0) {
1820:                            appendAffix(buffer, affixPattern.substring(pos),
1821:                                    localized);
1822:                            break;
1823:                        }
1824:                        if (i > pos) {
1825:                            appendAffix(buffer, affixPattern.substring(pos, i),
1826:                                    localized);
1827:                        }
1828:                        char c = affixPattern.charAt(++i);
1829:                        ++i;
1830:                        if (c == QUOTE) {
1831:                            buffer.append(c);
1832:                            // Fall through and append another QUOTE below
1833:                        } else if (c == CURRENCY_SIGN
1834:                                && i < affixPattern.length()
1835:                                && affixPattern.charAt(i) == CURRENCY_SIGN) {
1836:                            ++i;
1837:                            buffer.append(c);
1838:                            // Fall through and append another CURRENCY_SIGN below
1839:                        } else if (localized) {
1840:                            switch (c) {
1841:                            case PATTERN_PERCENT:
1842:                                c = symbols.getPercent();
1843:                                break;
1844:                            case PATTERN_PER_MILLE:
1845:                                c = symbols.getPerMill();
1846:                                break;
1847:                            case PATTERN_MINUS:
1848:                                c = symbols.getMinusSign();
1849:                                break;
1850:                            }
1851:                        }
1852:                        buffer.append(c);
1853:                    }
1854:                }
1855:            }
1856:
1857:            /**
1858:             * Append an affix to the given StringBuffer, using quotes if
1859:             * there are special characters.  Single quotes themselves must be
1860:             * escaped in either case.
1861:             */
1862:            private void appendAffix(StringBuffer buffer, String affix,
1863:                    boolean localized) {
1864:                boolean needQuote;
1865:                if (localized) {
1866:                    needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
1867:                            || affix.indexOf(symbols.getGroupingSeparator()) >= 0
1868:                            || affix.indexOf(symbols.getDecimalSeparator()) >= 0
1869:                            || affix.indexOf(symbols.getPercent()) >= 0
1870:                            || affix.indexOf(symbols.getPerMill()) >= 0
1871:                            || affix.indexOf(symbols.getDigit()) >= 0
1872:                            || affix.indexOf(symbols.getPatternSeparator()) >= 0
1873:                            || affix.indexOf(symbols.getMinusSign()) >= 0
1874:                            || affix.indexOf(CURRENCY_SIGN) >= 0;
1875:                } else {
1876:                    needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
1877:                            || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
1878:                            || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
1879:                            || affix.indexOf(PATTERN_PERCENT) >= 0
1880:                            || affix.indexOf(PATTERN_PER_MILLE) >= 0
1881:                            || affix.indexOf(PATTERN_DIGIT) >= 0
1882:                            || affix.indexOf(PATTERN_SEPARATOR) >= 0
1883:                            || affix.indexOf(PATTERN_MINUS) >= 0
1884:                            || affix.indexOf(CURRENCY_SIGN) >= 0;
1885:                }
1886:                if (needQuote)
1887:                    buffer.append('\'');
1888:                if (affix.indexOf('\'') < 0)
1889:                    buffer.append(affix);
1890:                else {
1891:                    for (int j = 0; j < affix.length(); ++j) {
1892:                        char c = affix.charAt(j);
1893:                        buffer.append(c);
1894:                        if (c == '\'')
1895:                            buffer.append(c);
1896:                    }
1897:                }
1898:                if (needQuote)
1899:                    buffer.append('\'');
1900:            }
1901:
1902:            /**
1903:             * Does the real work of generating a pattern.  */
1904:            private String toPattern(boolean localized) {
1905:                StringBuffer result = new StringBuffer();
1906:                for (int j = 1; j >= 0; --j) {
1907:                    if (j == 1)
1908:                        appendAffix(result, posPrefixPattern, positivePrefix,
1909:                                localized);
1910:                    else
1911:                        appendAffix(result, negPrefixPattern, negativePrefix,
1912:                                localized);
1913:                    int i;
1914:                    int digitCount = useExponentialNotation ? getMaximumIntegerDigits()
1915:                            : Math.max(groupingSize, getMinimumIntegerDigits()) + 1;
1916:                    for (i = digitCount; i > 0; --i) {
1917:                        if (i != digitCount && isGroupingUsed()
1918:                                && groupingSize != 0 && i % groupingSize == 0) {
1919:                            result.append(localized ? symbols
1920:                                    .getGroupingSeparator()
1921:                                    : PATTERN_GROUPING_SEPARATOR);
1922:                        }
1923:                        result
1924:                                .append(i <= getMinimumIntegerDigits() ? (localized ? symbols
1925:                                        .getZeroDigit()
1926:                                        : PATTERN_ZERO_DIGIT)
1927:                                        : (localized ? symbols.getDigit()
1928:                                                : PATTERN_DIGIT));
1929:                    }
1930:                    if (getMaximumFractionDigits() > 0
1931:                            || decimalSeparatorAlwaysShown)
1932:                        result.append(localized ? symbols.getDecimalSeparator()
1933:                                : PATTERN_DECIMAL_SEPARATOR);
1934:                    for (i = 0; i < getMaximumFractionDigits(); ++i) {
1935:                        if (i < getMinimumFractionDigits()) {
1936:                            result.append(localized ? symbols.getZeroDigit()
1937:                                    : PATTERN_ZERO_DIGIT);
1938:                        } else {
1939:                            result.append(localized ? symbols.getDigit()
1940:                                    : PATTERN_DIGIT);
1941:                        }
1942:                    }
1943:                    if (useExponentialNotation) {
1944:                        result.append(localized ? symbols
1945:                                .getExponentialSymbol() : PATTERN_EXPONENT);
1946:                        for (i = 0; i < minExponentDigits; ++i)
1947:                            result.append(localized ? symbols.getZeroDigit()
1948:                                    : PATTERN_ZERO_DIGIT);
1949:                    }
1950:                    if (j == 1) {
1951:                        appendAffix(result, posSuffixPattern, positiveSuffix,
1952:                                localized);
1953:                        if ((negSuffixPattern == posSuffixPattern && // n == p == null
1954:                                negativeSuffix.equals(positiveSuffix))
1955:                                || (negSuffixPattern != null && negSuffixPattern
1956:                                        .equals(posSuffixPattern))) {
1957:                            if ((negPrefixPattern != null
1958:                                    && posPrefixPattern != null && negPrefixPattern
1959:                                    .equals("'-" + posPrefixPattern))
1960:                                    || (negPrefixPattern == posPrefixPattern && // n == p == null
1961:                                    negativePrefix.equals(symbols
1962:                                            .getMinusSign()
1963:                                            + positivePrefix)))
1964:                                break;
1965:                        }
1966:                        result.append(localized ? symbols.getPatternSeparator()
1967:                                : PATTERN_SEPARATOR);
1968:                    } else
1969:                        appendAffix(result, negSuffixPattern, negativeSuffix,
1970:                                localized);
1971:                }
1972:                return result.toString();
1973:            }
1974:
1975:            /**
1976:             * Apply the given pattern to this Format object.  A pattern is a
1977:             * short-hand specification for the various formatting properties.
1978:             * These properties can also be changed individually through the
1979:             * various setter methods.
1980:             * <p>
1981:             * There is no limit to integer digits are set
1982:             * by this routine, since that is the typical end-user desire;
1983:             * use setMaximumInteger if you want to set a real value.
1984:             * For negative numbers, use a second pattern, separated by a semicolon
1985:             * <P>Example <code>"#,#00.0#"</code> -> 1,234.56
1986:             * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
1987:             * a maximum of 2 fraction digits.
1988:             * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
1989:             * parentheses.
1990:             * <p>In negative patterns, the minimum and maximum counts are ignored;
1991:             * these are presumed to be set in the positive pattern.
1992:             *
1993:             * @exception NullPointerException if <code>pattern</code> is null
1994:             * @exception IllegalArgumentException if the given pattern is invalid.
1995:             */
1996:            public void applyPattern(String pattern) {
1997:                applyPattern(pattern, false);
1998:            }
1999:
2000:            /**
2001:             * Apply the given pattern to this Format object.  The pattern
2002:             * is assumed to be in a localized notation. A pattern is a
2003:             * short-hand specification for the various formatting properties.
2004:             * These properties can also be changed individually through the
2005:             * various setter methods.
2006:             * <p>
2007:             * There is no limit to integer digits are set
2008:             * by this routine, since that is the typical end-user desire;
2009:             * use setMaximumInteger if you want to set a real value.
2010:             * For negative numbers, use a second pattern, separated by a semicolon
2011:             * <P>Example <code>"#,#00.0#"</code> -> 1,234.56
2012:             * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
2013:             * a maximum of 2 fraction digits.
2014:             * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
2015:             * parentheses.
2016:             * <p>In negative patterns, the minimum and maximum counts are ignored;
2017:             * these are presumed to be set in the positive pattern.
2018:             *
2019:             * @exception NullPointerException if <code>pattern</code> is null
2020:             * @exception IllegalArgumentException if the given pattern is invalid.
2021:             */
2022:            public void applyLocalizedPattern(String pattern) {
2023:                applyPattern(pattern, true);
2024:            }
2025:
2026:            /**
2027:             * Does the real work of applying a pattern.
2028:             */
2029:            private void applyPattern(String pattern, boolean localized) {
2030:                char zeroDigit = PATTERN_ZERO_DIGIT;
2031:                char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
2032:                char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
2033:                char percent = PATTERN_PERCENT;
2034:                char perMill = PATTERN_PER_MILLE;
2035:                char digit = PATTERN_DIGIT;
2036:                char separator = PATTERN_SEPARATOR;
2037:                char exponent = PATTERN_EXPONENT;
2038:                char minus = PATTERN_MINUS;
2039:                if (localized) {
2040:                    zeroDigit = symbols.getZeroDigit();
2041:                    groupingSeparator = symbols.getGroupingSeparator();
2042:                    decimalSeparator = symbols.getDecimalSeparator();
2043:                    percent = symbols.getPercent();
2044:                    perMill = symbols.getPerMill();
2045:                    digit = symbols.getDigit();
2046:                    separator = symbols.getPatternSeparator();
2047:                    exponent = symbols.getExponentialSymbol();
2048:                    minus = symbols.getMinusSign();
2049:                }
2050:                boolean gotNegative = false;
2051:
2052:                decimalSeparatorAlwaysShown = false;
2053:                isCurrencyFormat = false;
2054:                useExponentialNotation = false;
2055:
2056:                // Two variables are used to record the subrange of the pattern
2057:                // occupied by phase 1.  This is used during the processing of the
2058:                // second pattern (the one representing negative numbers) to ensure
2059:                // that no deviation exists in phase 1 between the two patterns.
2060:                int phaseOneStart = 0;
2061:                int phaseOneLength = 0;
2062:                /** Back-out comment : HShih
2063:                 * boolean phaseTwo = false;
2064:                 */
2065:
2066:                int start = 0;
2067:                for (int j = 1; j >= 0 && start < pattern.length(); --j) {
2068:                    boolean inQuote = false;
2069:                    StringBuffer prefix = new StringBuffer();
2070:                    StringBuffer suffix = new StringBuffer();
2071:                    int decimalPos = -1;
2072:                    int multiplier = 1;
2073:                    int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
2074:                    byte groupingCount = -1;
2075:
2076:                    // The phase ranges from 0 to 2.  Phase 0 is the prefix.  Phase 1 is
2077:                    // the section of the pattern with digits, decimal separator,
2078:                    // grouping characters.  Phase 2 is the suffix.  In phases 0 and 2,
2079:                    // percent, permille, and currency symbols are recognized and
2080:                    // translated.  The separation of the characters into phases is
2081:                    // strictly enforced; if phase 1 characters are to appear in the
2082:                    // suffix, for example, they must be quoted.
2083:                    int phase = 0;
2084:
2085:                    // The affix is either the prefix or the suffix.
2086:                    StringBuffer affix = prefix;
2087:
2088:                    for (int pos = start; pos < pattern.length(); ++pos) {
2089:                        char ch = pattern.charAt(pos);
2090:                        switch (phase) {
2091:                        case 0:
2092:                        case 2:
2093:                            // Process the prefix / suffix characters
2094:                            if (inQuote) {
2095:                                // A quote within quotes indicates either the closing
2096:                                // quote or two quotes, which is a quote literal.  That is,
2097:                                // we have the second quote in 'do' or 'don''t'.
2098:                                if (ch == QUOTE) {
2099:                                    if ((pos + 1) < pattern.length()
2100:                                            && pattern.charAt(pos + 1) == QUOTE) {
2101:                                        ++pos;
2102:                                        affix.append("''"); // 'don''t'
2103:                                    } else {
2104:                                        inQuote = false; // 'do'
2105:                                    }
2106:                                    continue;
2107:                                }
2108:                            } else {
2109:                                // Process unquoted characters seen in prefix or suffix
2110:                                // phase.
2111:                                if (ch == digit || ch == zeroDigit
2112:                                        || ch == groupingSeparator
2113:                                        || ch == decimalSeparator) {
2114:                                    // Any of these characters implicitly begins the next
2115:                                    // phase.  If we are in phase 2, there is no next phase,
2116:                                    // so these characters are illegal.
2117:                                    /**
2118:                                     * 1.2 Back-out comment : HShih
2119:                                     * Can't throw exception here.
2120:                                     * if (phase == 2)
2121:                                     *    throw new IllegalArgumentException("Unquoted special character '" +
2122:                                     *                   ch + "' in pattern \"" +
2123:                                     *                   pattern + '"');
2124:                                     */
2125:                                    phase = 1;
2126:                                    if (j == 1)
2127:                                        phaseOneStart = pos;
2128:                                    --pos; // Reprocess this character
2129:                                    continue;
2130:                                } else if (ch == CURRENCY_SIGN) {
2131:                                    // Use lookahead to determine if the currency sign is
2132:                                    // doubled or not.
2133:                                    boolean doubled = (pos + 1) < pattern
2134:                                            .length()
2135:                                            && pattern.charAt(pos + 1) == CURRENCY_SIGN;
2136:                                    if (doubled)
2137:                                        ++pos; // Skip over the doubled character
2138:                                    isCurrencyFormat = true;
2139:                                    affix.append(doubled ? "'\u00A4\u00A4"
2140:                                            : "'\u00A4");
2141:                                    continue;
2142:                                } else if (ch == QUOTE) {
2143:                                    // A quote outside quotes indicates either the opening
2144:                                    // quote or two quotes, which is a quote literal.  That is,
2145:                                    // we have the first quote in 'do' or o''clock.
2146:                                    if (ch == QUOTE) {
2147:                                        if ((pos + 1) < pattern.length()
2148:                                                && pattern.charAt(pos + 1) == QUOTE) {
2149:                                            ++pos;
2150:                                            affix.append("''"); // o''clock
2151:                                        } else {
2152:                                            inQuote = true; // 'do'
2153:                                        }
2154:                                        continue;
2155:                                    }
2156:                                } else if (ch == separator) {
2157:                                    // Don't allow separators before we see digit characters of phase
2158:                                    // 1, and don't allow separators in the second pattern (j == 0).
2159:                                    if (phase == 0 || j == 0)
2160:                                        throw new IllegalArgumentException(
2161:                                                "Unquoted special character '"
2162:                                                        + ch
2163:                                                        + "' in pattern \""
2164:                                                        + pattern + '"');
2165:                                    start = pos + 1;
2166:                                    pos = pattern.length();
2167:                                    continue;
2168:                                }
2169:
2170:                                // Next handle characters which are appended directly.
2171:                                else if (ch == percent) {
2172:                                    if (multiplier != 1)
2173:                                        throw new IllegalArgumentException(
2174:                                                "Too many percent/permille characters in pattern \""
2175:                                                        + pattern + '"');
2176:                                    multiplier = 100;
2177:                                    affix.append("'%");
2178:                                    continue;
2179:                                } else if (ch == perMill) {
2180:                                    if (multiplier != 1)
2181:                                        throw new IllegalArgumentException(
2182:                                                "Too many percent/permille characters in pattern \""
2183:                                                        + pattern + '"');
2184:                                    multiplier = 1000;
2185:                                    affix.append("'\u2030");
2186:                                    continue;
2187:                                } else if (ch == minus) {
2188:                                    affix.append("'-");
2189:                                    continue;
2190:                                }
2191:                            }
2192:                            // Note that if we are within quotes, or if this is an unquoted,
2193:                            // non-special character, then we usually fall through to here.
2194:                            affix.append(ch);
2195:                            break;
2196:                        case 1:
2197:                            // Phase one must be identical in the two sub-patterns.  We
2198:                            // enforce this by doing a direct comparison.  While
2199:                            // processing the first sub-pattern, we just record its
2200:                            // length.  While processing the second, we compare
2201:                            // characters.
2202:                            if (j == 1)
2203:                                ++phaseOneLength;
2204:                            else {
2205:                                /**
2206:                                 * 1.2 Back-out comment : HShih
2207:                                 * if (ch != pattern.charAt(phaseOneStart++))
2208:                                 *    throw new IllegalArgumentException("Subpattern mismatch in \"" +
2209:                                 *                       pattern + '"');
2210:                                 * phaseTwo = true;
2211:                                 */
2212:                                if (--phaseOneLength == 0) {
2213:                                    phase = 2;
2214:                                    affix = suffix;
2215:                                }
2216:                                continue;
2217:                            }
2218:
2219:                            // Process the digits, decimal, and grouping characters.  We
2220:                            // record five pieces of information.  We expect the digits
2221:                            // to occur in the pattern ####0000.####, and we record the
2222:                            // number of left digits, zero (central) digits, and right
2223:                            // digits.  The position of the last grouping character is
2224:                            // recorded (should be somewhere within the first two blocks
2225:                            // of characters), as is the position of the decimal point,
2226:                            // if any (should be in the zero digits).  If there is no
2227:                            // decimal point, then there should be no right digits.
2228:                            if (ch == digit) {
2229:                                if (zeroDigitCount > 0)
2230:                                    ++digitRightCount;
2231:                                else
2232:                                    ++digitLeftCount;
2233:                                if (groupingCount >= 0 && decimalPos < 0)
2234:                                    ++groupingCount;
2235:                            } else if (ch == zeroDigit) {
2236:                                if (digitRightCount > 0)
2237:                                    throw new IllegalArgumentException(
2238:                                            "Unexpected '0' in pattern \""
2239:                                                    + pattern + '"');
2240:                                ++zeroDigitCount;
2241:                                if (groupingCount >= 0 && decimalPos < 0)
2242:                                    ++groupingCount;
2243:                            } else if (ch == groupingSeparator) {
2244:                                groupingCount = 0;
2245:                            } else if (ch == decimalSeparator) {
2246:                                if (decimalPos >= 0)
2247:                                    throw new IllegalArgumentException(
2248:                                            "Multiple decimal separators in pattern \""
2249:                                                    + pattern + '"');
2250:                                decimalPos = digitLeftCount + zeroDigitCount
2251:                                        + digitRightCount;
2252:                            } else if (ch == exponent) {
2253:                                if (useExponentialNotation)
2254:                                    throw new IllegalArgumentException(
2255:                                            "Multiple exponential "
2256:                                                    + "symbols in pattern \""
2257:                                                    + pattern + '"');
2258:                                useExponentialNotation = true;
2259:                                minExponentDigits = 0;
2260:
2261:                                // Use lookahead to parse out the exponential part of the
2262:                                // pattern, then jump into phase 2.
2263:                                while (++pos < pattern.length()
2264:                                        && pattern.charAt(pos) == zeroDigit) {
2265:                                    ++minExponentDigits;
2266:                                    ++phaseOneLength;
2267:                                }
2268:
2269:                                if ((digitLeftCount + zeroDigitCount) < 1
2270:                                        || minExponentDigits < 1)
2271:                                    throw new IllegalArgumentException(
2272:                                            "Malformed exponential "
2273:                                                    + "pattern \"" + pattern
2274:                                                    + '"');
2275:
2276:                                // Transition to phase 2
2277:                                phase = 2;
2278:                                affix = suffix;
2279:                                --pos;
2280:                                continue;
2281:                            } else {
2282:                                phase = 2;
2283:                                affix = suffix;
2284:                                --pos;
2285:                                --phaseOneLength;
2286:                                continue;
2287:                            }
2288:                            break;
2289:                        }
2290:                    }
2291:                    /**
2292:                     * 1.2 Back-out comment : HShih
2293:                     * if (phaseTwo && phaseOneLength > 0)
2294:                     *      throw new IllegalArgumentException("Subpattern mismatch in \"" +
2295:                     *                                   pattern + '"');
2296:                     */
2297:                    // Handle patterns with no '0' pattern character.  These patterns
2298:                    // are legal, but must be interpreted.  "##.###" -> "#0.###".
2299:                    // ".###" -> ".0##".
2300:                    /* We allow patterns of the form "####" to produce a zeroDigitCount of
2301:                     * zero (got that?); although this seems like it might make it possible
2302:                     * for format() to produce empty strings, format() checks for this
2303:                     * condition and outputs a zero digit in this situation.  Having a
2304:                     * zeroDigitCount of zero yields a minimum integer digits of zero, which
2305:                     * allows proper round-trip patterns.  That is, we don't want "#" to
2306:                     * become "#0" when toPattern() is called (even though that's what it
2307:                     * really is, semantically).  */
2308:                    if (zeroDigitCount == 0 && digitLeftCount > 0
2309:                            && decimalPos >= 0) {
2310:                        // Handle "###.###" and "###." and ".###"
2311:                        int n = decimalPos;
2312:                        if (n == 0)
2313:                            ++n; // Handle ".###"
2314:                        digitRightCount = digitLeftCount - n;
2315:                        digitLeftCount = n - 1;
2316:                        zeroDigitCount = 1;
2317:                    }
2318:
2319:                    // Do syntax checking on the digits.
2320:                    if ((decimalPos < 0 && digitRightCount > 0)
2321:                            || (decimalPos >= 0 && (decimalPos < digitLeftCount || decimalPos > (digitLeftCount + zeroDigitCount)))
2322:                            || groupingCount == 0 || inQuote)
2323:                        throw new IllegalArgumentException(
2324:                                "Malformed pattern \"" + pattern + '"');
2325:
2326:                    if (j == 1) {
2327:                        posPrefixPattern = prefix.toString();
2328:                        posSuffixPattern = suffix.toString();
2329:                        negPrefixPattern = posPrefixPattern; // assume these for now
2330:                        negSuffixPattern = posSuffixPattern;
2331:                        int digitTotalCount = digitLeftCount + zeroDigitCount
2332:                                + digitRightCount;
2333:                        /* The effectiveDecimalPos is the position the decimal is at or
2334:                         * would be at if there is no decimal.  Note that if decimalPos<0,
2335:                         * then digitTotalCount == digitLeftCount + zeroDigitCount.  */
2336:                        int effectiveDecimalPos = decimalPos >= 0 ? decimalPos
2337:                                : digitTotalCount;
2338:                        setMinimumIntegerDigits(effectiveDecimalPos
2339:                                - digitLeftCount);
2340:                        setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount
2341:                                + getMinimumIntegerDigits()
2342:                                : DOUBLE_INTEGER_DIGITS);
2343:                        setMaximumFractionDigits(decimalPos >= 0 ? (digitTotalCount - decimalPos)
2344:                                : 0);
2345:                        setMinimumFractionDigits(decimalPos >= 0 ? (digitLeftCount
2346:                                + zeroDigitCount - decimalPos)
2347:                                : 0);
2348:                        setGroupingUsed(groupingCount > 0);
2349:                        this .groupingSize = (groupingCount > 0) ? groupingCount
2350:                                : 0;
2351:                        this .multiplier = multiplier;
2352:                        setDecimalSeparatorAlwaysShown(decimalPos == 0
2353:                                || decimalPos == digitTotalCount);
2354:                    } else {
2355:                        negPrefixPattern = prefix.toString();
2356:                        negSuffixPattern = suffix.toString();
2357:                        gotNegative = true;
2358:                    }
2359:                }
2360:
2361:                if (pattern.length() == 0) {
2362:                    posPrefixPattern = posSuffixPattern = "";
2363:                    setMinimumIntegerDigits(0);
2364:                    setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
2365:                    setMinimumFractionDigits(0);
2366:                    setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
2367:                }
2368:
2369:                // If there was no negative pattern, or if the negative pattern is identical
2370:                // to the positive pattern, then prepend the minus sign to the positive
2371:                // pattern to form the negative pattern.
2372:                if (!gotNegative
2373:                        || (negPrefixPattern.equals(posPrefixPattern) && negSuffixPattern
2374:                                .equals(posSuffixPattern))) {
2375:                    negSuffixPattern = posSuffixPattern;
2376:                    negPrefixPattern = "'-" + posPrefixPattern;
2377:                }
2378:
2379:                expandAffixes();
2380:            }
2381:
2382:            /**
2383:             * Sets the maximum number of digits allowed in the integer portion of a
2384:             * number. This override limits the integer digit count to 309.
2385:             * @see NumberFormat#setMaximumIntegerDigits
2386:             */
2387:            public void setMaximumIntegerDigits(int newValue) {
2388:                super .setMaximumIntegerDigits(Math.min(newValue,
2389:                        DOUBLE_INTEGER_DIGITS));
2390:            }
2391:
2392:            /**
2393:             * Sets the minimum number of digits allowed in the integer portion of a
2394:             * number. This override limits the integer digit count to 309.
2395:             * @see NumberFormat#setMinimumIntegerDigits
2396:             */
2397:            public void setMinimumIntegerDigits(int newValue) {
2398:                super .setMinimumIntegerDigits(Math.min(newValue,
2399:                        DOUBLE_INTEGER_DIGITS));
2400:            }
2401:
2402:            /**
2403:             * Sets the maximum number of digits allowed in the fraction portion of a
2404:             * number. This override limits the fraction digit count to 340.
2405:             * @see NumberFormat#setMaximumFractionDigits
2406:             */
2407:            public void setMaximumFractionDigits(int newValue) {
2408:                super .setMaximumFractionDigits(Math.min(newValue,
2409:                        DOUBLE_FRACTION_DIGITS));
2410:            }
2411:
2412:            /**
2413:             * Sets the minimum number of digits allowed in the fraction portion of a
2414:             * number. This override limits the fraction digit count to 340.
2415:             * @see NumberFormat#setMinimumFractionDigits
2416:             */
2417:            public void setMinimumFractionDigits(int newValue) {
2418:                super .setMinimumFractionDigits(Math.min(newValue,
2419:                        DOUBLE_FRACTION_DIGITS));
2420:            }
2421:
2422:            /**
2423:             * Gets the currency used by this decimal format when formatting
2424:             * currency values.
2425:             * The currency is obtained by calling
2426:             * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
2427:             * on this number format's symbols.
2428:             *
2429:             * @return the currency used by this decimal format, or <code>null</code>
2430:             * @since 1.4
2431:             */
2432:            public Currency getCurrency() {
2433:                return symbols.getCurrency();
2434:            }
2435:
2436:            /**
2437:             * Sets the currency used by this number format when formatting
2438:             * currency values. This does not update the minimum or maximum
2439:             * number of fraction digits used by the number format.
2440:             * The currency is set by calling
2441:             * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
2442:             * on this number format's symbols.
2443:             *
2444:             * @param currency the new currency to be used by this decimal format
2445:             * @exception NullPointerException if <code>currency</code> is null
2446:             * @since 1.4
2447:             */
2448:            public void setCurrency(Currency currency) {
2449:                if (currency != symbols.getCurrency()) {
2450:                    symbols.setCurrency(currency);
2451:                    if (isCurrencyFormat) {
2452:                        expandAffixes();
2453:                    }
2454:                }
2455:            }
2456:
2457:            /**
2458:             * Adjusts the minimum and maximum fraction digits to values that
2459:             * are reasonable for the currency's default fraction digits.
2460:             */
2461:            void adjustForCurrencyDefaultFractionDigits() {
2462:                Currency currency = symbols.getCurrency();
2463:                if (currency == null) {
2464:                    try {
2465:                        currency = Currency.getInstance(symbols
2466:                                .getInternationalCurrencySymbol());
2467:                    } catch (IllegalArgumentException e) {
2468:                    }
2469:                }
2470:                if (currency != null) {
2471:                    int digits = currency.getDefaultFractionDigits();
2472:                    if (digits != -1) {
2473:                        int oldMinDigits = getMinimumFractionDigits();
2474:                        // Common patterns are "#.##", "#.00", "#".
2475:                        // Try to adjust all of them in a reasonable way.
2476:                        if (oldMinDigits == getMaximumFractionDigits()) {
2477:                            setMinimumFractionDigits(digits);
2478:                            setMaximumFractionDigits(digits);
2479:                        } else {
2480:                            setMinimumFractionDigits(Math.min(digits,
2481:                                    oldMinDigits));
2482:                            setMaximumFractionDigits(digits);
2483:                        }
2484:                    }
2485:                }
2486:            }
2487:
2488:            /**
2489:             * First, read the default serializable fields from the stream.  Then
2490:             * if <code>serialVersionOnStream</code> is less than 1, indicating that
2491:             * the stream was written by JDK 1.1, initialize <code>useExponentialNotation</code>
2492:             * to false, since it was not present in JDK 1.1.
2493:             * Finally, set serialVersionOnStream back to the maximum allowed value so that
2494:             * default serialization will work properly if this object is streamed out again.
2495:             *
2496:             * <p>If the minimum or maximum integer digit count is larger than
2497:             * <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or maximum fraction
2498:             * digit count is larger than <code>DOUBLE_FRACTION_DIGITS</code>, then the
2499:             * stream data is invalid and this method throws an
2500:             * <code>InvalidObjectException</code>.
2501:             *
2502:             * <p>Stream versions older than 2 will not have the affix pattern variables
2503:             * <code>posPrefixPattern</code> etc.  As a result, they will be initialized
2504:             * to <code>null</code>, which means the affix strings will be taken as
2505:             * literal values.  This is exactly what we want, since that corresponds to
2506:             * the pre-version-2 behavior.
2507:             */
2508:            private void readObject(ObjectInputStream stream)
2509:                    throws IOException, ClassNotFoundException {
2510:                stream.defaultReadObject();
2511:                // We only need to check the maximum counts because NumberFormat
2512:                // .readObject has already ensured that the maximum is greater than the
2513:                // minimum count.
2514:                if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS
2515:                        || getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
2516:                    throw new InvalidObjectException("Digit count out of range");
2517:                }
2518:                if (serialVersionOnStream < 1) {
2519:                    // Didn't have exponential fields
2520:                    useExponentialNotation = false;
2521:                }
2522:                serialVersionOnStream = currentSerialVersion;
2523:                digitList = new DigitList();
2524:            }
2525:
2526:            //----------------------------------------------------------------------
2527:            // INSTANCE VARIABLES
2528:            //----------------------------------------------------------------------
2529:
2530:            private transient DigitList digitList = new DigitList();
2531:
2532:            /**
2533:             * The symbol used as a prefix when formatting positive numbers, e.g. "+".
2534:             *
2535:             * @serial
2536:             * @see #getPositivePrefix
2537:             */
2538:            private String positivePrefix = "";
2539:
2540:            /**
2541:             * The symbol used as a suffix when formatting positive numbers.
2542:             * This is often an empty string.
2543:             *
2544:             * @serial
2545:             * @see #getPositiveSuffix
2546:             */
2547:            private String positiveSuffix = "";
2548:
2549:            /**
2550:             * The symbol used as a prefix when formatting negative numbers, e.g. "-".
2551:             *
2552:             * @serial
2553:             * @see #getNegativePrefix
2554:             */
2555:            private String negativePrefix = "-";
2556:
2557:            /**
2558:             * The symbol used as a suffix when formatting negative numbers.
2559:             * This is often an empty string.
2560:             *
2561:             * @serial
2562:             * @see #getNegativeSuffix
2563:             */
2564:            private String negativeSuffix = "";
2565:
2566:            /**
2567:             * The prefix pattern for non-negative numbers.  This variable corresponds
2568:             * to <code>positivePrefix</code>.
2569:             *
2570:             * <p>This pattern is expanded by the method <code>expandAffix()</code> to
2571:             * <code>positivePrefix</code> to update the latter to reflect changes in
2572:             * <code>symbols</code>.  If this variable is <code>null</code> then
2573:             * <code>positivePrefix</code> is taken as a literal value that does not
2574:             * change when <code>symbols</code> changes.  This variable is always
2575:             * <code>null</code> for <code>DecimalFormat</code> objects older than
2576:             * stream version 2 restored from stream.
2577:             *
2578:             * @serial
2579:             * @since 1.3
2580:             */
2581:            private String posPrefixPattern;
2582:
2583:            /**
2584:             * The suffix pattern for non-negative numbers.  This variable corresponds
2585:             * to <code>positiveSuffix</code>.  This variable is analogous to
2586:             * <code>posPrefixPattern</code>; see that variable for further
2587:             * documentation.
2588:             *
2589:             * @serial
2590:             * @since 1.3
2591:             */
2592:            private String posSuffixPattern;
2593:
2594:            /**
2595:             * The prefix pattern for negative numbers.  This variable corresponds
2596:             * to <code>negativePrefix</code>.  This variable is analogous to
2597:             * <code>posPrefixPattern</code>; see that variable for further
2598:             * documentation.
2599:             *
2600:             * @serial
2601:             * @since 1.3
2602:             */
2603:            private String negPrefixPattern;
2604:
2605:            /**
2606:             * The suffix pattern for negative numbers.  This variable corresponds
2607:             * to <code>negativeSuffix</code>.  This variable is analogous to
2608:             * <code>posPrefixPattern</code>; see that variable for further
2609:             * documentation.
2610:             *
2611:             * @serial
2612:             * @since 1.3
2613:             */
2614:            private String negSuffixPattern;
2615:
2616:            /**
2617:             * The multiplier for use in percent, permill, etc.
2618:             *
2619:             * @serial
2620:             * @see #getMultiplier
2621:             */
2622:            private int multiplier = 1;
2623:
2624:            /**
2625:             * The number of digits between grouping separators in the integer
2626:             * portion of a number.  Must be greater than 0 if
2627:             * <code>NumberFormat.groupingUsed</code> is true.
2628:             *
2629:             * @serial
2630:             * @see #getGroupingSize
2631:             * @see java.text.NumberFormat#isGroupingUsed
2632:             */
2633:            private byte groupingSize = 3; // invariant, > 0 if useThousands
2634:
2635:            /**
2636:             * If true, forces the decimal separator to always appear in a formatted
2637:             * number, even if the fractional part of the number is zero.
2638:             *
2639:             * @serial
2640:             * @see #isDecimalSeparatorAlwaysShown
2641:             */
2642:            private boolean decimalSeparatorAlwaysShown = false;
2643:
2644:            /**
2645:             * True if this object represents a currency format.  This determines
2646:             * whether the monetary decimal separator is used instead of the normal one.
2647:             */
2648:            private transient boolean isCurrencyFormat = false;
2649:
2650:            /**
2651:             * The <code>DecimalFormatSymbols</code> object used by this format.
2652:             * It contains the symbols used to format numbers, e.g. the grouping separator,
2653:             * decimal separator, and so on.
2654:             *
2655:             * @serial
2656:             * @see #setDecimalFormatSymbols
2657:             * @see java.text.DecimalFormatSymbols
2658:             */
2659:            private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
2660:
2661:            /**
2662:             * True to force the use of exponential (i.e. scientific) notation when formatting
2663:             * numbers.
2664:             *
2665:             * @serial
2666:             * @since 1.2
2667:             */
2668:            private boolean useExponentialNotation; // Newly persistent in the Java 2 platform
2669:
2670:            /**
2671:             * FieldPositions describing the positive prefix String. This is
2672:             * lazily created. Use <code>getPositivePrefixFieldPositions</code>
2673:             * when needed.
2674:             */
2675:            private transient FieldPosition[] positivePrefixFieldPositions;
2676:
2677:            /**
2678:             * FieldPositions describing the positive suffix String. This is
2679:             * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
2680:             * when needed.
2681:             */
2682:            private transient FieldPosition[] positiveSuffixFieldPositions;
2683:
2684:            /**
2685:             * FieldPositions describing the negative prefix String. This is
2686:             * lazily created. Use <code>getNegativePrefixFieldPositions</code>
2687:             * when needed.
2688:             */
2689:            private transient FieldPosition[] negativePrefixFieldPositions;
2690:
2691:            /**
2692:             * FieldPositions describing the negative suffix String. This is
2693:             * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
2694:             * when needed.
2695:             */
2696:            private transient FieldPosition[] negativeSuffixFieldPositions;
2697:
2698:            /**
2699:             * The minimum number of digits used to display the exponent when a number is
2700:             * formatted in exponential notation.  This field is ignored if
2701:             * <code>useExponentialNotation</code> is not true.
2702:             *
2703:             * @serial
2704:             * @since 1.2
2705:             */
2706:            private byte minExponentDigits; // Newly persistent in the Java 2 platform
2707:
2708:            //----------------------------------------------------------------------
2709:
2710:            static final int currentSerialVersion = 2;
2711:
2712:            /**
2713:             * The internal serial version which says which version was written.
2714:             * Possible values are:
2715:             * <ul>
2716:             * <li><b>0</b> (default): versions before the Java 2 platform v1.2
2717:             * <li><b>1</b>: version for 1.2, which includes the two new fields
2718:             *      <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
2719:             * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
2720:             *      <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
2721:             *      <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
2722:             * </ul>
2723:             * @since 1.2
2724:             * @serial
2725:             */
2726:            private int serialVersionOnStream = currentSerialVersion;
2727:
2728:            //----------------------------------------------------------------------
2729:            // CONSTANTS
2730:            //----------------------------------------------------------------------
2731:
2732:            // Constants for characters used in programmatic (unlocalized) patterns.
2733:            private static final char PATTERN_ZERO_DIGIT = '0';
2734:            private static final char PATTERN_GROUPING_SEPARATOR = ',';
2735:            private static final char PATTERN_DECIMAL_SEPARATOR = '.';
2736:            private static final char PATTERN_PER_MILLE = '\u2030';
2737:            private static final char PATTERN_PERCENT = '%';
2738:            private static final char PATTERN_DIGIT = '#';
2739:            private static final char PATTERN_SEPARATOR = ';';
2740:            private static final char PATTERN_EXPONENT = 'E';
2741:            private static final char PATTERN_MINUS = '-';
2742:
2743:            /**
2744:             * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
2745:             * is used in patterns and substitued with either the currency symbol,
2746:             * or if it is doubled, with the international currency symbol.  If the
2747:             * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
2748:             * replaced with the monetary decimal separator.
2749:             *
2750:             * The CURRENCY_SIGN is not localized.
2751:             */
2752:            private static final char CURRENCY_SIGN = '\u00A4';
2753:
2754:            private static final char QUOTE = '\'';
2755:
2756:            private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0];
2757:
2758:            // Upper limit on integer and fraction digits for a Java double
2759:            static final int DOUBLE_INTEGER_DIGITS = 309;
2760:            static final int DOUBLE_FRACTION_DIGITS = 340;
2761:
2762:            // Proclaim JDK 1.1 serial compatibility.
2763:            static final long serialVersionUID = 864413376551465018L;
2764:
2765:            /**
2766:             * Cache to hold the NumberPattern of a Locale.
2767:             */
2768:            private static Hashtable cachedLocaleData = new Hashtable(3);
2769:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.