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

@@ -36,25 +36,26 @@
  *
  */
 
 package java.text;
 
-import java.io.InvalidObjectException;
 import java.io.IOException;
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
+import java.text.spi.NumberFormatProvider;
 import java.util.ArrayList;
 import java.util.Currency;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
-import sun.util.resources.LocaleData;
+import sun.util.locale.provider.LocaleProviderAdapter;
 
 /**
  * <code>DecimalFormat</code> is a concrete subclass of
  * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
  * features designed to make it possible to parse and format numbers in any

@@ -396,19 +397,26 @@
         Locale def = Locale.getDefault(Locale.Category.FORMAT);
         // try to get the pattern from the cache
         String pattern = cachedLocaleData.get(def);
         if (pattern == null) {  /* cache miss */
             // Get the pattern for the default locale.
-            ResourceBundle rb = LocaleData.getNumberFormatData(def);
+            LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
+            switch (adapter.getAdapterType()) {
+            case HOST:
+            case SPI:
+                adapter = LocaleProviderAdapter.getResourceBundleBased();
+                break;
+            }
+            ResourceBundle rb = adapter.getLocaleData().getNumberFormatData(def);
             String[] all = rb.getStringArray("NumberPatterns");
             pattern = all[0];
             /* update cache */
             cachedLocaleData.putIfAbsent(def, pattern);
         }
 
         // Always applyPattern after the symbols are set
-        this.symbols = new DecimalFormatSymbols(def);
+        this.symbols = DecimalFormatSymbols.getInstance(def);
         applyPattern(pattern, false);
     }
 
 
     /**

@@ -429,11 +437,11 @@
      * @see java.text.NumberFormat#getCurrencyInstance
      * @see java.text.NumberFormat#getPercentInstance
      */
     public DecimalFormat(String pattern) {
         // Always applyPattern after the symbols are set
-        this.symbols = new DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT));
+        this.symbols = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));
         applyPattern(pattern, false);
     }
 
 
     /**

@@ -483,10 +491,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 final StringBuffer format(Object number,
                                      StringBuffer toAppendTo,
                                      FieldPosition pos) {
         if (number instanceof Long || number instanceof Integer ||
                    number instanceof Short || number instanceof Byte ||

@@ -515,10 +524,11 @@
      * @exception ArithmeticException if rounding is needed with rounding
      *            mode being set to RoundingMode.UNNECESSARY
      * @return The formatted number string
      * @see java.text.FieldPosition
      */
