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