src/share/classes/java/text/DecimalFormatSymbols.java

Print this page
rev 5696 : 6336885: RFE: Locale Data Deployment Enhancements
4609153: Provide locale data for Indic locales
5104387: Support for gl_ES locale (galician language)
6337471: desktop/system locale preferences support
7056139: (cal) SPI support for locale-dependent Calendar parameters
7058206: Provide CalendarData SPI for week params and display field value names
7073852: Support multiple scripts for digits and decimal symbols per locale
7079560: [Fmt-Da] Context dependent month names support in SimpleDateFormat
7171324: getAvailableLocales() of locale sensitive services should return the actual availability of locales
7151414: (cal) Support calendar type identification
7168528: LocaleServiceProvider needs to be aware of Locale extensions
7171372: (cal) locale's default Calendar should be created if unknown calendar is specified
Summary: JEP 127: Improve Locale Data Packaging and Adopt Unicode CLDR Data (part 1 w/o packaging changes. by Naoto Sato and Masayoshi Okutsu)

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -42,16 +42,17 @@
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.text.spi.DecimalFormatSymbolsProvider;
 import java.util.Currency;
 import java.util.Locale;
+import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.LocaleServiceProviderPool;
 
-import sun.util.LocaleServiceProviderPool;
-import sun.util.resources.LocaleData;
-
 /**
  * This class represents the set of symbols (such as the decimal separator,
  * the grouping separator, and so on) needed by <code>DecimalFormat</code>
  * to format numbers. <code>DecimalFormat</code> creates for itself an instance of
  * <code>DecimalFormatSymbols</code> from its locale data.  If you need to change any

@@ -85,10 +86,18 @@
      * supported by the Java runtime environment, not for those
      * supported by installed
      * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
      * implementations. For full locale coverage, use the
      * {@link #getInstance(Locale) getInstance} method.
+     * If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}
+     * for the numbering system, the instance is initialized with the specified numbering
+     * system if the JRE implementation supports it. For example,
+     * <pre>
+     * NumberFormat.getNumberInstance(Locale.forLanguageTag("th-TH-u-nu-thai"))
+     * </pre>
+     * This may return a {@code NumberFormat} instance with the Thai numbering system,
+     * instead of the Latin numbering system.
      *
      * @exception NullPointerException if <code>locale</code> is null
      */
     public DecimalFormatSymbols( Locale locale ) {
         initialize( locale );

@@ -133,32 +142,35 @@
      * locale.  This method provides access to <code>DecimalFormatSymbols</code>
      * instances for locales supported by the Java runtime itself as well
      * as for those supported by installed
      * {@link java.text.spi.DecimalFormatSymbolsProvider
      * DecimalFormatSymbolsProvider} implementations.
+     * If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}
+     * for the numbering system, the instance is initialized with the specified numbering
+     * system if the JRE implementation supports it. For example,
+     * <pre>
+     * NumberFormat.getNumberInstance(Locale.forLanguageTag("th-TH-u-nu-thai"))
+     * </pre>
+     * This may return a {@code NumberFormat} instance with the Thai numbering system,
+     * instead of the Latin numbering system.
      * @param locale the desired locale.
      * @return a <code>DecimalFormatSymbols</code> instance.
      * @exception NullPointerException if <code>locale</code> is null
      * @since 1.6
      */
     public static final DecimalFormatSymbols getInstance(Locale locale) {
-
-        // Check whether a provider can provide an implementation that's closer
-        // to the requested locale than what the Java runtime itself can provide.
-        LocaleServiceProviderPool pool =
-            LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class);
-        if (pool.hasProviders()) {
-            DecimalFormatSymbols providersInstance = pool.getLocalizedObject(
-                                DecimalFormatSymbolsGetter.INSTANCE, locale);
-            if (providersInstance != null) {
-                return providersInstance;
+        LocaleProviderAdapter adapter;
+        adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+        DecimalFormatSymbolsProvider provider = adapter.getDecimalFormatSymbolsProvider();
+        DecimalFormatSymbols dfsyms = provider.getInstance(locale);
+        if (dfsyms == null) {
+            provider = LocaleProviderAdapter.forJRE().getDecimalFormatSymbolsProvider();
+            dfsyms = provider.getInstance(locale);
             }
+        return dfsyms;
         }
 
-        return new DecimalFormatSymbols(locale);
-    }
-
     /**
      * Gets the character used for zero. Different for Arabic, etc.
      */
     public char getZeroDigit() {
         return zeroDigit;

@@ -472,10 +484,11 @@
     //------------------------------------------------------------
 
     /**
      * Standard override.
      */
+    @Override
     public Object clone() {
         try {
             return (DecimalFormatSymbols)super.clone();
             // other fields are bit-copied
         } catch (CloneNotSupportedException e) {

@@ -484,10 +497,11 @@
     }
 
     /**
      * Override equals.
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == null) return false;
         if (this == obj) return true;
         if (getClass() != obj.getClass()) return false;
         DecimalFormatSymbols other = (DecimalFormatSymbols) obj;

@@ -510,10 +524,11 @@
     }
 
     /**
      * Override hashCode.
      */
+    @Override
     public int hashCode() {
             int result = zeroDigit;
             result = result * 37 + groupingSeparator;
             result = result * 37 + decimalSeparator;
             return result;

@@ -527,20 +542,34 @@
 
         // get resource bundle data - try the cache first
         boolean needCacheUpdate = false;
         Object[] data = cachedLocaleData.get(locale);
         if (data == null) {  /* cache miss */
-            // When numbering system is thai (Locale's extension contains u-nu-thai),
-            // we read the data from th_TH_TH.
-            Locale lookupLocale = locale;
-            String numberType = locale.getUnicodeLocaleType("nu");
-            if (numberType != null && numberType.equals("thai")) {
-                lookupLocale = new Locale("th", "TH", "TH");
+            LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+            // Avoid potential recursions
+            switch (adapter.getAdapterType()) {
+            case HOST:
+            case SPI:
+                adapter = LocaleProviderAdapter.getResourceBundleBased();
+                break;
             }
+            ResourceBundle rb = adapter.getLocaleData().getNumberFormatData(locale);
             data = new Object[3];
-            ResourceBundle rb = LocaleData.getNumberFormatData(lookupLocale);
+            String numberType = locale.getUnicodeLocaleType("nu");
+            StringBuilder numElemKey =
+                new StringBuilder(numberType != null ?
+                                  numberType : rb.getString("DefaultNumberingSystem"));
+            if (numElemKey.length() != 0) {
+                numElemKey.append(".");
+            }
+            numElemKey.append("NumberElements");
+            try {
+                data[0] = rb.getStringArray(numElemKey.toString());
+            } catch (MissingResourceException mre) {
+                // numberType must be bogus. Use the last resort numbering system.
             data[0] = rb.getStringArray("NumberElements");
+            }
             needCacheUpdate = true;
         }
 
         String[] numberElements = (String[]) data[0];
 

@@ -559,11 +588,11 @@
 
         // Try to obtain the currency used in the locale's country.
         // Check for empty country string separately because it's a valid
         // country ID for Locale (and used for the C locale), but not a valid
         // ISO 3166 country code, and exceptions are expensive.
-        if (!"".equals(locale.getCountry())) {
+        if (locale.getCountry().length() > 0) {
             try {
                 currency = Currency.getInstance(locale);
             } catch (IllegalArgumentException e) {
                 // use default values below for compatibility
             }

@@ -811,27 +840,8 @@
 
     /**
      * cache to hold the NumberElements and the Currency
      * of a Locale.
      */
-    private static final ConcurrentHashMap<Locale, Object[]> cachedLocaleData = new ConcurrentHashMap<Locale, Object[]>(3);
-
-    /**
-     * Obtains a DecimalFormatSymbols instance from a DecimalFormatSymbolsProvider
-     * implementation.
-     */
-    private static class DecimalFormatSymbolsGetter
-        implements LocaleServiceProviderPool.LocalizedObjectGetter<DecimalFormatSymbolsProvider,
-                                                                   DecimalFormatSymbols> {
-        private static final DecimalFormatSymbolsGetter INSTANCE =
-            new DecimalFormatSymbolsGetter();
-
-        public DecimalFormatSymbols getObject(
-                                DecimalFormatSymbolsProvider decimalFormatSymbolsProvider,
-                                Locale locale,
-                                String key,
-                                Object... params) {
-            assert params.length == 0;
-            return decimalFormatSymbolsProvider.getInstance(locale);
-        }
-    }
+    private static final ConcurrentMap<Locale, Object[]> cachedLocaleData
+            = new ConcurrentHashMap<>(3);
 }