+    @Override
     public StringBuffer format(double number, StringBuffer result,
                                FieldPosition fieldPosition) {
         fieldPosition.setBeginIndex(0);
         fieldPosition.setEndIndex(0);
 

@@ -616,10 +626,11 @@
      * @exception       ArithmeticException if rounding is needed with rounding
      *                  mode being set to RoundingMode.UNNECESSARY
      * @return The formatted number string
      * @see java.text.FieldPosition
      */
+    @Override
     public StringBuffer format(long number, StringBuffer result,
                                FieldPosition fieldPosition) {
         fieldPosition.setBeginIndex(0);
         fieldPosition.setEndIndex(0);
 

@@ -830,10 +841,11 @@
      *                   mode being set to RoundingMode.UNNECESSARY
      * @param obj The object to format
      * @return AttributedCharacterIterator describing the formatted value.
      * @since 1.4
      */
+    @Override
     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
         CharacterIteratorFieldDelegate delegate =
                          new CharacterIteratorFieldDelegate();
         StringBuffer sb = new StringBuffer();
 

@@ -1255,10 +1267,11 @@
      *             index information as described above.
      * @return     the parsed value, or <code>null</code> if the parse fails
      * @exception  NullPointerException if <code>text</code> or
      *             <code>pos</code> is null.
      */
+    @Override
     public Number parse(String text, ParsePosition pos) {
         // special case NaN
         if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
             pos.index = pos.index + symbols.getNaN().length();
             return new Double(Double.NaN);

@@ -1888,10 +1901,11 @@
     }
 
     /**
      * Standard override; no change in semantics.
      */
+    @Override
     public Object clone() {
         DecimalFormat other = (DecimalFormat) super.clone();
         other.symbols = (DecimalFormatSymbols) symbols.clone();
         other.digitList = (DigitList) digitList.clone();
         return other;

@@ -1898,10 +1912,11 @@
     }
 
     /**
      * Overrides equals
      */
+    @Override
     public boolean equals(Object obj)
     {
         if (obj == null) return false;
         if (!super.equals(obj)) return false; // super does class check
         DecimalFormat other = (DecimalFormat) obj;

@@ -1937,10 +1952,11 @@
     }
 
     /**
      * Overrides hashCode
      */
+    @Override
     public int hashCode() {
         return super.hashCode() * 37 + positivePrefix.hashCode();
         // just enough fields for a reasonable distribution
     }
 

@@ -2666,10 +2682,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
      * 309 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMaximumIntegerDigits
      */
+    @Override
     public void setMaximumIntegerDigits(int newValue) {
         maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
         super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
             DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
         if (minimumIntegerDigits > maximumIntegerDigits) {

@@ -2685,10 +2702,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
      * 309 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMinimumIntegerDigits
      */
+    @Override
     public void setMinimumIntegerDigits(int newValue) {
         minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
         super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
             DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
         if (minimumIntegerDigits > maximumIntegerDigits) {

@@ -2704,10 +2722,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
      * 340 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMaximumFractionDigits
      */
+    @Override
     public void setMaximumFractionDigits(int newValue) {
         maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
         super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
             DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
         if (minimumFractionDigits > maximumFractionDigits) {

@@ -2723,10 +2742,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
      * 340 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMinimumFractionDigits
      */
+    @Override
     public void setMinimumFractionDigits(int newValue) {
         minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
         super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
             DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
         if (minimumFractionDigits > maximumFractionDigits) {

@@ -2742,10 +2762,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of the return value and
      * 309 is used.
      * @see #setMaximumIntegerDigits
      */
+    @Override
     public int getMaximumIntegerDigits() {
         return maximumIntegerDigits;
     }
 
     /**

@@ -2754,10 +2775,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of the return value and
      * 309 is used.
      * @see #setMinimumIntegerDigits
      */
+    @Override
     public int getMinimumIntegerDigits() {
         return minimumIntegerDigits;
     }
 
     /**

@@ -2766,10 +2788,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of the return value and
      * 340 is used.
      * @see #setMaximumFractionDigits
      */
+    @Override
     public int getMaximumFractionDigits() {
         return maximumFractionDigits;
     }
 
     /**

@@ -2778,10 +2801,11 @@
      * For formatting numbers other than <code>BigInteger</code> and
      * <code>BigDecimal</code> objects, the lower of the return value and
      * 340 is used.
      * @see #setMinimumFractionDigits
      */
+    @Override
     public int getMinimumFractionDigits() {
         return minimumFractionDigits;
     }
 
     /**

@@ -2792,10 +2816,11 @@
      * on this number format's symbols.
      *
      * @return the currency used by this decimal format, or <code>null</code>
      * @since 1.4
      */
+    @Override
     public Currency getCurrency() {
         return symbols.getCurrency();
     }
 
     /**

@@ -2808,10 +2833,11 @@
      *
      * @param currency the new currency to be used by this decimal format
      * @exception NullPointerException if <code>currency</code> is null
      * @since 1.4
      */
+    @Override
     public void setCurrency(Currency currency) {
         if (currency != symbols.getCurrency()) {
             symbols.setCurrency(currency);
             if (isCurrencyFormat) {
                 expandAffixes();

@@ -2824,10 +2850,11 @@
      *
      * @return The <code>RoundingMode</code> used for this DecimalFormat.
      * @see #setRoundingMode(RoundingMode)
      * @since 1.6
      */
+    @Override
     public RoundingMode getRoundingMode() {
         return roundingMode;
     }
 
     /**

@@ -2836,10 +2863,11 @@
      * @param roundingMode The <code>RoundingMode</code> to be used
      * @see #getRoundingMode()
      * @exception NullPointerException if <code>roundingMode</code> is null.
      * @since 1.6
      */
+    @Override
     public void setRoundingMode(RoundingMode roundingMode) {
         if (roundingMode == null) {
             throw new NullPointerException();
         }
 

@@ -2846,39 +2874,10 @@
         this.roundingMode = roundingMode;
         digitList.setRoundingMode(roundingMode);
     }
 
     /**
-     * Adjusts the minimum and maximum fraction digits to values that
-     * are reasonable for the currency's default fraction digits.
-     */
-    void adjustForCurrencyDefaultFractionDigits() {
-        Currency currency = symbols.getCurrency();
-        if (currency == null) {
-            try {
-                currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
-            } catch (IllegalArgumentException e) {
-            }
-        }
-        if (currency != null) {
-            int digits = currency.getDefaultFractionDigits();
-            if (digits != -1) {
-                int oldMinDigits = getMinimumFractionDigits();
-                // Common patterns are "#.##", "#.00", "#".
-                // Try to adjust all of them in a reasonable way.
-                if (oldMinDigits == getMaximumFractionDigits()) {
-                    setMinimumFractionDigits(digits);
-                    setMaximumFractionDigits(digits);
-                } else {
-                    setMinimumFractionDigits(Math.min(digits, oldMinDigits));
-                    setMaximumFractionDigits(digits);
-                }
-            }
-        }
-    }
-
-    /**
      * Reads the default serializable fields from the stream and performs
      * validations and adjustments for older serialized versions. The
      * validations and adjustments are:
      * <ol>
      * <li>

@@ -3268,7 +3267,7 @@
 
     /**
      * Cache to hold the NumberPattern of a Locale.
      */
     private static final ConcurrentMap<Locale, String> cachedLocaleData
-        = new ConcurrentHashMap<Locale, String>(3);
+        = new ConcurrentHashMap<>(3);
 }