Source for java.text.NumberFormat

   1: /* NumberFormat.java -- Formats and parses numbers
   2:    Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: 
  40: package java.text;
  41: 
  42: import gnu.java.locale.LocaleHelper;
  43: 
  44: import java.io.IOException;
  45: import java.io.InvalidObjectException;
  46: import java.io.ObjectInputStream;
  47: import java.io.ObjectOutputStream;
  48: 
  49: import java.text.spi.NumberFormatProvider;
  50: 
  51: import java.util.Currency;
  52: import java.util.Locale;
  53: import java.util.MissingResourceException;
  54: import java.util.ResourceBundle;
  55: import java.util.ServiceLoader;
  56: 
  57: /**
  58:  * This is the abstract superclass of all classes which format and
  59:  * parse numeric values such as decimal numbers, integers, currency values,
  60:  * and percentages.  These classes perform their parsing and formatting
  61:  * in a locale specific manner, accounting for such items as differing
  62:  * currency symbols and thousands separators.
  63:  * <p>
  64:  * To create an instance of a concrete subclass of <code>NumberFormat</code>,
  65:  * do not call a class constructor directly.  Instead, use one of the
  66:  * static factory methods in this class such as
  67:  * <code>getCurrencyInstance</code>.
  68:  *
  69:  * @author Tom Tromey (tromey@cygnus.com)
  70:  * @author Aaron M. Renn (arenn@urbanophile.com)
  71:  * @date March 4, 1999
  72:  */
  73: /* Written using "Java Class Libraries", 2nd edition, plus online
  74:  * API docs for JDK 1.2 from http://www.javasoft.com.
  75:  * Status:  Believed complete and correct to 1.2, except getAvailableLocales.
  76:  */
  77: public abstract class NumberFormat extends Format implements Cloneable
  78: {
  79:   /**
  80:    * This is a constant used to create a <code>FieldPosition</code> object
  81:    * that will return the integer portion of a formatted number.
  82:    */
  83:   public static final int INTEGER_FIELD = 0;
  84: 
  85:   /**
  86:    * This is a constant used to create a <code>FieldPosition</code> object
  87:    * that will return the fractional portion of a formatted number.
  88:    */
  89:   public static final int FRACTION_FIELD = 1;
  90: 
  91:   public static class Field extends Format.Field
  92:   {
  93:     static final long serialVersionUID = 7494728892700160890L;
  94: 
  95:     /**
  96:      * Attribute set to all characters containing digits of the integer
  97:      * part.
  98:      */
  99:     public static final NumberFormat.Field INTEGER
 100:       = new Field("integer");
 101: 
 102:     /**
 103:      * Attribute set to all characters containing digits of the fractional
 104:      * part.
 105:      */
 106:     public static final NumberFormat.Field FRACTION
 107:       = new Field("fraction");
 108: 
 109:     /**
 110:      * Attribute set to all characters containing digits of the exponential
 111:      * part.
 112:      */
 113:     public static final NumberFormat.Field EXPONENT
 114:       = new Field("exponent");
 115: 
 116:     /**
 117:      * Attribute set to all characters containing a decimal separator.
 118:      */
 119:     public static final NumberFormat.Field DECIMAL_SEPARATOR
 120:       = new Field("decimal separator");
 121: 
 122:     /**
 123:      * Attribute set to all characters containing a sign (plus or minus).
 124:      */
 125:     public static final NumberFormat.Field SIGN
 126:       = new Field("sign");
 127: 
 128:     /**
 129:      * Attribute set to all characters containing a grouping separator (e.g.
 130:      * a comma, a white space,...).
 131:      */
 132:     public static final NumberFormat.Field GROUPING_SEPARATOR
 133:       = new Field("grouping separator");
 134: 
 135:     /**
 136:      * Attribute set to all characters containing an exponential symbol (e.g.
 137:      * 'E')
 138:      */
 139:     public static final NumberFormat.Field EXPONENT_SYMBOL
 140:       = new Field("exponent symbol");
 141: 
 142:     /**
 143:      * Attribute set to all characters containing a percent symbol (e.g. '%')
 144:      */
 145:     public static final NumberFormat.Field PERCENT
 146:       = new Field("percent");
 147: 
 148:     /**
 149:      * Attribute set to all characters containing a permille symbol.
 150:      */
 151:     public static final NumberFormat.Field PERMILLE
 152:       = new Field("permille");
 153: 
 154:     /**
 155:      * Attribute set to all characters containing the currency unit.
 156:      */
 157:     public static final NumberFormat.Field CURRENCY
 158:       = new Field("currency");
 159: 
 160:     /**
 161:      * Attribute set to all characters containing the exponent sign.
 162:      */
 163:     public static final NumberFormat.Field EXPONENT_SIGN
 164:       = new Field("exponent sign");
 165: 
 166:     /**
 167:      * Private fields to register all fields contained in this descriptor.
 168:      */
 169:     private static final NumberFormat.Field[] allFields =
 170:     {
 171:       INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
 172:       GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
 173:       PERMILLE, CURRENCY, EXPONENT_SIGN
 174:     };
 175: 
 176:     /**
 177:      * This constructor is only used by the deserializer. Without it,
 178:      * it would fail to construct a valid object.
 179:      */
 180:     @SuppressWarnings("unused")
 181:     private Field()
 182:     {
 183:       super("");
 184:     }
 185: 
 186:     /**
 187:      * Create a Field instance with the specified field name.
 188:      *
 189:      * @param field_name Field name for the new Field instance.
 190:      */
 191:     protected Field(String field_name)
 192:     {
 193:       super (field_name);
 194:     }
 195: 
 196:     /**
 197:      * This function is used by the deserializer to know which object
 198:      * to use when it encounters an encoded NumberFormat.Field in a
 199:      * serialization stream. If the stream is valid it should return
 200:      * one of the above field. In the other case we throw an exception.
 201:      *
 202:      * @return a valid official NumberFormat.Field instance.
 203:      *
 204:      * @throws InvalidObjectException if the field name is invalid.
 205:      */
 206:     protected Object readResolve() throws InvalidObjectException
 207:     {
 208:       String s = getName();
 209:       for (int i = 0; i < allFields.length; i++)
 210:         if (s.equals(allFields[i].getName()))
 211:           return allFields[i];
 212: 
 213:       throw new InvalidObjectException("no such NumberFormat field called "
 214:                                        + s);
 215:     }
 216:   }
 217: 
 218:   /**
 219:    * This method is a specialization of the format method that performs
 220:    * a simple formatting of the specified <code>long</code> number.
 221:    *
 222:    * @param number The <code>long</code> to format.
 223:    *
 224:    * @return The formatted number
 225:    */
 226:   public final String format (long number)
 227:   {
 228:     StringBuffer sbuf = new StringBuffer(50);
 229:     format (number, sbuf, new FieldPosition(0));
 230:     return sbuf.toString();
 231:   }
 232: 
 233:   /**
 234:    * @specnote this method was final in releases before 1.5
 235:    */
 236:   public StringBuffer format (Object obj, StringBuffer sbuf,
 237:                               FieldPosition pos)
 238:   {
 239:     if (obj instanceof Number)
 240:       return format(((Number) obj).doubleValue(), sbuf, pos);
 241: 
 242:     throw new
 243:       IllegalArgumentException("Cannot format given Object as a Number");
 244:   }
 245: 
 246:   /**
 247:    * This method formats the specified <code>double</code> and appends it to
 248:    * a <code>StringBuffer</code>.
 249:    *
 250:    * @param number The <code>double</code> to format.
 251:    * @param sbuf The <code>StringBuffer</code> to append the formatted number
 252:    *             to.
 253:    * @param pos The desired <code>FieldPosition</code>.
 254:    *
 255:    * @return The <code>StringBuffer</code> with the appended number.
 256:    */
 257:   public abstract StringBuffer format (double number,
 258:                                        StringBuffer sbuf, FieldPosition pos);
 259: 
 260:   /**
 261:    * This method formats the specified <code>long</code> and appends it to
 262:    * a <code>StringBuffer</code>.
 263:    *
 264:    * @param number The <code>long</code> to format.
 265:    * @param sbuf The <code>StringBuffer</code> to append the formatted number
 266:    *             to.
 267:    * @param pos The desired <code>FieldPosition</code>.
 268:    *
 269:    * @return The <code>StringBuffer</code> with the appended number.
 270:    */
 271:   public abstract StringBuffer format (long number,
 272:                                        StringBuffer sbuf, FieldPosition pos);
 273: 
 274:   /**
 275:    * This method tests the specified object for equality against this object.
 276:    * This will be <code>true</code> if the following conditions are met:
 277:    * <p>
 278:    * <ul>
 279:    * <li>The specified object is not <code>null</code>.
 280:    * <li>The specified object is an instance of <code>NumberFormat</code>.
 281:    * </ul>
 282:    * <p>
 283:    * Since this method does not test much, it is highly advised that
 284:    * concrete subclasses override this method.
 285:    *
 286:    * @param obj The <code>Object</code> to test against equality with
 287:    *            this object.
 288:    *
 289:    * @return <code>true</code> if the specified object is equal to
 290:    * this object, <code>false</code> otherwise.
 291:    */
 292:   public boolean equals (Object obj)
 293:   {
 294:     if (! (obj instanceof NumberFormat))
 295:       return false;
 296:     NumberFormat nf = (NumberFormat) obj;
 297:     return (groupingUsed == nf.groupingUsed
 298:             && maximumFractionDigits == nf.maximumFractionDigits
 299:             && maximumIntegerDigits == nf.maximumIntegerDigits
 300:             && minimumFractionDigits == nf.minimumFractionDigits
 301:             && minimumIntegerDigits == nf.minimumIntegerDigits
 302:             && parseIntegerOnly == nf.parseIntegerOnly);
 303:   }
 304: 
 305:   /**
 306:    * This method returns a list of locales for which concrete instances
 307:    * of <code>NumberFormat</code> subclasses may be created.
 308:    *
 309:    * @return The list of available locales.
 310:    */
 311:   public static Locale[] getAvailableLocales ()
 312:   {
 313:     Locale[] list = new Locale[1];
 314:     list[0] = Locale.US;
 315:     return list;
 316:   }
 317: 
 318:   private static NumberFormat computeInstance(Locale loc, String resource,
 319:                                               String def)
 320:     throws MissingResourceException
 321:   {
 322:     if (loc.equals(Locale.ROOT))
 323:       return new DecimalFormat(def, DecimalFormatSymbols.getInstance(loc));
 324:     ResourceBundle res =
 325:       ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
 326:                                loc, ClassLoader.getSystemClassLoader());
 327:     String fmt;
 328:     try
 329:       {
 330:         fmt = res == null ? def : res.getString(resource);
 331:       }
 332:     catch (MissingResourceException x)
 333:       {
 334:         fmt = def;
 335:       }
 336:     DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc);
 337:     return new DecimalFormat (fmt, dfs);
 338:   }
 339: 
 340:   /**
 341:    * This method returns an instance of <code>NumberFormat</code> suitable
 342:    * for formatting and parsing currency values in the default locale.
 343:    *
 344:    * @return An instance of <code>NumberFormat</code> for handling currencies.
 345:    */
 346:   public static final NumberFormat getCurrencyInstance ()
 347:   {
 348:     return getCurrencyInstance (Locale.getDefault());
 349:   }
 350: 
 351:   /**
 352:    * This method returns an instance of <code>NumberFormat</code> suitable
 353:    * for formatting and parsing currency values in the specified locale.
 354:    *
 355:    * @return An instance of <code>NumberFormat</code> for handling currencies.
 356:    */
 357:   public static NumberFormat getCurrencyInstance (Locale loc)
 358:   {
 359:     try
 360:       {
 361:         NumberFormat format;
 362: 
 363:         format = computeInstance (loc, "currencyFormat",
 364:                                   "\u00A4#,##0.00;(\u00A4#,##0.00)");
 365:         format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());
 366:         return format;
 367:       }
 368:     catch (MissingResourceException e)
 369:       {
 370:         for (NumberFormatProvider p :
 371:                ServiceLoader.load(NumberFormatProvider.class))
 372:           {
 373:             for (Locale l : p.getAvailableLocales())
 374:               {
 375:                 if (l.equals(loc))
 376:                   {
 377:                     NumberFormat nf = p.getCurrencyInstance(loc);
 378:                     if (nf != null)
 379:                       return nf;
 380:                     break;
 381:                   }
 382:               }
 383:           }
 384:         return getCurrencyInstance(LocaleHelper.getFallbackLocale(loc));
 385:       }
 386:   }
 387: 
 388:   /**
 389:    * This method returns a default instance for the default locale. This
 390:    * will be a concrete subclass of <code>NumberFormat</code>, but the
 391:    * actual class returned is dependent on the locale.
 392:    *
 393:    * @return An instance of the default <code>NumberFormat</code> class.
 394:    */
 395:   public static final NumberFormat getInstance ()
 396:   {
 397:     return getInstance (Locale.getDefault());
 398:   }
 399: 
 400:   /**
 401:    * This method returns a default instance for the specified locale. This
 402:    * will be a concrete subclass of <code>NumberFormat</code>, but the
 403:    * actual class returned is dependent on the locale.
 404:    *
 405:    * @param loc The desired locale.
 406:    *
 407:    * @return An instance of the default <code>NumberFormat</code> class.
 408:    */
 409:   public static NumberFormat getInstance (Locale loc)
 410:   {
 411:     // For now always return a number instance.
 412:     return getNumberInstance (loc);
 413:   }
 414: 
 415:   /**
 416:    * This method returns the maximum number of digits allowed in the fraction
 417:    * portion of a number.
 418:    *
 419:    * @return The maximum number of digits allowed in the fraction
 420:    * portion of a number.
 421:    */
 422:   public int getMaximumFractionDigits ()
 423:   {
 424:     return maximumFractionDigits;
 425:   }
 426: 
 427:   /**
 428:    * This method returns the maximum number of digits allowed in the integer
 429:    * portion of a number.
 430:    *
 431:    * @return The maximum number of digits allowed in the integer
 432:    * portion of a number.
 433:    */
 434:   public int getMaximumIntegerDigits ()
 435:   {
 436:     return maximumIntegerDigits;
 437:   }
 438: 
 439:   /**
 440:    * This method returns the minimum number of digits allowed in the fraction
 441:    * portion of a number.
 442:    *
 443:    * @return The minimum number of digits allowed in the fraction
 444:    * portion of a number.
 445:    */
 446:   public int getMinimumFractionDigits ()
 447:   {
 448:     return minimumFractionDigits;
 449:   }
 450: 
 451:   /**
 452:    * This method returns the minimum number of digits allowed in the integer
 453:    * portion of a number.
 454:    *
 455:    * @return The minimum number of digits allowed in the integer
 456:    * portion of a number.
 457:    */
 458:   public int getMinimumIntegerDigits ()
 459:   {
 460:     return minimumIntegerDigits;
 461:   }
 462: 
 463:   /**
 464:    * This method returns a default instance for the specified locale. This
 465:    * will be a concrete subclass of <code>NumberFormat</code>, but the
 466:    * actual class returned is dependent on the locale.
 467:    *
 468:    * @return An instance of the default <code>NumberFormat</code> class.
 469:    */
 470:   public static final NumberFormat getNumberInstance ()
 471:   {
 472:     return getNumberInstance (Locale.getDefault());
 473:   }
 474: 
 475:   /**
 476:    * This method returns a general purpose number formatting and parsing
 477:    * class for the default locale.  This will be a concrete subclass of
 478:    * <code>NumberFormat</code>, but the actual class returned is dependent
 479:    * on the locale.
 480:    *
 481:    * @return An instance of a generic number formatter for the default locale.
 482:    */
 483:   public static NumberFormat getNumberInstance (Locale loc)
 484:   {
 485:     try
 486:       {
 487:         return computeInstance (loc, "numberFormat", "#,##0.###");
 488:       }
 489:     catch (MissingResourceException e)
 490:       {
 491:         for (NumberFormatProvider p :
 492:                ServiceLoader.load(NumberFormatProvider.class))
 493:           {
 494:             for (Locale l : p.getAvailableLocales())
 495:               {
 496:                 if (l.equals(loc))
 497:                   {
 498:                     NumberFormat nf = p.getNumberInstance(loc);
 499:                     if (nf != null)
 500:                       return nf;
 501:                     break;
 502:                   }
 503:               }
 504:           }
 505:         return getNumberInstance(LocaleHelper.getFallbackLocale(loc));
 506:       }
 507:   }
 508: 
 509:   /**
 510:    * This method returns an integer formatting and parsing class for the
 511:    * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
 512:    * but the actual class returned is dependent on the locale.
 513:    *
 514:    * @return An instance of an integer number formatter for the default locale.
 515:    * @since 1.4
 516:    */
 517:   public static final NumberFormat getIntegerInstance()
 518:   {
 519:     return getIntegerInstance (Locale.getDefault());
 520:   }
 521: 
 522:   /**
 523:    * This method returns an integer formatting and parsing class for the
 524:    * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
 525:    * but the actual class returned is dependent on the locale.
 526:    *
 527:    * @param locale the desired locale.
 528:    *
 529:    * @return An instance of an integer number formatter for the desired locale.
 530:    * @since 1.4
 531:    */
 532:   public static NumberFormat getIntegerInstance(Locale locale)
 533:   {
 534:     try
 535:       {
 536:         NumberFormat format = computeInstance (locale,
 537:                                                "integerFormat", "#,##0");
 538:         format.setMaximumFractionDigits(0);
 539:         format.setParseIntegerOnly (true);
 540:         return format;
 541:       }
 542:     catch (MissingResourceException e)
 543:       {
 544:         for (NumberFormatProvider p :
 545:                ServiceLoader.load(NumberFormatProvider.class))
 546:           {
 547:             for (Locale l : p.getAvailableLocales())
 548:               {
 549:                 if (l.equals(locale))
 550:                   {
 551:                     NumberFormat nf = p.getIntegerInstance(locale);
 552:                     if (nf != null)
 553:                       return nf;
 554:                     break;
 555:                   }
 556:               }
 557:           }
 558:         return getIntegerInstance(LocaleHelper.getFallbackLocale(locale));
 559:       }
 560:   }
 561: 
 562:   /**
 563:    * This method returns an instance of <code>NumberFormat</code> suitable
 564:    * for formatting and parsing percentage values in the default locale.
 565:    *
 566:    * @return An instance of <code>NumberFormat</code> for handling percentages.
 567:    */
 568:   public static final NumberFormat getPercentInstance ()
 569:   {
 570:     return getPercentInstance (Locale.getDefault());
 571:   }
 572: 
 573:   /**
 574:    * This method returns an instance of <code>NumberFormat</code> suitable
 575:    * for formatting and parsing percentage values in the specified locale.
 576:    *
 577:    * @param loc The desired locale.
 578:    *
 579:    * @return An instance of <code>NumberFormat</code> for handling percentages.
 580:    */
 581:   public static NumberFormat getPercentInstance (Locale loc)
 582:   {
 583:     try
 584:       {
 585:         return computeInstance (loc, "percentFormat", "#,##0%");
 586:       }
 587:     catch (MissingResourceException e)
 588:       {
 589:         for (NumberFormatProvider p :
 590:                ServiceLoader.load(NumberFormatProvider.class))
 591:           {
 592:             for (Locale l : p.getAvailableLocales())
 593:               {
 594:                 if (l.equals(loc))
 595:                   {
 596:                     NumberFormat nf = p.getPercentInstance(loc);
 597:                     if (nf != null)
 598:                       return nf;
 599:                     break;
 600:                   }
 601:               }
 602:           }
 603:         return getPercentInstance(LocaleHelper.getFallbackLocale(loc));
 604:       }
 605:   }
 606: 
 607:   /**
 608:    * This method returns a hash value for this object.
 609:    *
 610:    * @return The hash code.
 611:    */
 612:   public int hashCode ()
 613:   {
 614:     int hash = super.hashCode();
 615:     hash ^= (maximumFractionDigits + maximumIntegerDigits
 616:              + minimumFractionDigits + minimumIntegerDigits);
 617:     if (groupingUsed)
 618:       hash ^= 0xf0f0;
 619:     if (parseIntegerOnly)
 620:       hash ^= 0x0f0f;
 621:     return hash;
 622:   }
 623: 
 624:   /**
 625:    * This method tests whether or not grouping is in use.  Grouping is
 626:    * a method of marking separations in numbers, such as thousand separators
 627:    * in the US English locale.  The grouping positions and symbols are all
 628:    * locale specific.  As an example, with grouping disabled, the number one
 629:    * million would appear as "1000000".  With grouping enabled, this number
 630:    * might appear as "1,000,000".  (Both of these assume the US English
 631:    * locale).
 632:    *
 633:    * @return <code>true</code> if grouping is enabled,
 634:    * <code>false</code> otherwise.
 635:    */
 636:   public boolean isGroupingUsed ()
 637:   {
 638:     return groupingUsed;
 639:   }
 640: 
 641:   /**
 642:    * This method tests whether or not only integer values should be parsed.
 643:    * If this class is parsing only integers, parsing stops at the decimal
 644:    * point.
 645:    *
 646:    * @return <code>true</code> if only integers are parsed,
 647:    * <code>false</code> otherwise.
 648:    */
 649:   public boolean isParseIntegerOnly ()
 650:   {
 651:     return parseIntegerOnly;
 652:   }
 653: 
 654:   /**
 655:    * This is a default constructor for use by subclasses.
 656:    */
 657:   protected NumberFormat ()
 658:   {
 659:   }
 660: 
 661:   /**
 662:    * This method parses the specified string into a <code>Number</code>.  This
 663:    * will be a <code>Long</code> if possible, otherwise it will be a
 664:    * <code>Double</code>.    If no number can be parsed, no exception is
 665:    * thrown.  Instead, the parse position remains at its initial index.
 666:    *
 667:    * @param sourceStr The string to parse.
 668:    * @param pos The desired <code>ParsePosition</code>.
 669:    *
 670:    * @return The parsed <code>Number</code>
 671:    */
 672:   public abstract Number parse (String sourceStr, ParsePosition pos);
 673: 
 674:   /**
 675:    * This method parses the specified string into a <code>Number</code>.  This
 676:    * will be a <code>Long</code> if possible, otherwise it will be a
 677:    * <code>Double</code>.  If no number can be parsed, an exception will be
 678:    * thrown.
 679:    *
 680:    * @param sourceStr The string to parse.
 681:    *
 682:    * @return The parsed <code>Number</code>
 683:    *
 684:    * @exception ParseException If no number can be parsed.
 685:    */
 686:   public Number parse (String sourceStr) throws ParseException
 687:   {
 688:     ParsePosition pp = new ParsePosition (0);
 689:     Number r = parse (sourceStr, pp);
 690:     if (r == null)
 691:       {
 692:         int index = pp.getErrorIndex();
 693:         if (index < 0)
 694:           index = pp.getIndex();
 695:         throw new ParseException ("couldn't parse number", index);
 696:       }
 697:     return r;
 698:   }
 699: 
 700:   /**
 701:    * This method parses the specified string into an <code>Object</code>.  This
 702:    * will be a <code>Long</code> if possible, otherwise it will be a
 703:    * <code>Double</code>.    If no number can be parsed, no exception is
 704:    * thrown.  Instead, the parse position remains at its initial index.
 705:    *
 706:    * @param sourceStr The string to parse.
 707:    * @param pos The desired <code>ParsePosition</code>.
 708:   *
 709:   * @return The parsed <code>Object</code>
 710:   */
 711:   public final Object parseObject (String sourceStr, ParsePosition pos)
 712:   {
 713:     return parse (sourceStr, pos);
 714:   }
 715: 
 716:   /**
 717:    * This method sets the grouping behavior of this formatter.  Grouping is
 718:    * a method of marking separations in numbers, such as thousand separators
 719:    * in the US English locale.  The grouping positions and symbols are all
 720:    * locale specific.  As an example, with grouping disabled, the number one
 721:    * million would appear as "1000000".  With grouping enabled, this number
 722:    * might appear as "1,000,000".  (Both of these assume the US English
 723:    * locale).
 724:    *
 725:    * @param newValue <code>true</code> to enable grouping,
 726:    *                     <code>false</code> to disable it.
 727:    */
 728:   public void setGroupingUsed (boolean newValue)
 729:   {
 730:     groupingUsed = newValue;
 731:   }
 732: 
 733:   /**
 734:    * This method sets the maximum number of digits allowed in the fraction
 735:    * portion of a number to the specified value.  If this is less than the
 736:    * current minimum allowed digits, the minimum allowed digits value will
 737:    * be lowered to be equal to the new maximum allowed digits value.
 738:    *
 739:    * @param digits The new maximum fraction digits value.
 740:    */
 741:   public void setMaximumFractionDigits (int digits)
 742:   {
 743:     maximumFractionDigits = digits;
 744:     if (getMinimumFractionDigits () > maximumFractionDigits)
 745:       setMinimumFractionDigits (maximumFractionDigits);
 746:   }
 747: 
 748:   /**
 749:    * This method sets the maximum number of digits allowed in the integer
 750:    * portion of a number to the specified value.  If this is less than the
 751:    * current minimum allowed digits, the minimum allowed digits value will
 752:    * be lowered to be equal to the new maximum allowed digits value.
 753:    *
 754:    * @param digits The new maximum integer digits value.
 755:    */
 756:   public void setMaximumIntegerDigits (int digits)
 757:   {
 758:     maximumIntegerDigits = digits;
 759:     if (getMinimumIntegerDigits () > maximumIntegerDigits)
 760:       setMinimumIntegerDigits (maximumIntegerDigits);
 761:   }
 762: 
 763:   /**
 764:    * This method sets the minimum number of digits allowed in the fraction
 765:    * portion of a number to the specified value.  If this is greater than the
 766:    * current maximum allowed digits, the maximum allowed digits value will
 767:    * be raised to be equal to the new minimum allowed digits value.
 768:    *
 769:    * @param digits The new minimum fraction digits value.
 770:    */
 771:   public void setMinimumFractionDigits (int digits)
 772:   {
 773:     minimumFractionDigits = digits;
 774:     if (getMaximumFractionDigits () < minimumFractionDigits)
 775:       setMaximumFractionDigits (minimumFractionDigits);
 776:   }
 777: 
 778:   /**
 779:    * This method sets the minimum number of digits allowed in the integer
 780:    * portion of a number to the specified value.  If this is greater than the
 781:    * current maximum allowed digits, the maximum allowed digits value will
 782:    * be raised to be equal to the new minimum allowed digits value.
 783:    *
 784:    * @param digits The new minimum integer digits value.
 785:    */
 786:   public void setMinimumIntegerDigits (int digits)
 787:   {
 788:     minimumIntegerDigits = digits;
 789:     if (getMaximumIntegerDigits () < minimumIntegerDigits)
 790:       setMaximumIntegerDigits (minimumIntegerDigits);
 791:   }
 792: 
 793:   /**
 794:    * This method sets the parsing behavior of this object to parse only
 795:    * integers or not.
 796:    *
 797:    * @param value <code>true</code> to parse only integers,
 798:    *                         <code>false</code> otherwise.
 799:    */
 800:   public void setParseIntegerOnly (boolean value)
 801:   {
 802:     parseIntegerOnly = value;
 803:   }
 804: 
 805:   /**
 806:    * This method is a specialization of the format method that performs
 807:    * a simple formatting of the specified <code>double</code> number.
 808:    *
 809:    * @param number The <code>double</code> to format.
 810:    *
 811:    * @return The formatted number
 812:    */
 813:   public final String format (double number)
 814:   {
 815:     StringBuffer sbuf = new StringBuffer(50);
 816:     FieldPosition position = new FieldPosition(0);
 817: 
 818:     format (number, sbuf, position);
 819:     return sbuf.toString();
 820:   }
 821: 
 822:   // These field names are fixed by the serialization spec.
 823:   boolean groupingUsed;
 824:   int maximumFractionDigits;
 825:   private byte maxFractionDigits;
 826:   int maximumIntegerDigits;
 827:   private byte maxIntegerDigits;
 828:   int minimumFractionDigits;
 829:   private byte minFractionDigits;
 830:   int minimumIntegerDigits;
 831:   private byte minIntegerDigits;
 832:   boolean parseIntegerOnly;
 833:   private int serialVersionOnStream;
 834:   private static final long serialVersionUID = -2308460125733713944L;
 835: 
 836:   private void readObject(ObjectInputStream stream)
 837:     throws IOException, ClassNotFoundException
 838:   {
 839:     stream.defaultReadObject();
 840:     if (serialVersionOnStream < 1)
 841:       {
 842:         maximumFractionDigits = maxFractionDigits;
 843:         maximumIntegerDigits = maxIntegerDigits;
 844:         minimumFractionDigits = minFractionDigits;
 845:         minimumIntegerDigits = minIntegerDigits;
 846:         serialVersionOnStream = 1;
 847:       }
 848:   }
 849: 
 850:   private void writeObject(ObjectOutputStream stream) throws IOException
 851:   {
 852:     maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
 853:       (byte) maximumFractionDigits : Byte.MAX_VALUE;
 854:     maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
 855:       (byte) maximumIntegerDigits : Byte.MAX_VALUE;
 856:     minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
 857:       (byte) minimumFractionDigits : Byte.MAX_VALUE;
 858:     minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
 859:       (byte) minimumIntegerDigits : Byte.MAX_VALUE;
 860:     serialVersionOnStream = 1;
 861:     stream.defaultWriteObject();
 862:   }
 863: 
 864:   /**
 865:    * Returns the currency used by this number format when formatting currency
 866:    * values.
 867:    *
 868:    * The default implementation throws UnsupportedOperationException.
 869:    *
 870:    * @return The used currency object, or null.
 871:    *
 872:    * @throws UnsupportedOperationException If the number format class doesn't
 873:    * implement currency formatting.
 874:    *
 875:    * @since 1.4
 876:    */
 877:   public Currency getCurrency()
 878:   {
 879:     throw new UnsupportedOperationException();
 880:   }
 881: 
 882:   /**
 883:    * Sets the currency used by this number format when formatting currency
 884:    * values.
 885:    *
 886:    * The default implementation throws UnsupportedOperationException.
 887:    *
 888:    * @param currency The new currency to be used by this number format.
 889:    *
 890:    * @throws NullPointerException If currenc is null.
 891:    * @throws UnsupportedOperationException If the number format class doesn't
 892:    * implement currency formatting.
 893:    *
 894:    * @since 1.4
 895:    */
 896:   public void setCurrency(Currency currency)
 897:   {
 898:     if (currency == null)
 899:       throw new NullPointerException("currency may not be null");
 900: 
 901:     throw new UnsupportedOperationException();
 902:   }
 903: }