src/share/classes/java/text/NumberFormat.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)

@@ -52,11 +52,12 @@
 import java.util.Map;
 import java.util.ResourceBundle;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.spi.LocaleServiceProvider;
-import sun.util.LocaleServiceProviderPool;
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.LocaleServiceProviderPool;
 import sun.util.resources.LocaleData;
 
 /**
  * <code>NumberFormat</code> is the abstract base class for all number
  * formats. This class provides the interface for formatting and parsing

@@ -230,10 +231,11 @@
      *                   <code>pos</code> is null
      * @exception        ArithmeticException if rounding is needed with rounding
      *                   mode being set to RoundingMode.UNNECESSARY
      * @see              java.text.FieldPosition
      */
+    @Override
     public StringBuffer format(Object number,
                                StringBuffer toAppendTo,
                                FieldPosition pos) {
         if (number instanceof Long || number instanceof Integer ||
             number instanceof Short || number instanceof Byte ||

@@ -270,10 +272,11 @@
      *            index information as described above.
      * @return A <code>Number</code> parsed from the string. In case of
      *         error, returns null.
      * @exception NullPointerException if <code>pos</code> is null.
      */
+    @Override
     public final Object parseObject(String source, ParsePosition pos) {
         return parse(source, pos);
     }
 
    /**

@@ -499,20 +502,22 @@
             LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
         return pool.getAvailableLocales();
     }
 
     /**
-     * Overrides hashCode
+     * Overrides hashCode.
      */
+    @Override
     public int hashCode() {
         return maximumIntegerDigits * 37 + maxFractionDigits;
         // just enough fields for a reasonable distribution
     }
 
     /**
-     * Overrides equals
+     * Overrides equals.
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj == null) {
             return false;
         }
         if (this == obj) {

@@ -529,12 +534,13 @@
             && groupingUsed == other.groupingUsed
             && parseIntegerOnly == other.parseIntegerOnly);
     }
 
     /**
-     * Overrides Cloneable
+     * Overrides Cloneable.
      */
+    @Override
     public Object clone() {
         NumberFormat other = (NumberFormat) super.clone();
         return other;
     }
 

@@ -739,48 +745,42 @@
 
     // =======================privates===============================
 
     private static NumberFormat getInstance(Locale desiredLocale,
                                            int choice) {
-        // 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(NumberFormatProvider.class);
-        if (pool.hasProviders()) {
-            NumberFormat providersInstance = pool.getLocalizedObject(
-                                    NumberFormatGetter.INSTANCE,
-                                    desiredLocale,
-                                    choice);
-            if (providersInstance != null) {
-                return providersInstance;
+        LocaleProviderAdapter adapter;
+        adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class,
+                                                   desiredLocale);
+        NumberFormat numberFormat = getInstance(adapter, desiredLocale, choice);
+        if (numberFormat == null) {
+            numberFormat = getInstance(LocaleProviderAdapter.forJRE(),
+                                       desiredLocale, choice);
             }
+        return numberFormat;
         }
 
-        /* try the cache first */
-        String[] numberPatterns = cachedLocaleData.get(desiredLocale);
-        if (numberPatterns == null) { /* cache miss */
-            ResourceBundle resource = LocaleData.getNumberFormatData(desiredLocale);
-            numberPatterns = resource.getStringArray("NumberPatterns");
-            /* update cache */
-            cachedLocaleData.put(desiredLocale, numberPatterns);
+    private static NumberFormat getInstance(LocaleProviderAdapter adapter,
+                                            Locale locale, int choice) {
+        NumberFormatProvider provider = adapter.getNumberFormatProvider();
+        NumberFormat numberFormat = null;
+        switch (choice) {
+        case NUMBERSTYLE:
+            numberFormat = provider.getNumberInstance(locale);
+            break;
+        case PERCENTSTYLE:
+            numberFormat = provider.getPercentInstance(locale);
+            break;
+        case CURRENCYSTYLE:
+            numberFormat = provider.getCurrencyInstance(locale);
+            break;
+        case INTEGERSTYLE:
+            numberFormat = provider.getIntegerInstance(locale);
+            break;
         }
-
-        DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
-        int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
-        DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
-
-        if (choice == INTEGERSTYLE) {
-            format.setMaximumFractionDigits(0);
-            format.setDecimalSeparatorAlwaysShown(false);
-            format.setParseIntegerOnly(true);
-        } else if (choice == CURRENCYSTYLE) {
-            format.adjustForCurrencyDefaultFractionDigits();
+        return numberFormat;
         }
 
-        return format;
-    }
-
     /**
      * First, read in the default serializable data.
      *
      * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
      * the stream was written by JDK 1.1,

@@ -839,15 +839,10 @@
         minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
                             Byte.MAX_VALUE : (byte)minimumFractionDigits;
         stream.defaultWriteObject();
     }
 
-    /**
-     * Cache to hold the NumberPatterns of a Locale.
-     */
-    private static final Hashtable<Locale, String[]> cachedLocaleData = new Hashtable<>(3);
-
     // Constants used by factory methods to specify a style of format.
     private static final int NUMBERSTYLE = 0;
     private static final int CURRENCYSTYLE = 1;
     private static final int PERCENTSTYLE = 2;
     private static final int SCIENTIFICSTYLE = 3;

@@ -1054,10 +1049,11 @@
          * Resolves instances being deserialized to the predefined constants.
          *
          * @throws InvalidObjectException if the constant could not be resolved.
          * @return resolved NumberFormat.Field constant
          */
+        @Override
         protected Object readResolve() throws InvalidObjectException {
             if (this.getClass() != NumberFormat.Field.class) {
                 throw new InvalidObjectException("subclass didn't correctly implement readResolve");
             }
 

@@ -1125,38 +1121,6 @@
         /**
          * Constant identifying the exponent sign field.
          */
         public static final Field EXPONENT_SIGN = new Field("exponent sign");
     }
-
-    /**
-     * Obtains a NumberFormat instance from a NumberFormatProvider implementation.
-     */
-    private static class NumberFormatGetter
-        implements LocaleServiceProviderPool.LocalizedObjectGetter<NumberFormatProvider,
-                                                                   NumberFormat> {
-        private static final NumberFormatGetter INSTANCE = new NumberFormatGetter();
-
-        public NumberFormat getObject(NumberFormatProvider numberFormatProvider,
-                                Locale locale,
-                                String key,
-                                Object... params) {
-            assert params.length == 1;
-            int choice = (Integer)params[0];
-
-            switch (choice) {
-            case NUMBERSTYLE:
-                return numberFormatProvider.getNumberInstance(locale);
-            case PERCENTSTYLE:
-                return numberFormatProvider.getPercentInstance(locale);
-            case CURRENCYSTYLE:
-                return numberFormatProvider.getCurrencyInstance(locale);
-            case INTEGERSTYLE:
-                return numberFormatProvider.getIntegerInstance(locale);
-            default:
-                assert false : choice;
-            }
-
-            return null;
-        }
-    }
 }