Source for java.text.DecimalFormatSymbols

   1: /* DecimalFormatSymbols.java -- Format symbols used by DecimalFormat
   2:    Copyright (C) 1999, 2000, 2001, 2004 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: package java.text;
  40: 
  41: import java.io.IOException;
  42: import java.io.ObjectInputStream;
  43: import java.io.Serializable;
  44: import java.util.Currency;
  45: import java.util.Locale;
  46: import java.util.MissingResourceException;
  47: import java.util.ResourceBundle;
  48: 
  49: /**
  50:  * This class is a container for the symbols used by 
  51:  * <code>DecimalFormat</code> to format numbers and currency
  52:  * for a particular locale.  These are
  53:  * normally handled automatically, but an application can override
  54:  * values as desired using this class.
  55:  *
  56:  * @author Tom Tromey (tromey@cygnus.com)
  57:  * @author Aaron M. Renn (arenn@urbanophile.com)
  58:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  59:  * @date February 24, 1999
  60:  * @see java.text.DecimalFormat
  61:  */
  62: /* Written using "Java Class Libraries", 2nd edition, plus online
  63:  * API docs for JDK 1.2 from http://www.javasoft.com.
  64:  * Status:  Believed complete and correct to 1.2.
  65:  */
  66: public final class DecimalFormatSymbols implements Cloneable, Serializable
  67: {
  68:   public Object clone ()
  69:   {
  70:     try
  71:       {
  72:     return super.clone ();
  73:       }
  74:     catch(CloneNotSupportedException e)
  75:       {
  76:     return null;
  77:       }
  78:   }
  79: 
  80:   /**
  81:    * This method initializes a new instance of
  82:    * <code>DecimalFormatSymbols</code> for the default locale.
  83:    */
  84:   public DecimalFormatSymbols ()
  85:   {
  86:     this (Locale.getDefault());
  87:   }
  88: 
  89:   /**
  90:    * Retrieves a valid string, either using the supplied resource
  91:    * bundle or the default value.
  92:    *
  93:    * @param bundle the resource bundle to use to find the string.
  94:    * @param name key for the string in the resource bundle.
  95:    * @param def default value for the string.
  96:    */
  97:   private String safeGetString(ResourceBundle bundle,
  98:                                String name, String def)
  99:   {
 100:     if (bundle != null)
 101:       {
 102:     try
 103:       {
 104:         return bundle.getString(name);
 105:       }
 106:     catch (MissingResourceException x)
 107:       {
 108:       }
 109:       }
 110:     return def;
 111:   }
 112: 
 113:   private char safeGetChar(ResourceBundle bundle,
 114:                            String name, char def)
 115:   {
 116:     String r = null;
 117:     if (bundle != null)
 118:       {
 119:     try
 120:       {
 121:         r = bundle.getString(name);
 122:       }
 123:     catch (MissingResourceException x)
 124:       {
 125:       }
 126:       }
 127:     if (r == null || r.length() < 1)
 128:       return def;
 129:     return r.charAt(0);
 130:   }
 131: 
 132:   /**
 133:    * This method initializes a new instance of
 134:    * <code>DecimalFormatSymbols</code> for the specified locale.
 135:    * <strong>Note</strong>: if the locale does not have an associated
 136:    * <code>Currency</code> instance, the currency symbol and
 137:    * international currency symbol will be set to the strings "?"
 138:    * and "XXX" respectively.  This generally happens with language
 139:    * locales (those with no specified country), such as
 140:    * <code>Locale.ENGLISH</code>.
 141:    *
 142:    * @param loc The local to load symbols for.
 143:    * @throws NullPointerException if the locale is null.
 144:    */
 145:   public DecimalFormatSymbols (Locale loc)
 146:   {
 147:     ResourceBundle res;
 148: 
 149:     currency = Currency.getInstance("XXX");
 150:     currencySymbol = "?";
 151:     intlCurrencySymbol = "XXX";
 152:     try
 153:       {
 154:     res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
 155:         loc, ClassLoader.getSystemClassLoader());
 156:       }
 157:     catch (MissingResourceException x)
 158:       {
 159:     res = null;
 160:       }
 161:     try
 162:       {
 163:     Currency localeCurrency = Currency.getInstance(loc);
 164:     if (localeCurrency != null)
 165:       {
 166:         setCurrency(localeCurrency);
 167:       }
 168:       }
 169:     catch(IllegalArgumentException exception)
 170:       {
 171:     /* Locale has an invalid currency */
 172:       }
 173:     decimalSeparator = safeGetChar (res, "decimalSeparator", '.');
 174:     digit = safeGetChar (res, "digit", '#');
 175:     exponential = safeGetChar (res, "exponential", 'E');
 176:     groupingSeparator = safeGetChar (res, "groupingSeparator", ',');
 177:     infinity = safeGetString (res, "infinity", "\u221e");
 178:     try
 179:       {
 180:     monetarySeparator = safeGetChar (res, "monetarySeparator", '.');
 181:       }
 182:     catch (MissingResourceException x)
 183:       {
 184:     monetarySeparator = decimalSeparator;
 185:       }
 186:     minusSign = safeGetChar (res, "minusSign", '-');
 187:     NaN = safeGetString (res, "NaN", "\ufffd");
 188:     patternSeparator = safeGetChar (res, "patternSeparator", ';');
 189:     percent = safeGetChar (res, "percent", '%');
 190:     perMill = safeGetChar (res, "perMill", '\u2030');
 191:     zeroDigit = safeGetChar (res, "zeroDigit", '0');
 192:     locale = loc;
 193:   }
 194: 
 195:   /**
 196:    * This method this this object for equality against the specified object.
 197:    * This will be true if and only if the following criteria are met with
 198:    * regard to the specified object:
 199:    * <p>
 200:    * <ul>
 201:    * <li>It is not <code>null</code>.</li>
 202:    * <li>It is an instance of <code>DecimalFormatSymbols</code>.</li>
 203:    * <li>All of its symbols are identical to the symbols in this object.</li>
 204:    * </ul>
 205:    *
 206:    * @return <code>true</code> if the specified object is equal to this
 207:    * object, <code>false</code> otherwise.
 208:    */
 209:   public boolean equals (Object obj)
 210:   {
 211:     if (! (obj instanceof DecimalFormatSymbols))
 212:       return false;
 213:     DecimalFormatSymbols dfs = (DecimalFormatSymbols) obj;
 214:     return (currencySymbol.equals(dfs.currencySymbol)
 215:         && decimalSeparator == dfs.decimalSeparator
 216:         && digit == dfs.digit
 217:         && exponential == dfs.exponential
 218:         && groupingSeparator == dfs.groupingSeparator
 219:         && infinity.equals(dfs.infinity)
 220:         && intlCurrencySymbol.equals(dfs.intlCurrencySymbol)
 221:         && minusSign == dfs.minusSign
 222:         && monetarySeparator == dfs.monetarySeparator
 223:         && NaN.equals(dfs.NaN)
 224:         && patternSeparator == dfs.patternSeparator
 225:         && percent == dfs.percent
 226:         && perMill == dfs.perMill
 227:         && zeroDigit == dfs.zeroDigit);
 228:   }
 229: 
 230:   /**
 231:    * Returns the currency corresponding to the currency symbol stored
 232:    * in this instance of <code>DecimalFormatSymbols</code>.
 233:    *
 234:    * @return An instance of <code>Currency</code> which matches
 235:    *         the currency used, or null if there is no corresponding
 236:    *         instance.
 237:    */
 238:   public Currency getCurrency ()
 239:   {
 240:     return currency;
 241:   }
 242: 
 243:   /**
 244:    * This method returns the currency symbol in local format.  For example,
 245:    * "$" for Canadian dollars.
 246:    *
 247:    * @return The currency symbol in local format.
 248:    */
 249:   public String getCurrencySymbol ()
 250:   {
 251:     return currencySymbol;
 252:   }
 253: 
 254:   /**
 255:    * This method returns the character used as the decimal point.
 256:    *
 257:    * @return The character used as the decimal point.
 258:    */
 259:   public char getDecimalSeparator ()
 260:   {
 261:     return decimalSeparator;
 262:   }
 263: 
 264:   /**
 265:    * This method returns the character used to represent a digit in a
 266:    * format pattern string.
 267:    *
 268:    * @return The character used to represent a digit in a format
 269:    * pattern string. 
 270:    */
 271:   public char getDigit ()
 272:   {
 273:     return digit;
 274:   }
 275: 
 276:   /**
 277:    * This method returns the character used to represent the exponential
 278:    * format.  This is a GNU Classpath extension.
 279:    *
 280:    * @return the character used to represent an exponential in a format
 281:    *         pattern string.
 282:    */
 283:   char getExponential ()
 284:   {
 285:     return exponential;
 286:   }
 287: 
 288:   /**
 289:    * This method sets the character used to separate groups of digits.  For
 290:    * example, the United States uses a comma (,) to separate thousands in
 291:    * a number.
 292:    *
 293:    * @return The character used to separate groups of digits.
 294:    */
 295:   public char getGroupingSeparator ()
 296:   {
 297:     return groupingSeparator;
 298:   }
 299: 
 300:   /**
 301:    * This method returns the character used to represent infinity.
 302:    *
 303:    * @return The character used to represent infinity.
 304:    */
 305:   public String getInfinity ()
 306:   {
 307:     return infinity;
 308:   }
 309: 
 310:   /**
 311:    * This method returns the ISO 4217 currency code for
 312:    * the currency used.
 313:    *
 314:    * @return the ISO 4217 currency code.
 315:    */
 316:   public String getInternationalCurrencySymbol ()
 317:   {
 318:     return intlCurrencySymbol;
 319:   }
 320: 
 321:   /**
 322:    * This method returns the character used to represent the minus sign.
 323:    *
 324:    * @return The character used to represent the minus sign.
 325:    */
 326:   public char getMinusSign ()
 327:   {
 328:     return minusSign;
 329:   }
 330: 
 331:   /**
 332:    * This method returns the character used to represent the decimal
 333:    * point for currency values.
 334:    *
 335:    * @return The decimal point character used in currency values.
 336:    */
 337:   public char getMonetaryDecimalSeparator ()
 338:   {
 339:     return monetarySeparator;
 340:   }
 341: 
 342:   /**
 343:    * This method returns the string used to represent the NaN (not a number)
 344:    * value.
 345:    *
 346:    * @return The string used to represent NaN
 347:    */
 348:   public String getNaN ()
 349:   {
 350:     return NaN;
 351:   }
 352: 
 353:   /**
 354:    * This method returns the character used to separate positive and negative
 355:    * subpatterns in a format pattern.
 356:    *
 357:    * @return The character used to separate positive and negative subpatterns
 358:    * in a format pattern.
 359:    */
 360:   public char getPatternSeparator ()
 361:   {
 362:     return patternSeparator;
 363:   }
 364: 
 365:   /**
 366:    * This method returns the character used as the percent sign.
 367:    *
 368:    * @return The character used as the percent sign.
 369:    */
 370:   public char getPercent ()
 371:   {
 372:     return percent;
 373:   }
 374: 
 375:   /**
 376:    * This method returns the character used as the per mille character.
 377:    *
 378:    * @return The per mille character.
 379:    */
 380:   public char getPerMill ()
 381:   {
 382:     return perMill;
 383:   }
 384: 
 385:   /**
 386:    * This method returns the character used to represent the digit zero.
 387:    *
 388:    * @return The character used to represent the digit zero.
 389:    */
 390:   public char getZeroDigit ()
 391:   {
 392:     return zeroDigit;
 393:   }
 394: 
 395:   /**
 396:    * This method returns a hash value for this object.
 397:    *
 398:    * @return A hash value for this object.
 399:    */
 400:   public int hashCode ()
 401:   {
 402:     // Compute based on zero digit, grouping separator, and decimal
 403:     // separator -- JCL book.  This probably isn't a very good hash
 404:     // code.
 405:     return zeroDigit << 16 + groupingSeparator << 8 + decimalSeparator;
 406:   }
 407: 
 408:   /**
 409:    * This method sets the currency symbol and ISO 4217 currency
 410:    * code to the values obtained from the supplied currency.
 411:    *
 412:    * @param currency the currency from which to obtain the values.
 413:    * @throws NullPointerException if the currency is null.
 414:    */
 415:   public void setCurrency (Currency currency)
 416:   {
 417:     intlCurrencySymbol = currency.getCurrencyCode();
 418:     currencySymbol = currency.getSymbol();
 419:     this.currency = currency;
 420:   }
 421: 
 422:   /**
 423:    * This method sets the currency symbol to the specified value.
 424:    *
 425:    * @param currency The new currency symbol
 426:    */
 427:   public void setCurrencySymbol (String currency)
 428:   {
 429:     currencySymbol = currency;
 430:   }
 431: 
 432:   /**
 433:    * This method sets the decimal point character to the specified value.
 434:    *
 435:    * @param decimalSep The new decimal point character
 436:    */
 437:   public void setDecimalSeparator (char decimalSep)
 438:   {
 439:     decimalSeparator = decimalSep;
 440:   }
 441: 
 442:   /**
 443:    * This method sets the character used to represents a digit in a format
 444:    * string to the specified value.
 445:    *
 446:    * @param digit The character used to represent a digit in a format pattern.
 447:    */
 448:   public void setDigit (char digit)
 449:   {
 450:     this.digit = digit;
 451:   }
 452: 
 453:   /**
 454:    * This method sets the exponential character used in the format string to
 455:    * the specified value.  This is a GNU Classpath extension.
 456:    *
 457:    * @param exp the character used for the exponential in a format pattern.
 458:    */
 459:   void setExponential (char exp)
 460:   {
 461:     exponential = exp;
 462:   }
 463: 
 464:   /**
 465:    * This method sets the character used to separate groups of digits.
 466:    *
 467:    * @param groupSep The character used to separate groups of digits.
 468:    */
 469:   public void setGroupingSeparator (char groupSep)
 470:   {
 471:     groupingSeparator = groupSep;
 472:   }
 473: 
 474:   /**
 475:    * This method sets the string used to represents infinity.
 476:    *
 477:    * @param infinity The string used to represent infinity.
 478:    */
 479:   public void setInfinity (String infinity)
 480:   {
 481:     this.infinity = infinity;
 482:   }
 483: 
 484:   /**
 485:    * This method sets the international currency symbol to the
 486:    * specified value. If a valid <code>Currency</code> instance
 487:    * exists for the international currency code, then this is
 488:    * used for the currency attribute, and the currency symbol
 489:    * is set to the corresponding value from this instance.
 490:    * Otherwise, the currency attribute is set to null and the
 491:    * symbol is left unmodified. 
 492:    *
 493:    * @param currencyCode The new international currency symbol.
 494:    */
 495:   public void setInternationalCurrencySymbol (String currencyCode)
 496:   {
 497:     intlCurrencySymbol = currencyCode;
 498:     try
 499:       {
 500:     currency = Currency.getInstance(currencyCode);
 501:       }
 502:     catch (IllegalArgumentException exception)
 503:       {
 504:     currency = null;
 505:       }
 506:     if (currency != null)
 507:       {
 508:         setCurrencySymbol(currency.getSymbol(locale));
 509:       }
 510:   }
 511: 
 512:   /**
 513:    * This method sets the character used to represent the minus sign.
 514:    *
 515:    * @param minusSign The character used to represent the minus sign.
 516:    */
 517:   public void setMinusSign (char minusSign)
 518:   {
 519:     this.minusSign = minusSign;
 520:   }
 521: 
 522:   /**
 523:    * This method sets the character used for the decimal point in currency
 524:    * values.
 525:    *
 526:    * @param decimalSep The decimal point character used in currency values. 
 527:    */
 528:   public void setMonetaryDecimalSeparator (char decimalSep)
 529:   {
 530:     monetarySeparator = decimalSep;
 531:   }
 532: 
 533:   /**
 534:    * This method sets the string used to represent the NaN (not a
 535:    * number) value. 
 536:    *
 537:    * @param nan The string used to represent NaN
 538:    */
 539:   public void setNaN (String nan)
 540:   {
 541:     NaN = nan;
 542:   }
 543: 
 544:   /**
 545:    * This method sets the character used to separate positive and negative
 546:    * subpatterns in a format pattern.
 547:    *
 548:    * @param patternSep The character used to separate positive and
 549:    * negative subpatterns in a format pattern.
 550:    */
 551:   public void setPatternSeparator (char patternSep)
 552:   {
 553:     patternSeparator = patternSep;
 554:   }
 555: 
 556:   /**
 557:    * This method sets the character used as the percent sign.
 558:    *
 559:    * @param percent  The character used as the percent sign.
 560:    */
 561:   public void setPercent (char percent)
 562:   {
 563:     this.percent = percent;
 564:   }
 565: 
 566:   /**
 567:    * This method sets the character used as the per mille character.
 568:    *
 569:    * @param perMill The per mille character.
 570:    */
 571:   public void setPerMill (char perMill)
 572:   {
 573:     this.perMill = perMill;
 574:   }
 575: 
 576:   /**
 577:    * This method sets the character used to represent the digit zero.
 578:    *
 579:    * @param zeroDigit The character used to represent the digit zero.
 580:    */
 581:   public void setZeroDigit (char zeroDigit)
 582:   {
 583:     this.zeroDigit = zeroDigit;
 584:   }
 585: 
 586:   /**
 587:    * @serial A string used for the local currency
 588:    */
 589:   private String currencySymbol;
 590:   /**
 591:    * @serial The <code>char</code> used to separate decimals in a number.
 592:    */
 593:   private char decimalSeparator;
 594:   /**
 595:    * @serial This is the <code>char</code> used to represent a digit in
 596:    * a format specification.
 597:    */
 598:   private char digit;
 599:   /**
 600:    * @serial This is the <code>char</code> used to represent the exponent
 601:    * separator in exponential notation.
 602:    */
 603:   private char exponential;
 604:   /**
 605:    * @serial This separates groups of thousands in numbers.
 606:    */
 607:   private char groupingSeparator;
 608:   /**
 609:    * @serial This string represents infinity.
 610:    */
 611:   private String infinity;
 612:   /**
 613:    * @serial This string represents the local currency in an international
 614:    * context, eg, "C$" for Canadian dollars.
 615:    */
 616:   private String intlCurrencySymbol;
 617:   /**
 618:    * @serial This is the character used to represent the minus sign.
 619:    */
 620:   private char minusSign;
 621:   /**
 622:    * @serial This character is used to separate decimals when formatting
 623:    * currency values.
 624:    */
 625:   private char monetarySeparator;
 626:   /**
 627:    * @serial This string is used the represent the Java NaN value for
 628:    * "not a number".
 629:    */
 630:   private String NaN;
 631:   /**
 632:    * @serial This is the character used to separate positive and negative
 633:    * subpatterns in a format pattern.
 634:    */
 635:   private char patternSeparator;
 636:   /**
 637:    * @serial This is the percent symbols
 638:    */
 639:   private char percent;
 640:   /**
 641:    * @serial This character is used for the mille percent sign.
 642:    */
 643:   private char perMill;
 644:   /**
 645:    * @serial This value represents the type of object being de-serialized.
 646:    * 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later.
 647:    * 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later,
 648:    * 2 indicates 1.4 or later
 649:     */
 650:   private int serialVersionOnStream = 2;
 651:   /**
 652:    * @serial This is the character used to represent 0.
 653:    */
 654:   private char zeroDigit;
 655: 
 656:   /**
 657:    * @serial The locale of these currency symbols.
 658:    */
 659:   private Locale locale;
 660: 
 661:   /**
 662:    * The currency used for the symbols in this instance.
 663:    * This is stored temporarily for efficiency reasons,
 664:    * as well as to ensure that the correct instance
 665:    * is restored from the currency code.
 666:    *
 667:    * @serial Ignored.
 668:    */
 669:   private transient Currency currency;
 670: 
 671:   private static final long serialVersionUID = 5772796243397350300L;
 672: 
 673:   private void readObject(ObjectInputStream stream)
 674:     throws IOException, ClassNotFoundException
 675:   {
 676:     stream.defaultReadObject();
 677:     if (serialVersionOnStream < 1)
 678:       {
 679:         monetarySeparator = decimalSeparator;
 680:     exponential = 'E';
 681:       }
 682:     if (serialVersionOnStream < 2)
 683:     locale = Locale.getDefault();
 684: 
 685:     serialVersionOnStream = 2;
 686:   }
 687: }