Source for java.text.DecimalFormat

   1: /* DecimalFormat.java -- Formats and parses numbers
   2:    Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10:  
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: /* 
  39:  * This class contains few bits from ICU4J (http://icu.sourceforge.net/),
  40:  * Copyright by IBM and others and distributed under the
  41:  * distributed under MIT/X.
  42:  */
  43: 
  44: package java.text;
  45: 
  46: import java.math.BigDecimal;
  47: import java.math.BigInteger;
  48: 
  49: import java.util.ArrayList;
  50: import java.util.Currency;
  51: import java.util.Locale;
  52: 
  53: /*
  54:  * This note is here for historical reasons and because I had not the courage
  55:  * to remove it :)
  56:  *  
  57:  * @author Tom Tromey (tromey@cygnus.com)
  58:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  59:  * @date March 4, 1999
  60:  *
  61:  * Written using "Java Class Libraries", 2nd edition, plus online
  62:  * API docs for JDK 1.2 from http://www.javasoft.com.
  63:  * Status:  Believed complete and correct to 1.2.
  64:  * Note however that the docs are very unclear about how format parsing
  65:  * should work.  No doubt there are problems here.
  66:  */
  67: 
  68: /**
  69:  * This class is a concrete implementation of NumberFormat used to format
  70:  * decimal numbers. The class can format numbers given a specific locale.
  71:  * Generally, to get an instance of DecimalFormat you should call the factory
  72:  * methods in the <code>NumberFormat</code> base class.
  73:  * 
  74:  * @author Mario Torre <neugens@limasoftware.net>
  75:  * @author Tom Tromey (tromey@cygnus.com)
  76:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  77:  */
  78: public class DecimalFormat extends NumberFormat
  79: {
  80:   /** serialVersionUID for serializartion. */
  81:   private static final long serialVersionUID = 864413376551465018L;
  82:   
  83:   /** Defines the default number of digits allowed while formatting integers. */
  84:   private static final int DEFAULT_INTEGER_DIGITS = 309; 
  85: 
  86:   /**
  87:    * Defines the default number of digits allowed while formatting
  88:    * fractions.
  89:    */
  90:   private static final int DEFAULT_FRACTION_DIGITS = 340;
  91:   
  92:   /**
  93:    * Locale-independent pattern symbols.
  94:    */
  95:   // Happen to be the same as the US symbols.
  96:   private static final DecimalFormatSymbols nonLocalizedSymbols
  97:     = new DecimalFormatSymbols (Locale.US);
  98:   
  99:   /**
 100:    * Defines if parse should return a BigDecimal or not.
 101:    */
 102:   private boolean parseBigDecimal;
 103:   
 104:   /**
 105:    * Defines if we have to use the monetary decimal separator or
 106:    * the decimal separator while formatting numbers.
 107:    */
 108:   private boolean useCurrencySeparator;
 109:     
 110:   /** Defines if the decimal separator is always shown or not. */
 111:   private boolean decimalSeparatorAlwaysShown;
 112:   
 113:   /**
 114:    * Defines if the decimal separator has to be shown.
 115:    * 
 116:    * This is different then <code>decimalSeparatorAlwaysShown</code>,
 117:    * as it defines if the format string contains a decimal separator or no.
 118:    */
 119:   private boolean showDecimalSeparator;
 120:   
 121:   /**
 122:    * This field is used to determine if the grouping
 123:    * separator is included in the format string or not.
 124:    * This is only needed to match the behaviour of the RI.
 125:    */
 126:   private boolean groupingSeparatorInPattern;
 127:   
 128:   /** Defines the size of grouping groups when grouping is used. */
 129:   private byte groupingSize;
 130:   
 131:   /**
 132:    * This is an internal parameter used to keep track of the number
 133:    * of digits the form the exponent, when exponential notation is used.
 134:    * It is used with <code>exponentRound</code>
 135:    */
 136:   private byte minExponentDigits;
 137:  
 138:   /** This field is used to set the exponent in the engineering notation. */
 139:   private int exponentRound;
 140:   
 141:   /** Multiplier used in percent style formats. */
 142:   private int multiplier;
 143:   
 144:   /** Multiplier used in percent style formats. */
 145:   private int negativePatternMultiplier;
 146:   
 147:   /** The negative prefix. */
 148:   private String negativePrefix;
 149:   
 150:   /** The negative suffix. */
 151:   private String negativeSuffix;
 152:   
 153:   /** The positive prefix. */
 154:   private String positivePrefix;
 155:   
 156:   /** The positive suffix. */
 157:   private String positiveSuffix;
 158:   
 159:   /** Decimal Format Symbols for the given locale. */
 160:   private DecimalFormatSymbols symbols;
 161:   
 162:   /** Determine if we have to use exponential notation or not. */
 163:   private boolean useExponentialNotation;
 164:   
 165:   /**
 166:    * Defines the maximum number of integer digits to show when we use
 167:    * the exponential notation.
 168:    */
 169:   private int maxIntegerDigitsExponent;
 170:   
 171:   /** Defines if the format string has a negative prefix or not. */
 172:   private boolean hasNegativePrefix;
 173:   
 174:   /** Defines if the format string has a fractional pattern or not. */
 175:   private boolean hasFractionalPattern;
 176:  
 177:   /** Stores a list of attributes for use by formatToCharacterIterator. */
 178:   private ArrayList attributes = new ArrayList();
 179:   
 180:   /**
 181:    * Constructs a <code>DecimalFormat</code> which uses the default
 182:    * pattern and symbols.
 183:    */
 184:   public DecimalFormat()
 185:   {
 186:     this ("#,##0.###");
 187:   }
 188:   
 189:   /**
 190:    * Constructs a <code>DecimalFormat</code> which uses the given
 191:    * pattern and the default symbols for formatting and parsing.
 192:    *
 193:    * @param pattern the non-localized pattern to use.
 194:    * @throws NullPointerException if any argument is null.
 195:    * @throws IllegalArgumentException if the pattern is invalid.
 196:    */
 197:   public DecimalFormat(String pattern)
 198:   {
 199:     this (pattern, new DecimalFormatSymbols());
 200:   }
 201: 
 202:   /**
 203:    * Constructs a <code>DecimalFormat</code> using the given pattern
 204:    * and formatting symbols.  This construction method is used to give
 205:    * complete control over the formatting process.  
 206:    *
 207:    * @param pattern the non-localized pattern to use.
 208:    * @param symbols the set of symbols used for parsing and formatting.
 209:    * @throws NullPointerException if any argument is null.
 210:    * @throws IllegalArgumentException if the pattern is invalid.
 211:    */
 212:   public DecimalFormat(String pattern, DecimalFormatSymbols symbols)
 213:   {
 214:     this.symbols = (DecimalFormatSymbols) symbols.clone();
 215:     applyPatternWithSymbols(pattern, nonLocalizedSymbols);
 216:   }
 217:   
 218:   /**
 219:    * Apply the given localized patern to the current DecimalFormat object.
 220:    * 
 221:    * @param pattern The localized pattern to apply.
 222:    * @throws IllegalArgumentException if the given pattern is invalid.
 223:    * @throws NullPointerException if the input pattern is null.
 224:    */
 225:   public void applyLocalizedPattern (String pattern)
 226:   {
 227:     applyPatternWithSymbols(pattern, this.symbols);
 228:   }
 229: 
 230:   /**
 231:    * Apply the given localized pattern to the current DecimalFormat object.
 232:    * 
 233:    * @param pattern The localized pattern to apply.
 234:    * @throws IllegalArgumentException if the given pattern is invalid.
 235:    * @throws NullPointerException if the input pattern is null.
 236:    */
 237:   public void applyPattern(String pattern)
 238:   {
 239:     applyPatternWithSymbols(pattern, nonLocalizedSymbols);
 240:   }
 241: 
 242:   public Object clone()
 243:   {
 244:     DecimalFormat c = (DecimalFormat) super.clone();
 245:     c.symbols = (DecimalFormatSymbols) symbols.clone();
 246:     return c;
 247:   }
 248: 
 249:   /**
 250:    * Tests this instance for equality with an arbitrary object.  This method
 251:    * returns <code>true</code> if:
 252:    * <ul>
 253:    * <li><code>obj</code> is not <code>null</code>;</li>
 254:    * <li><code>obj</code> is an instance of <code>DecimalFormat</code>;</li>
 255:    * <li>this instance and <code>obj</code> have the same attributes;</li>
 256:    * </ul>
 257:    * 
 258:    * @param obj  the object (<code>null</code> permitted).
 259:    * 
 260:    * @return A boolean.
 261:    */
 262:   public boolean equals(Object obj)
 263:   {
 264:     if (! (obj instanceof DecimalFormat))
 265:       return false;
 266:     DecimalFormat dup = (DecimalFormat) obj;
 267:     return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown 
 268:            && groupingUsed == dup.groupingUsed
 269:            && groupingSeparatorInPattern == dup.groupingSeparatorInPattern 
 270:            && groupingSize == dup.groupingSize
 271:            && multiplier == dup.multiplier
 272:            && useExponentialNotation == dup.useExponentialNotation
 273:            && minExponentDigits == dup.minExponentDigits
 274:            && minimumIntegerDigits == dup.minimumIntegerDigits
 275:            && maximumIntegerDigits == dup.maximumIntegerDigits
 276:            && minimumFractionDigits == dup.minimumFractionDigits
 277:            && maximumFractionDigits == dup.maximumFractionDigits
 278:            && parseBigDecimal == dup.parseBigDecimal
 279:            && useCurrencySeparator == dup.useCurrencySeparator
 280:            && showDecimalSeparator == dup.showDecimalSeparator
 281:            && exponentRound == dup.exponentRound
 282:            && negativePatternMultiplier == dup.negativePatternMultiplier
 283:            && maxIntegerDigitsExponent == dup.maxIntegerDigitsExponent
 284:            // XXX: causes equivalent patterns to fail
 285:            // && hasNegativePrefix == dup.hasNegativePrefix
 286:            && equals(negativePrefix, dup.negativePrefix)
 287:            && equals(negativeSuffix, dup.negativeSuffix)
 288:            && equals(positivePrefix, dup.positivePrefix)
 289:            && equals(positiveSuffix, dup.positiveSuffix)
 290:            && symbols.equals(dup.symbols));
 291:   }
 292: 
 293:   /**
 294:    * Returns a hash code for this object.
 295:    *
 296:    * @return A hash code.
 297:    */
 298:   public int hashCode()
 299:   {
 300:     return toPattern().hashCode();
 301:   }
 302:   
 303:   /**
 304:    * Produce a formatted {@link String} representation of this object.
 305:    * The passed object must be of type number. 
 306:    * 
 307:    * @param obj The {@link Number} to format.
 308:    * @param sbuf The destination String; text will be appended to this String. 
 309:    * @param pos If used on input can be used to define an alignment
 310:    * field. If used on output defines the offsets of the alignment field.
 311:    * @return The String representation of this long.
 312:    */
 313:   public StringBuffer format(Object obj, StringBuffer sbuf, FieldPosition pos)
 314:   {
 315:     if (obj instanceof BigInteger)
 316:       {
 317:         BigDecimal decimal = new BigDecimal((BigInteger) obj);
 318:         formatInternal(decimal, true, sbuf, pos);
 319:         return sbuf;
 320:       }
 321:     else if (obj instanceof BigDecimal)
 322:       {
 323:         formatInternal((BigDecimal) obj, true, sbuf, pos);
 324:         return sbuf;
 325:       }
 326:     
 327:     return super.format(obj, sbuf, pos);
 328:   }
 329:   
 330:   /**
 331:    * Produce a formatted {@link String} representation of this double.
 332:    * 
 333:    * @param number The double to format.
 334:    * @param dest The destination String; text will be appended to this String. 
 335:    * @param fieldPos If used on input can be used to define an alignment
 336:    * field. If used on output defines the offsets of the alignment field.
 337:    * @return The String representation of this long.
 338:    * @throws NullPointerException if <code>dest</code> or fieldPos are null
 339:    */
 340:   public StringBuffer format(double number, StringBuffer dest,
 341:                  FieldPosition fieldPos)
 342:   {
 343:     // special cases for double: NaN and negative or positive infinity
 344:     if (Double.isNaN(number))
 345:       {
 346:         // 1. NaN
 347:         String nan = symbols.getNaN();
 348:         dest.append(nan);
 349:         
 350:         // update field position if required
 351:         if ((fieldPos.getField() == INTEGER_FIELD ||
 352:              fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
 353:           {
 354:             int index = dest.length();
 355:             fieldPos.setBeginIndex(index - nan.length());
 356:             fieldPos.setEndIndex(index);
 357:           }
 358:       }
 359:     else if (Double.isInfinite(number))
 360:       {
 361:         // 2. Infinity
 362:         if (number < 0)
 363:           dest.append(this.negativePrefix);
 364:         else
 365:           dest.append(this.positivePrefix);
 366:         
 367:         dest.append(symbols.getInfinity());
 368:         
 369:         if (number < 0)
 370:           dest.append(this.negativeSuffix);
 371:         else
 372:           dest.append(this.positiveSuffix);
 373:         
 374:         if ((fieldPos.getField() == INTEGER_FIELD ||
 375:             fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
 376:          {
 377:            fieldPos.setBeginIndex(dest.length());
 378:            fieldPos.setEndIndex(0);
 379:          }
 380:       }
 381:     else
 382:       {
 383:         // get the number as a BigDecimal
 384:         BigDecimal bigDecimal = new BigDecimal(String.valueOf(number));
 385:         formatInternal(bigDecimal, false, dest, fieldPos);
 386:       }
 387:     
 388:     return dest;
 389:   }
 390: 
 391:   /**
 392:    * Produce a formatted {@link String} representation of this long.
 393:    * 
 394:    * @param number The long to format.
 395:    * @param dest The destination String; text will be appended to this String. 
 396:    * @param fieldPos If used on input can be used to define an alignment
 397:    * field. If used on output defines the offsets of the alignment field.
 398:    * @return The String representation of this long.
 399:    */
 400:   public StringBuffer format(long number, StringBuffer dest,
 401:                              FieldPosition fieldPos)
 402:   {
 403:     BigDecimal bigDecimal = new BigDecimal(String.valueOf(number));
 404:     formatInternal(bigDecimal, true, dest, fieldPos);
 405:     return dest;
 406:   }
 407:   
 408:   /**
 409:    * Return an <code>AttributedCharacterIterator</code> as a result of
 410:    * the formatting of the passed {@link Object}.
 411:    * 
 412:    * @return An {@link AttributedCharacterIterator}.
 413:    * @throws NullPointerException if value is <code>null</code>. 
 414:    * @throws IllegalArgumentException if value is not an instance of
 415:    * {@link Number}.
 416:    */
 417:   public AttributedCharacterIterator formatToCharacterIterator(Object value)
 418:   {
 419:     /*
 420:      * This method implementation derives directly from the
 421:      * ICU4J (http://icu.sourceforge.net/) library, distributed under MIT/X.
 422:      */
 423:     
 424:     if (value == null)
 425:       throw new NullPointerException("Passed Object is null");
 426:     
 427:     if (!(value instanceof Number)) throw new
 428:       IllegalArgumentException("Cannot format given Object as a Number");
 429:     
 430:     StringBuffer text = new StringBuffer();
 431:     attributes.clear();
 432:     super.format(value, text, new FieldPosition(0));
 433: 
 434:     AttributedString as = new AttributedString(text.toString());
 435: 
 436:     // add NumberFormat field attributes to the AttributedString
 437:     for (int i = 0; i < attributes.size(); i++)
 438:       {
 439:         FieldPosition pos = (FieldPosition) attributes.get(i);
 440:         Format.Field attribute = pos.getFieldAttribute();
 441:         
 442:         as.addAttribute(attribute, attribute, pos.getBeginIndex(),
 443:                         pos.getEndIndex());
 444:       }
 445:     
 446:     // return the CharacterIterator from AttributedString
 447:     return as.getIterator();
 448:   }
 449:   
 450:   /**
 451:    * Returns the currency corresponding to the currency symbol stored
 452:    * in the instance of <code>DecimalFormatSymbols</code> used by this
 453:    * <code>DecimalFormat</code>.
 454:    *
 455:    * @return A new instance of <code>Currency</code> if
 456:    * the currency code matches a known one, null otherwise.
 457:    */
 458:   public Currency getCurrency()
 459:   {
 460:     return symbols.getCurrency();
 461:   }
 462:   
 463:   /**
 464:    * Returns a copy of the symbols used by this instance.
 465:    * 
 466:    * @return A copy of the symbols.
 467:    */
 468:   public DecimalFormatSymbols getDecimalFormatSymbols()
 469:   {
 470:     return (DecimalFormatSymbols) symbols.clone();
 471:   }
 472:   
 473:   /**
 474:    * Gets the interval used between a grouping separator and the next.
 475:    * For example, a grouping size of 3 means that the number 1234 is
 476:    * formatted as 1,234.
 477:    * 
 478:    * The actual character used as grouping separator depends on the
 479:    * locale and is defined by {@link DecimalFormatSymbols#getDecimalSeparator()}
 480:    * 
 481:    * @return The interval used between a grouping separator and the next.
 482:    */
 483:   public int getGroupingSize()
 484:   {
 485:     return groupingSize;
 486:   }
 487: 
 488:   /**
 489:    * Gets the multiplier used in percent and similar formats.
 490:    * 
 491:    * @return The multiplier used in percent and similar formats.
 492:    */
 493:   public int getMultiplier()
 494:   {
 495:     return multiplier;
 496:   }
 497:   
 498:   /**
 499:    * Gets the negative prefix.
 500:    * 
 501:    * @return The negative prefix.
 502:    */
 503:   public String getNegativePrefix()
 504:   {
 505:     return negativePrefix;
 506:   }
 507: 
 508:   /**
 509:    * Gets the negative suffix.
 510:    * 
 511:    * @return The negative suffix.
 512:    */
 513:   public String getNegativeSuffix()
 514:   {
 515:     return negativeSuffix;
 516:   }
 517:   
 518:   /**
 519:    * Gets the positive prefix.
 520:    * 
 521:    * @return The positive prefix.
 522:    */
 523:   public String getPositivePrefix()
 524:   {
 525:     return positivePrefix;
 526:   }
 527:   
 528:   /**
 529:    * Gets the positive suffix.
 530:    *  
 531:    * @return The positive suffix.
 532:    */
 533:   public String getPositiveSuffix()
 534:   {
 535:     return positiveSuffix;
 536:   }
 537:   
 538:   public boolean isDecimalSeparatorAlwaysShown()
 539:   {
 540:     return decimalSeparatorAlwaysShown;
 541:   }
 542:   
 543:   /**
 544:    * Define if <code>parse(java.lang.String, java.text.ParsePosition)</code>
 545:    * should return a {@link BigDecimal} or not. 
 546:    * 
 547:    * @param newValue
 548:    */
 549:   public void setParseBigDecimal(boolean newValue)
 550:   {
 551:     this.parseBigDecimal = newValue;
 552:   }
 553:   
 554:   /**
 555:    * Returns <code>true</code> if
 556:    * <code>parse(java.lang.String, java.text.ParsePosition)</code> returns
 557:    * a <code>BigDecimal</code>, <code>false</code> otherwise.
 558:    * The default return value for this method is <code>false</code>.
 559:    * 
 560:    * @return <code>true</code> if the parse method returns a {@link BigDecimal},
 561:    * <code>false</code> otherwise.
 562:    * @since 1.5
 563:    * @see #setParseBigDecimal(boolean)
 564:    */
 565:   public boolean isParseBigDecimal()
 566:   {
 567:     return this.parseBigDecimal;
 568:   }
 569:   
 570:   /**
 571:    * This method parses the specified string into a <code>Number</code>.
 572:    * 
 573:    * The parsing starts at <code>pos</code>, which is updated as the parser
 574:    * consume characters in the passed string.
 575:    * On error, the <code>Position</code> object index is not updated, while
 576:    * error position is set appropriately, an <code>null</code> is returned.
 577:    * 
 578:    * @param str The string to parse.
 579:    * @param pos The desired <code>ParsePosition</code>.
 580:    *
 581:    * @return The parsed <code>Number</code>
 582:    */
 583:   public Number parse(String str, ParsePosition pos)
 584:   {
 585:     // a special values before anything else
 586:     // NaN
 587:     if (str.contains(this.symbols.getNaN()))
 588:       return Double.valueOf(Double.NaN);
 589:    
 590:     // this will be our final number
 591:     StringBuffer number = new StringBuffer();
 592:     
 593:     // special character
 594:     char minus = symbols.getMinusSign();
 595:     
 596:     // starting parsing position
 597:     int start = pos.getIndex();
 598:     
 599:     // validate the string, it have to be in the 
 600:     // same form as the format string or parsing will fail
 601:     String _negativePrefix = (this.negativePrefix.compareTo("") == 0
 602:                               ? minus + positivePrefix
 603:                               : this.negativePrefix);
 604:     
 605:     // we check both prefixes, because one might be empty.
 606:     // We want to pick the longest prefix that matches.
 607:     int positiveLen = positivePrefix.length();
 608:     int negativeLen = _negativePrefix.length();
 609:     
 610:     boolean isNegative = str.startsWith(_negativePrefix);
 611:     boolean isPositive = str.startsWith(positivePrefix);
 612:     
 613:     if (isPositive && isNegative)
 614:       {
 615:         // By checking this way, we preserve ambiguity in the case
 616:         // where the negative format differs only in suffix.
 617:         if (negativeLen > positiveLen)
 618:           {
 619:             start += _negativePrefix.length();
 620:             isNegative = true;
 621:           }
 622:         else
 623:           {
 624:             start += positivePrefix.length();
 625:             isPositive = true;
 626:             if (negativeLen < positiveLen)
 627:               isNegative = false;
 628:           }
 629:       }
 630:     else if (isNegative)
 631:       {
 632:         start += _negativePrefix.length();
 633:         isPositive = false;
 634:       }
 635:     else if (isPositive)
 636:       {
 637:         start += positivePrefix.length();
 638:         isNegative = false;
 639:       }
 640:     else
 641:       {
 642:         pos.setErrorIndex(start);
 643:         return null;
 644:       }
 645:     
 646:     // other special characters used by the parser
 647:     char decimalSeparator = symbols.getDecimalSeparator();
 648:     char zero = symbols.getZeroDigit();
 649:     char exponent = symbols.getExponential(); 
 650:     
 651:     // stop parsing position in the string
 652:     int stop = start + this.maximumIntegerDigits + maximumFractionDigits + 2;
 653:     
 654:     if (useExponentialNotation)
 655:       stop += minExponentDigits + 1;
 656:     
 657:     boolean inExponent = false;
 658: 
 659:     // correct the size of the end parsing flag
 660:     int len = str.length();
 661:     if (len < stop) stop = len;
 662:     char groupingSeparator = symbols.getGroupingSeparator();
 663:     
 664:     int i = start;
 665:     while (i < stop)
 666:       {
 667:         char ch = str.charAt(i);
 668:         i++;
 669:        
 670:         if (ch >= zero && ch <= (zero + 9))
 671:           {
 672:             number.append(ch);
 673:           }
 674:         else if (this.parseIntegerOnly)
 675:           {
 676:             i--;
 677:             break;
 678:           }
 679:         else if (ch == decimalSeparator)
 680:           {
 681:             number.append('.');
 682:           }
 683:         else if (ch == exponent)
 684:           {
 685:             number.append(ch);
 686:             inExponent = !inExponent;
 687:           }
 688:         else if ((ch == '+' || ch == '-' || ch == minus))
 689:           {
 690:             if (inExponent)
 691:               number.append(ch);
 692:             else
 693:           {
 694:         i--;
 695:             break;
 696:           }
 697:           }
 698:     else
 699:       {
 700:         if (!groupingUsed || ch != groupingSeparator)
 701:           {
 702:             i--;
 703:             break;
 704:           }
 705:       }
 706:       }
 707: 
 708:     // 2nd special case: infinity
 709:     // XXX: need to be tested
 710:     if (str.contains(symbols.getInfinity()))
 711:       {
 712:         int inf = str.indexOf(symbols.getInfinity()); 
 713:         pos.setIndex(inf);
 714:         
 715:         // FIXME: ouch, this is really ugly and lazy code...
 716:         if (this.parseBigDecimal)
 717:           {
 718:             if (isNegative)
 719:               return new BigDecimal(Double.NEGATIVE_INFINITY);
 720:             
 721:             return new BigDecimal(Double.POSITIVE_INFINITY);
 722:           }
 723:         
 724:         if (isNegative)
 725:           return new Double(Double.NEGATIVE_INFINITY);
 726: 
 727:         return new Double(Double.POSITIVE_INFINITY);
 728:       }
 729:     
 730:     // no number...
 731:     if (i == start || number.length() == 0)
 732:       {
 733:         pos.setErrorIndex(i);
 734:         return null;
 735:       }
 736: 
 737:     // now we have to check the suffix, done here after number parsing
 738:     // or the index will not be updated correctly...
 739:     boolean hasNegativeSuffix = str.endsWith(this.negativeSuffix);
 740:     boolean hasPositiveSuffix = str.endsWith(this.positiveSuffix);
 741:     boolean positiveEqualsNegative = negativeSuffix.equals(positiveSuffix);
 742: 
 743:     positiveLen = positiveSuffix.length();
 744:     negativeLen = negativeSuffix.length();
 745:     
 746:     if (isNegative && !hasNegativeSuffix)
 747:       {
 748:         pos.setErrorIndex(i);
 749:         return null;
 750:       }
 751:     else if (hasNegativeSuffix &&
 752:              !positiveEqualsNegative &&
 753:              (negativeLen > positiveLen))
 754:       {
 755:         isNegative = true;
 756:       }
 757:     else if (!hasPositiveSuffix)
 758:       {
 759:         pos.setErrorIndex(i);
 760:         return null;
 761:       }
 762:     
 763:     if (isNegative) number.insert(0, '-');
 764:    
 765:     pos.setIndex(i);
 766:     
 767:     // now we handle the return type
 768:     BigDecimal bigDecimal = new BigDecimal(number.toString());
 769:     if (this.parseBigDecimal)
 770:       return bigDecimal;
 771:     
 772:     // want integer?
 773:     if (this.parseIntegerOnly)
 774:       return new Long(bigDecimal.longValue());
 775: 
 776:     // 3th special case -0.0
 777:     if (isNegative && (bigDecimal.compareTo(BigDecimal.ZERO) == 0))
 778:       return new Double(-0.0);
 779:     
 780:     try
 781:       {
 782:         BigDecimal integer
 783:           = bigDecimal.setScale(0, BigDecimal.ROUND_UNNECESSARY);
 784:         return new Long(integer.longValue());
 785:       }
 786:     catch (ArithmeticException e)
 787:       {
 788:         return new Double(bigDecimal.doubleValue());
 789:       }
 790:   }
 791: 
 792:   /**
 793:    * Sets the <code>Currency</code> on the
 794:    * <code>DecimalFormatSymbols</code> used, which also sets the
 795:    * currency symbols on those symbols.
 796:    * 
 797:    * @param currency The new <code>Currency</code> on the
 798:    * <code>DecimalFormatSymbols</code>.
 799:    */
 800:   public void setCurrency(Currency currency)
 801:   {
 802:     symbols.setCurrency(currency);
 803:   }
 804:   
 805:   /**
 806:    * Sets the symbols used by this instance.  This method makes a copy of 
 807:    * the supplied symbols.
 808:    * 
 809:    * @param newSymbols  the symbols (<code>null</code> not permitted).
 810:    */
 811:   public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)
 812:   {
 813:     symbols = (DecimalFormatSymbols) newSymbols.clone();
 814:   }
 815:   
 816:   /**
 817:    * Define if the decimal separator should be always visible or only
 818:    * visible when needed. This method as effect only on integer values.
 819:    * Pass <code>true</code> if you want the decimal separator to be
 820:    * always shown, <code>false</code> otherwise.
 821:    * 
 822:    * @param newValue true</code> if you want the decimal separator to be
 823:    * always shown, <code>false</code> otherwise.
 824:    */
 825:   public void setDecimalSeparatorAlwaysShown(boolean newValue)
 826:   {
 827:     decimalSeparatorAlwaysShown = newValue;
 828:   }
 829:   
 830:   /**
 831:    * Sets the number of digits used to group portions of the integer part of
 832:    * the number. For example, the number <code>123456</code>, with a grouping
 833:    * size of 3, is rendered <code>123,456</code>.
 834:    * 
 835:    * @param groupSize The number of digits used while grouping portions
 836:    * of the integer part of a number.
 837:    */
 838:   public void setGroupingSize(int groupSize)
 839:   {
 840:     groupingSize = (byte) groupSize;
 841:   }
 842:   
 843:   /**
 844:    * Sets the maximum number of digits allowed in the integer
 845:    * portion of a number to the specified value.
 846:    * The new value will be the choosen as the minimum between
 847:    * <code>newvalue</code> and 309. Any value below zero will be
 848:    * replaced by zero.
 849:    * 
 850:    * @param newValue The new maximum integer digits value.
 851:    */
 852:   public void setMaximumIntegerDigits(int newValue)
 853:   {
 854:     newValue = (newValue > 0) ? newValue : 0;
 855:     super.setMaximumIntegerDigits(Math.min(newValue, DEFAULT_INTEGER_DIGITS));
 856:   }
 857:   
 858:   /**
 859:    * Sets the minimum number of digits allowed in the integer
 860:    * portion of a number to the specified value.
 861:    * The new value will be the choosen as the minimum between
 862:    * <code>newvalue</code> and 309. Any value below zero will be
 863:    * replaced by zero.
 864:    * 
 865:    * @param newValue The new minimum integer digits value.
 866:    */
 867:   public void setMinimumIntegerDigits(int newValue)
 868:   {
 869:     newValue = (newValue > 0) ? newValue : 0;
 870:     super.setMinimumIntegerDigits(Math.min(newValue,  DEFAULT_INTEGER_DIGITS));
 871:   }
 872:   
 873:   /**
 874:    * Sets the maximum number of digits allowed in the fraction
 875:    * portion of a number to the specified value.
 876:    * The new value will be the choosen as the minimum between
 877:    * <code>newvalue</code> and 309. Any value below zero will be
 878:    * replaced by zero.
 879:    * 
 880:    * @param newValue The new maximum fraction digits value.
 881:    */
 882:   public void setMaximumFractionDigits(int newValue)
 883:   {
 884:     newValue = (newValue > 0) ? newValue : 0;
 885:     super.setMaximumFractionDigits(Math.min(newValue, DEFAULT_FRACTION_DIGITS));
 886:   }
 887:   
 888:   /**
 889:    * Sets the minimum number of digits allowed in the fraction
 890:    * portion of a number to the specified value.
 891:    * The new value will be the choosen as the minimum between
 892:    * <code>newvalue</code> and 309. Any value below zero will be
 893:    * replaced by zero.
 894:    * 
 895:    * @param newValue The new minimum fraction digits value.
 896:    */
 897:   public void setMinimumFractionDigits(int newValue)
 898:   {
 899:     newValue = (newValue > 0) ? newValue : 0;
 900:     super.setMinimumFractionDigits(Math.min(newValue, DEFAULT_FRACTION_DIGITS));
 901:   }
 902:   
 903:   /**
 904:    * Sets the multiplier for use in percent and similar formats.
 905:    * For example, for percent set the multiplier to 100, for permille, set the
 906:    * miltiplier to 1000.
 907:    * 
 908:    * @param newValue the new value for multiplier.
 909:    */
 910:   public void setMultiplier