Source Code Cross Referenced for Currency.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.util;
027
028        import java.io.BufferedInputStream;
029        import java.io.DataInputStream;
030        import java.io.File;
031        import java.io.FileInputStream;
032        import java.io.FileReader;
033        import java.io.IOException;
034        import java.io.Serializable;
035        import java.security.AccessController;
036        import java.security.PrivilegedAction;
037        import java.util.logging.Level;
038        import java.util.logging.Logger;
039        import java.util.regex.Pattern;
040        import java.util.regex.Matcher;
041        import java.util.spi.CurrencyNameProvider;
042        import java.util.spi.LocaleServiceProvider;
043        import sun.util.LocaleServiceProviderPool;
044        import sun.util.resources.LocaleData;
045        import sun.util.resources.OpenListResourceBundle;
046
047        /**
048         * Represents a currency. Currencies are identified by their ISO 4217 currency
049         * codes. Visit the <a href="http://www.bsi-global.com/">
050         * BSi web site</a> for more information, including a table of
051         * currency codes.
052         * <p>
053         * The class is designed so that there's never more than one
054         * <code>Currency</code> instance for any given currency. Therefore, there's
055         * no public constructor. You obtain a <code>Currency</code> instance using
056         * the <code>getInstance</code> methods.
057         * <p>
058         * Users can supersede the Java runtime currency data by creating a properties 
059         * file named <code>&lt;JAVA_HOME&gt;/lib/currency.properties</code>.  The contents 
060         * of the properties file are key/value pairs of the ISO 3166 country codes 
061         * and the ISO 4217 currency data respectively.  The value part consists of 
062         * three ISO 4217 values of a currency, i.e., an alphabetic code, a numeric 
063         * code, and a minor unit.  Those three ISO 4217 values are separated by commas.  
064         * The lines which start with '#'s are considered comment lines.  For example,
065         * <p> 
066         * <code>
067         * #Sample currency properties<br>
068         * JP=JPZ,999,0
069         * </code>
070         * <p>
071         * will supersede the currency data for Japan.
072         *
073         * @since 1.4
074         */
075        public final class Currency implements  Serializable {
076
077            private static final long serialVersionUID = -158308464356906721L;
078
079            /**
080             * ISO 4217 currency code for this currency.
081             *
082             * @serial
083             */
084            private final String currencyCode;
085
086            /**
087             * Default fraction digits for this currency.
088             * Set from currency data tables.
089             */
090            transient private final int defaultFractionDigits;
091
092            /**
093             * ISO 4217 numeric code for this currency.
094             * Set from currency data tables.
095             */
096            transient private final int numericCode;
097
098            // class data: instance map
099
100            private static HashMap<String, Currency> instances = new HashMap<String, Currency>(
101                    7);
102            private static HashSet<Currency> available;
103
104            // Class data: currency data obtained from currency.data file.
105            // Purpose:
106            // - determine valid country codes
107            // - determine valid currency codes
108            // - map country codes to currency codes
109            // - obtain default fraction digits for currency codes
110            //
111            // sc = special case; dfd = default fraction digits
112            // Simple countries are those where the country code is a prefix of the
113            // currency code, and there are no known plans to change the currency.
114            //
115            // table formats:
116            // - mainTable:
117            //   - maps country code to 32-bit int
118            //   - 26*26 entries, corresponding to [A-Z]*[A-Z]
119            //   - \u007F -> not valid country
120            //   - bits 18-31: unused
121            //   - bits 8-17: numeric code (0 to 1023) 
122            //   - bit 7: 1 - special case, bits 0-4 indicate which one
123            //            0 - simple country, bits 0-4 indicate final char of currency code
124            //   - bits 5-6: fraction digits for simple countries, 0 for special cases
125            //   - bits 0-4: final char for currency code for simple country, or ID of special case
126            // - special case IDs:
127            //   - 0: country has no currency
128            //   - other: index into sc* arrays + 1
129            // - scCutOverTimes: cut-over time in millis as returned by
130            //   System.currentTimeMillis for special case countries that are changing
131            //   currencies; Long.MAX_VALUE for countries that are not changing currencies
132            // - scOldCurrencies: old currencies for special case countries
133            // - scNewCurrencies: new currencies for special case countries that are
134            //   changing currencies; null for others
135            // - scOldCurrenciesDFD: default fraction digits for old currencies
136            // - scNewCurrenciesDFD: default fraction digits for new currencies, 0 for
137            //   countries that are not changing currencies
138            // - otherCurrencies: concatenation of all currency codes that are not the
139            //   main currency of a simple country, separated by "-"
140            // - otherCurrenciesDFD: decimal format digits for currencies in otherCurrencies, same order
141
142            static int formatVersion;
143            static int dataVersion;
144            static int[] mainTable;
145            static long[] scCutOverTimes;
146            static String[] scOldCurrencies;
147            static String[] scNewCurrencies;
148            static int[] scOldCurrenciesDFD;
149            static int[] scNewCurrenciesDFD;
150            static int[] scOldCurrenciesNumericCode;
151            static int[] scNewCurrenciesNumericCode;
152            static String otherCurrencies;
153            static int[] otherCurrenciesDFD;
154            static int[] otherCurrenciesNumericCode;
155
156            // handy constants - must match definitions in GenerateCurrencyData
157            // magic number
158            private static final int MAGIC_NUMBER = 0x43757244;
159            // number of characters from A to Z
160            private static final int A_TO_Z = ('Z' - 'A') + 1;
161            // entry for invalid country codes
162            private static final int INVALID_COUNTRY_ENTRY = 0x007F;
163            // entry for countries without currency
164            private static final int COUNTRY_WITHOUT_CURRENCY_ENTRY = 0x0080;
165            // mask for simple case country entries
166            private static final int SIMPLE_CASE_COUNTRY_MASK = 0x0000;
167            // mask for simple case country entry final character
168            private static final int SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK = 0x001F;
169            // mask for simple case country entry default currency digits
170            private static final int SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK = 0x0060;
171            // shift count for simple case country entry default currency digits
172            private static final int SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT = 5;
173            // mask for special case country entries
174            private static final int SPECIAL_CASE_COUNTRY_MASK = 0x0080;
175            // mask for special case country index
176            private static final int SPECIAL_CASE_COUNTRY_INDEX_MASK = 0x001F;
177            // delta from entry index component in main table to index into special case tables
178            private static final int SPECIAL_CASE_COUNTRY_INDEX_DELTA = 1;
179            // mask for distinguishing simple and special case countries
180            private static final int COUNTRY_TYPE_MASK = SIMPLE_CASE_COUNTRY_MASK
181                    | SPECIAL_CASE_COUNTRY_MASK;
182            // mask for the numeric code of the currency
183            private static final int NUMERIC_CODE_MASK = 0x0003FF00;
184            // shift count for the numeric code of the currency
185            private static final int NUMERIC_CODE_SHIFT = 8;
186
187            // Currency data format version
188            private static final int VALID_FORMAT_VERSION = 1;
189
190            static {
191                AccessController.doPrivileged(new PrivilegedAction() {
192                    public Object run() {
193                        String homeDir = System.getProperty("java.home");
194                        try {
195                            String dataFile = homeDir + File.separator + "lib"
196                                    + File.separator + "currency.data";
197                            DataInputStream dis = new DataInputStream(
198                                    new BufferedInputStream(
199                                            new FileInputStream(dataFile)));
200                            if (dis.readInt() != MAGIC_NUMBER) {
201                                throw new InternalError(
202                                        "Currency data is possibly corrupted");
203                            }
204                            formatVersion = dis.readInt();
205                            if (formatVersion != VALID_FORMAT_VERSION) {
206                                throw new InternalError(
207                                        "Currency data format is incorrect");
208                            }
209                            dataVersion = dis.readInt();
210                            mainTable = readIntArray(dis, A_TO_Z * A_TO_Z);
211                            int scCount = dis.readInt();
212                            scCutOverTimes = readLongArray(dis, scCount);
213                            scOldCurrencies = readStringArray(dis, scCount);
214                            scNewCurrencies = readStringArray(dis, scCount);
215                            scOldCurrenciesDFD = readIntArray(dis, scCount);
216                            scNewCurrenciesDFD = readIntArray(dis, scCount);
217                            scOldCurrenciesNumericCode = readIntArray(dis,
218                                    scCount);
219                            scNewCurrenciesNumericCode = readIntArray(dis,
220                                    scCount);
221                            int ocCount = dis.readInt();
222                            otherCurrencies = dis.readUTF();
223                            otherCurrenciesDFD = readIntArray(dis, ocCount);
224                            otherCurrenciesNumericCode = readIntArray(dis,
225                                    ocCount);
226                            dis.close();
227                        } catch (IOException e) {
228                            InternalError ie = new InternalError();
229                            ie.initCause(e);
230                            throw ie;
231                        }
232
233                        // look for the properties file for overrides
234                        try {
235                            File propFile = new File(homeDir + File.separator
236                                    + "lib" + File.separator
237                                    + "currency.properties");
238                            if (propFile.exists()) {
239                                Properties props = new Properties();
240                                props.load(new FileReader(propFile));
241                                Set<String> keys = props.stringPropertyNames();
242                                Pattern propertiesPattern = Pattern
243                                        .compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*([0-3])");
244                                for (String key : keys) {
245                                    replaceCurrencyData(propertiesPattern, key
246                                            .toUpperCase(Locale.ROOT), props
247                                            .getProperty(key).toUpperCase(
248                                                    Locale.ROOT));
249                                }
250                            }
251                        } catch (IOException e) {
252                            log(
253                                    Level.INFO,
254                                    "currency.properties is ignored because of an IOException",
255                                    e);
256                        }
257                        return null;
258                    }
259                });
260            }
261
262            /**
263             * Constants for retrieving localized names from the name providers.
264             */
265            private static final int SYMBOL = 0;
266            private static final int DISPLAYNAME = 1;
267
268            /**
269             * Constructs a <code>Currency</code> instance. The constructor is private
270             * so that we can insure that there's never more than one instance for a
271             * given currency.
272             */
273            private Currency(String currencyCode, int defaultFractionDigits,
274                    int numericCode) {
275                this .currencyCode = currencyCode;
276                this .defaultFractionDigits = defaultFractionDigits;
277                this .numericCode = numericCode;
278            }
279
280            /**
281             * Returns the <code>Currency</code> instance for the given currency code.
282             *
283             * @param currencyCode the ISO 4217 code of the currency
284             * @return the <code>Currency</code> instance for the given currency code
285             * @exception NullPointerException if <code>currencyCode</code> is null
286             * @exception IllegalArgumentException if <code>currencyCode</code> is not
287             * a supported ISO 4217 code.
288             */
289            public static Currency getInstance(String currencyCode) {
290                return getInstance(currencyCode, Integer.MIN_VALUE, 0);
291            }
292
293            private static Currency getInstance(String currencyCode,
294                    int defaultFractionDigits, int numericCode) {
295                synchronized (instances) {
296                    // Try to look up the currency code in the instances table.
297                    // This does the null pointer check as a side effect.
298                    // Also, if there already is an entry, the currencyCode must be valid.
299                    Currency instance = instances.get(currencyCode);
300                    if (instance != null) {
301                        return instance;
302                    }
303
304                    if (defaultFractionDigits == Integer.MIN_VALUE) {
305                        // Currency code not internally generated, need to verify first
306                        // A currency code must have 3 characters and exist in the main table
307                        // or in the list of other currencies.
308                        if (currencyCode.length() != 3) {
309                            throw new IllegalArgumentException();
310                        }
311                        char char1 = currencyCode.charAt(0);
312                        char char2 = currencyCode.charAt(1);
313                        int tableEntry = getMainTableEntry(char1, char2);
314                        if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
315                                && tableEntry != INVALID_COUNTRY_ENTRY
316                                && currencyCode.charAt(2) - 'A' == (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK)) {
317                            defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
318                            numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
319                        } else {
320                            // Check for '-' separately so we don't get false hits in the table.
321                            if (currencyCode.charAt(2) == '-') {
322                                throw new IllegalArgumentException();
323                            }
324                            int index = otherCurrencies.indexOf(currencyCode);
325                            if (index == -1) {
326                                throw new IllegalArgumentException();
327                            }
328                            defaultFractionDigits = otherCurrenciesDFD[index / 4];
329                            numericCode = otherCurrenciesNumericCode[index / 4];
330                        }
331                    }
332
333                    instance = new Currency(currencyCode,
334                            defaultFractionDigits, numericCode);
335                    instances.put(currencyCode, instance);
336                    return instance;
337                }
338            }
339
340            /**
341             * Returns the <code>Currency</code> instance for the country of the
342             * given locale. The language and variant components of the locale
343             * are ignored. The result may vary over time, as countries change their
344             * currencies. For example, for the original member countries of the
345             * European Monetary Union, the method returns the old national currencies
346             * until December 31, 2001, and the Euro from January 1, 2002, local time
347             * of the respective countries.
348             * <p>
349             * The method returns <code>null</code> for territories that don't
350             * have a currency, such as Antarctica.
351             *
352             * @param locale the locale for whose country a <code>Currency</code>
353             * instance is needed
354             * @return the <code>Currency</code> instance for the country of the given
355             * locale, or null
356             * @exception NullPointerException if <code>locale</code> or its country
357             * code is null
358             * @exception IllegalArgumentException if the country of the given locale
359             * is not a supported ISO 3166 country code.
360             */
361            public static Currency getInstance(Locale locale) {
362                String country = locale.getCountry();
363                if (country == null) {
364                    throw new NullPointerException();
365                }
366
367                if (country.length() != 2) {
368                    throw new IllegalArgumentException();
369                }
370
371                char char1 = country.charAt(0);
372                char char2 = country.charAt(1);
373                int tableEntry = getMainTableEntry(char1, char2);
374                if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
375                        && tableEntry != INVALID_COUNTRY_ENTRY) {
376                    char finalChar = (char) ((tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) + 'A');
377                    int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
378                    int numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
379                    StringBuffer sb = new StringBuffer(country);
380                    sb.append(finalChar);
381                    return getInstance(sb.toString(), defaultFractionDigits,
382                            numericCode);
383                } else {
384                    // special cases
385                    if (tableEntry == INVALID_COUNTRY_ENTRY) {
386                        throw new IllegalArgumentException();
387                    }
388                    if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) {
389                        return null;
390                    } else {
391                        int index = (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK)
392                                - SPECIAL_CASE_COUNTRY_INDEX_DELTA;
393                        if (scCutOverTimes[index] == Long.MAX_VALUE
394                                || System.currentTimeMillis() < scCutOverTimes[index]) {
395                            return getInstance(scOldCurrencies[index],
396                                    scOldCurrenciesDFD[index],
397                                    scOldCurrenciesNumericCode[index]);
398                        } else {
399                            return getInstance(scNewCurrencies[index],
400                                    scNewCurrenciesDFD[index],
401                                    scNewCurrenciesNumericCode[index]);
402                        }
403                    }
404                }
405            }
406
407            /**
408             * Gets the set of available currencies.  The returned set of currencies
409             * contains all of the available currencies, which may include currencies
410             * that represent obsolete ISO 4217 codes.  The set can be modified
411             * without affecting the available currencies in the runtime.
412             *
413             * @return the set of available currencies.  If there is no currency
414             *    available in the runtime, the returned set is empty.
415             * @since 1.7
416             */
417            public static Set<Currency> getAvailableCurrencies() {
418                synchronized (Currency.class) {
419                    if (available == null) {
420                        available = new HashSet<Currency>(256);
421
422                        // Add simple currencies first
423                        for (char c1 = 'A'; c1 <= 'Z'; c1++) {
424                            for (char c2 = 'A'; c2 <= 'Z'; c2++) {
425                                int tableEntry = getMainTableEntry(c1, c2);
426                                if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
427                                        && tableEntry != INVALID_COUNTRY_ENTRY) {
428                                    char finalChar = (char) ((tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) + 'A');
429                                    int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
430                                    int numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
431                                    StringBuilder sb = new StringBuilder();
432                                    sb.append(c1);
433                                    sb.append(c2);
434                                    sb.append(finalChar);
435                                    available
436                                            .add(getInstance(sb.toString(),
437                                                    defaultFractionDigits,
438                                                    numericCode));
439                                }
440                            }
441                        }
442
443                        // Now add other currencies
444                        StringTokenizer st = new StringTokenizer(
445                                otherCurrencies, "-");
446                        while (st.hasMoreElements()) {
447                            available
448                                    .add(getInstance((String) st.nextElement()));
449                        }
450                    }
451                }
452
453                return (Set<Currency>) available.clone();
454            }
455
456            /**
457             * Gets the ISO 4217 currency code of this currency.
458             *
459             * @return the ISO 4217 currency code of this currency.
460             */
461            public String getCurrencyCode() {
462                return currencyCode;
463            }
464
465            /**
466             * Gets the symbol of this currency for the default locale.
467             * For example, for the US Dollar, the symbol is "$" if the default
468             * locale is the US, while for other locales it may be "US$". If no
469             * symbol can be determined, the ISO 4217 currency code is returned.
470             *
471             * @return the symbol of this currency for the default locale
472             */
473            public String getSymbol() {
474                return getSymbol(Locale.getDefault());
475            }
476
477            /**
478             * Gets the symbol of this currency for the specified locale.
479             * For example, for the US Dollar, the symbol is "$" if the specified
480             * locale is the US, while for other locales it may be "US$". If no
481             * symbol can be determined, the ISO 4217 currency code is returned.
482             *
483             * @param locale the locale for which a display name for this currency is
484             * needed
485             * @return the symbol of this currency for the specified locale
486             * @exception NullPointerException if <code>locale</code> is null
487             */
488            public String getSymbol(Locale locale) {
489                try {
490                    // Check whether a provider can provide an implementation that's closer 
491                    // to the requested locale than what the Java runtime itself can provide.
492                    LocaleServiceProviderPool pool = LocaleServiceProviderPool
493                            .getPool(CurrencyNameProvider.class);
494
495                    if (pool.hasProviders()) {
496                        // Assuming that all the country locales include necessary currency 
497                        // symbols in the Java runtime's resources,  so there is no need to
498                        // examine whether Java runtime's currency resource bundle is missing 
499                        // names.  Therefore, no resource bundle is provided for calling this 
500                        // method.
501                        String symbol = pool.getLocalizedObject(
502                                CurrencyNameGetter.INSTANCE, locale,
503                                (OpenListResourceBundle) null, currencyCode,
504                                SYMBOL);
505                        if (symbol != null) {
506                            return symbol;
507                        }
508                    }
509
510                    ResourceBundle bundle = LocaleData.getCurrencyNames(locale);
511                    return bundle.getString(currencyCode);
512                } catch (MissingResourceException e) {
513                    // use currency code as symbol of last resort
514                    return currencyCode;
515                }
516            }
517
518            /**
519             * Gets the default number of fraction digits used with this currency.
520             * For example, the default number of fraction digits for the Euro is 2,
521             * while for the Japanese Yen it's 0.
522             * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
523             * -1 is returned.
524             *
525             * @return the default number of fraction digits used with this currency
526             */
527            public int getDefaultFractionDigits() {
528                return defaultFractionDigits;
529            }
530
531            /**
532             * Returns the ISO 4217 numeric code of this currency.
533             *
534             * @return the ISO 4217 numeric code of this currency
535             * @since 1.7
536             */
537            public int getNumericCode() {
538                return numericCode;
539            }
540
541            /**
542             * Gets the name that is suitable for displaying this currency for 
543             * the default locale.  If there is no suitable display name found
544             * for the default locale, the ISO 4217 currency code is returned.
545             *
546             * @return the display name of this currency for the default locale
547             * @since 1.7
548             */
549            public String getDisplayName() {
550                return getDisplayName(Locale.getDefault());
551            }
552
553            /**
554             * Gets the name that is suitable for displaying this currency for 
555             * the specified locale.  If there is no suitable display name found
556             * for the specified locale, the ISO 4217 currency code is returned.
557             *
558             * @param locale the locale for which a display name for this currency is
559             * needed
560             * @return the display name of this currency for the specified locale
561             * @exception NullPointerException if <code>locale</code> is null
562             * @since 1.7
563             */
564            public String getDisplayName(Locale locale) {
565                try {
566                    OpenListResourceBundle bundle = LocaleData
567                            .getCurrencyNames(locale);
568                    String result = null;
569                    String bundleKey = currencyCode.toLowerCase(Locale.ROOT);
570
571                    // Check whether a provider can provide an implementation that's closer 
572                    // to the requested locale than what the Java runtime itself can provide.
573                    LocaleServiceProviderPool pool = LocaleServiceProviderPool
574                            .getPool(CurrencyNameProvider.class);
575                    if (pool.hasProviders()) {
576                        result = pool.getLocalizedObject(
577                                CurrencyNameGetter.INSTANCE, locale, bundleKey,
578                                bundle, currencyCode, DISPLAYNAME);
579                    }
580
581                    if (result == null) {
582                        result = bundle.getString(bundleKey);
583                    }
584
585                    if (result != null) {
586                        return result;
587                    }
588                } catch (MissingResourceException e) {
589                    // fall through
590                }
591
592                // use currency code as symbol of last resort
593                return currencyCode;
594            }
595
596            /**
597             * Returns the ISO 4217 currency code of this currency.
598             *
599             * @return the ISO 4217 currency code of this currency
600             */
601            public String toString() {
602                return currencyCode;
603            }
604
605            /**
606             * Resolves instances being deserialized to a single instance per currency.
607             */
608            private Object readResolve() {
609                return getInstance(currencyCode);
610            }
611
612            /**
613             * Gets the main table entry for the country whose country code consists
614             * of char1 and char2.
615             */
616            private static int getMainTableEntry(char char1, char char2) {
617                if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') {
618                    throw new IllegalArgumentException();
619                }
620                return mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')];
621            }
622
623            /**
624             * Sets the main table entry for the country whose country code consists
625             * of char1 and char2.
626             */
627            private static void setMainTableEntry(char char1, char char2,
628                    int entry) {
629                if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') {
630                    throw new IllegalArgumentException();
631                }
632                mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')] = entry;
633            }
634
635            /**
636             * Obtains a localized currency names from a CurrencyNameProvider
637             * implementation.
638             */
639            private static class CurrencyNameGetter
640                    implements 
641                    LocaleServiceProviderPool.LocalizedObjectGetter<CurrencyNameProvider, String> {
642                private static final CurrencyNameGetter INSTANCE = new CurrencyNameGetter();
643
644                public String getObject(
645                        CurrencyNameProvider currencyNameProvider,
646                        Locale locale, String key, Object... params) {
647                    assert params.length == 1;
648                    int type = (Integer) params[0];
649
650                    switch (type) {
651                    case SYMBOL:
652                        return currencyNameProvider.getSymbol(key, locale);
653                    case DISPLAYNAME:
654                        return currencyNameProvider.getDisplayName(key, locale);
655                    default:
656                        assert false; // shouldn't happen
657                    }
658
659                    return null;
660                }
661            }
662
663            private static int[] readIntArray(DataInputStream dis, int count)
664                    throws IOException {
665                int[] ret = new int[count];
666                for (int i = 0; i < count; i++) {
667                    ret[i] = dis.readInt();
668                }
669
670                return ret;
671            }
672
673            private static long[] readLongArray(DataInputStream dis, int count)
674                    throws IOException {
675                long[] ret = new long[count];
676                for (int i = 0; i < count; i++) {
677                    ret[i] = dis.readLong();
678                }
679
680                return ret;
681            }
682
683            private static String[] readStringArray(DataInputStream dis,
684                    int count) throws IOException {
685                String[] ret = new String[count];
686                for (int i = 0; i < count; i++) {
687                    ret[i] = dis.readUTF();
688                }
689
690                return ret;
691            }
692
693            /**
694             * Replaces currency data found in the currencydata.properties file
695             *
696             * @param pattern regex pattern for the properties
697             * @param ctry country code
698             * @param data currency data.  This is a comma separated string that
699             *    consists of "three-letter alphabet code", "three-digit numeric code", 
700             *    and "one-digit (0,1,2, or 3) default fraction digit". 
701             *    For example, "JPZ,392,0".
702             * @throws 
703             */
704            private static void replaceCurrencyData(Pattern pattern,
705                    String ctry, String curdata) {
706
707                if (ctry.length() != 2) {
708                    // ignore invalid country code
709                    String message = new StringBuilder().append(
710                            "The entry in currency.properties for ").append(
711                            ctry).append(
712                            " is ignored because of the invalid country code.")
713                            .toString();
714                    log(Level.INFO, message, null);
715                    return;
716                }
717
718                Matcher m = pattern.matcher(curdata);
719                if (!m.find()) {
720                    // format is not recognized.  ignore the data
721                    String message = new StringBuilder()
722                            .append("The entry in currency.properties for ")
723                            .append(ctry)
724                            .append(
725                                    " is ignored because the value format is not recognized.")
726                            .toString();
727                    log(Level.INFO, message, null);
728                    return;
729                }
730
731                String code = m.group(1);
732                int numeric = Integer.parseInt(m.group(2));
733                int fraction = Integer.parseInt(m.group(3));
734                int entry = numeric << NUMERIC_CODE_SHIFT;
735
736                int index;
737                for (index = 0; index < scOldCurrencies.length; index++) {
738                    if (scOldCurrencies[index].equals(code)) {
739                        break;
740                    }
741                }
742
743                if (index == scOldCurrencies.length) {
744                    // simple case
745                    entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT)
746                            | (code.charAt(2) - 'A');
747                } else {
748                    // special case
749                    entry |= SPECIAL_CASE_COUNTRY_MASK
750                            | (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA);
751                }
752                setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
753            }
754
755            private static void log(Level level, String message, Throwable t) {
756                Logger logger = Logger.getLogger("java.util.Currency");
757                if (logger.isLoggable(level)) {
758                    if (t != null) {
759                        logger.log(level, message, t);
760                    } else {
761                        logger.log(level, message);
762                    }
763                }
764            }
765        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.