Print this page
rev 5615 : 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 Jigsaw. by Naoto Sato and Masayoshi Okutsu)

Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/text/NumberFormat.java
          +++ new/src/share/classes/java/text/NumberFormat.java
↓ open down ↓ 46 lines elided ↑ open up ↑
  47   47  import java.text.spi.NumberFormatProvider;
  48   48  import java.util.Currency;
  49   49  import java.util.HashMap;
  50   50  import java.util.Hashtable;
  51   51  import java.util.Locale;
  52   52  import java.util.Map;
  53   53  import java.util.ResourceBundle;
  54   54  import java.util.concurrent.atomic.AtomicInteger;
  55   55  import java.util.concurrent.atomic.AtomicLong;
  56   56  import java.util.spi.LocaleServiceProvider;
  57      -import sun.util.LocaleServiceProviderPool;
       57 +import sun.util.locale.provider.LocaleProviderAdapter;
       58 +import sun.util.locale.provider.LocaleServiceProviderPool;
  58   59  import sun.util.resources.LocaleData;
  59   60  
  60   61  /**
  61   62   * <code>NumberFormat</code> is the abstract base class for all number
  62   63   * formats. This class provides the interface for formatting and parsing
  63   64   * numbers. <code>NumberFormat</code> also provides methods for determining
  64   65   * which locales have number formats, and what their names are.
  65   66   *
  66   67   * <p>
  67   68   * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
↓ open down ↓ 157 lines elided ↑ open up ↑
 225  226       *                   On output: the offsets of the alignment field.
 226  227       * @return           the value passed in as <code>toAppendTo</code>
 227  228       * @exception        IllegalArgumentException if <code>number</code> is
 228  229       *                   null or not an instance of <code>Number</code>.
 229  230       * @exception        NullPointerException if <code>toAppendTo</code> or
 230  231       *                   <code>pos</code> is null
 231  232       * @exception        ArithmeticException if rounding is needed with rounding
 232  233       *                   mode being set to RoundingMode.UNNECESSARY
 233  234       * @see              java.text.FieldPosition
 234  235       */
      236 +    @Override
 235  237      public StringBuffer format(Object number,
 236  238                                 StringBuffer toAppendTo,
 237  239                                 FieldPosition pos) {
 238  240          if (number instanceof Long || number instanceof Integer ||
 239  241              number instanceof Short || number instanceof Byte ||
 240  242              number instanceof AtomicInteger || number instanceof AtomicLong ||
 241  243              (number instanceof BigInteger &&
 242  244               ((BigInteger)number).bitLength() < 64)) {
 243  245              return format(((Number)number).longValue(), toAppendTo, pos);
 244  246          } else if (number instanceof Number) {
↓ open down ↓ 20 lines elided ↑ open up ↑
 265  267       * See the {@link #parse(String, ParsePosition)} method for more information
 266  268       * on number parsing.
 267  269       *
 268  270       * @param source A <code>String</code>, part of which should be parsed.
 269  271       * @param pos A <code>ParsePosition</code> object with index and error
 270  272       *            index information as described above.
 271  273       * @return A <code>Number</code> parsed from the string. In case of
 272  274       *         error, returns null.
 273  275       * @exception NullPointerException if <code>pos</code> is null.
 274  276       */
      277 +    @Override
 275  278      public final Object parseObject(String source, ParsePosition pos) {
 276  279          return parse(source, pos);
 277  280      }
 278  281  
 279  282     /**
 280  283       * Specialization of format.
 281  284       * @exception        ArithmeticException if rounding is needed with rounding
 282  285       *                   mode being set to RoundingMode.UNNECESSARY
 283  286       * @see java.text.Format#format
 284  287       */
↓ open down ↓ 209 lines elided ↑ open up ↑
 494  497       * @return An array of locales for which localized
 495  498       *         <code>NumberFormat</code> instances are available.
 496  499       */
 497  500      public static Locale[] getAvailableLocales() {
 498  501          LocaleServiceProviderPool pool =
 499  502              LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
 500  503          return pool.getAvailableLocales();
 501  504      }
 502  505  
 503  506      /**
 504      -     * Overrides hashCode
      507 +     * Overrides hashCode.
 505  508       */
      509 +    @Override
 506  510      public int hashCode() {
 507  511          return maximumIntegerDigits * 37 + maxFractionDigits;
 508  512          // just enough fields for a reasonable distribution
 509  513      }
 510  514  
 511  515      /**
 512      -     * Overrides equals
      516 +     * Overrides equals.
 513  517       */
      518 +    @Override
 514  519      public boolean equals(Object obj) {
 515  520          if (obj == null) {
 516  521              return false;
 517  522          }
 518  523          if (this == obj) {
 519  524              return true;
 520  525          }
 521  526          if (getClass() != obj.getClass()) {
 522  527              return false;
 523  528          }
 524  529          NumberFormat other = (NumberFormat) obj;
 525  530          return (maximumIntegerDigits == other.maximumIntegerDigits
 526  531              && minimumIntegerDigits == other.minimumIntegerDigits
 527  532              && maximumFractionDigits == other.maximumFractionDigits
 528  533              && minimumFractionDigits == other.minimumFractionDigits
 529  534              && groupingUsed == other.groupingUsed
 530  535              && parseIntegerOnly == other.parseIntegerOnly);
 531  536      }
 532  537  
 533  538      /**
 534      -     * Overrides Cloneable
      539 +     * Overrides Cloneable.
 535  540       */
      541 +    @Override
 536  542      public Object clone() {
 537  543          NumberFormat other = (NumberFormat) super.clone();
 538  544          return other;
 539  545      }
 540  546  
 541  547      /**
 542  548       * Returns true if grouping is used in this format. For example, in the
 543  549       * English locale, with grouping on, the number 1234567 might be formatted
 544  550       * as "1,234,567". The grouping separator as well as the size of each group
 545  551       * is locale dependant and is determined by sub-classes of NumberFormat.
↓ open down ↓ 188 lines elided ↑ open up ↑
 734  740       * @since 1.6
 735  741       */
 736  742      public void setRoundingMode(RoundingMode roundingMode) {
 737  743          throw new UnsupportedOperationException();
 738  744      }
 739  745  
 740  746      // =======================privates===============================
 741  747  
 742  748      private static NumberFormat getInstance(Locale desiredLocale,
 743  749                                             int choice) {
 744      -        // Check whether a provider can provide an implementation that's closer
 745      -        // to the requested locale than what the Java runtime itself can provide.
 746      -        LocaleServiceProviderPool pool =
 747      -            LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
 748      -        if (pool.hasProviders()) {
 749      -            NumberFormat providersInstance = pool.getLocalizedObject(
 750      -                                    NumberFormatGetter.INSTANCE,
 751      -                                    desiredLocale,
 752      -                                    choice);
 753      -            if (providersInstance != null) {
 754      -                return providersInstance;
 755      -            }
      750 +        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, desiredLocale);
      751 +        NumberFormatProvider provider = adapter.getNumberFormatProvider();
      752 +        NumberFormat numberFormat = null;
      753 +        switch (choice) {
      754 +        case NUMBERSTYLE:
      755 +            numberFormat = provider.getNumberInstance(desiredLocale);
      756 +            break;
      757 +        case PERCENTSTYLE:
      758 +            numberFormat = provider.getPercentInstance(desiredLocale);
      759 +            break;
      760 +        case CURRENCYSTYLE:
      761 +            numberFormat = provider.getCurrencyInstance(desiredLocale);
      762 +            break;
      763 +        case INTEGERSTYLE:
      764 +            numberFormat = provider.getIntegerInstance(desiredLocale);
      765 +            break;
 756  766          }
 757  767  
 758      -        /* try the cache first */
 759      -        String[] numberPatterns = cachedLocaleData.get(desiredLocale);
 760      -        if (numberPatterns == null) { /* cache miss */
 761      -            ResourceBundle resource = LocaleData.getNumberFormatData(desiredLocale);
 762      -            numberPatterns = resource.getStringArray("NumberPatterns");
 763      -            /* update cache */
 764      -            cachedLocaleData.put(desiredLocale, numberPatterns);
      768 +        if (numberFormat == null) {
      769 +            throw new InternalError("NumberFormat instance creation failed.");
 765  770          }
 766  771  
 767      -        DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
 768      -        int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
 769      -        DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
 770      -
 771      -        if (choice == INTEGERSTYLE) {
 772      -            format.setMaximumFractionDigits(0);
 773      -            format.setDecimalSeparatorAlwaysShown(false);
 774      -            format.setParseIntegerOnly(true);
 775      -        } else if (choice == CURRENCYSTYLE) {
 776      -            format.adjustForCurrencyDefaultFractionDigits();
 777      -        }
 778      -
 779      -        return format;
      772 +        return numberFormat;
 780  773      }
 781  774  
 782  775      /**
 783  776       * First, read in the default serializable data.
 784  777       *
 785  778       * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
 786  779       * the stream was written by JDK 1.1,
 787  780       * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
 788  781       * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
 789  782       * since the <code>int</code> fields were not present in JDK 1.1.
↓ open down ↓ 44 lines elided ↑ open up ↑
 834  827                             Byte.MAX_VALUE : (byte)maximumIntegerDigits;
 835  828          minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ?
 836  829                             Byte.MAX_VALUE : (byte)minimumIntegerDigits;
 837  830          maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ?
 838  831                              Byte.MAX_VALUE : (byte)maximumFractionDigits;
 839  832          minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
 840  833                              Byte.MAX_VALUE : (byte)minimumFractionDigits;
 841  834          stream.defaultWriteObject();
 842  835      }
 843  836  
 844      -    /**
 845      -     * Cache to hold the NumberPatterns of a Locale.
 846      -     */
 847      -    private static final Hashtable<Locale, String[]> cachedLocaleData = new Hashtable<>(3);
 848      -
 849  837      // Constants used by factory methods to specify a style of format.
 850  838      private static final int NUMBERSTYLE = 0;
 851  839      private static final int CURRENCYSTYLE = 1;
 852  840      private static final int PERCENTSTYLE = 2;
 853  841      private static final int SCIENTIFICSTYLE = 3;
 854  842      private static final int INTEGERSTYLE = 4;
 855  843  
 856  844      /**
 857  845       * True if the grouping (i.e. thousands) separator is used when
 858  846       * formatting and parsing numbers.
↓ open down ↓ 190 lines elided ↑ open up ↑
1049 1037                  instanceMap.put(name, this);
1050 1038              }
1051 1039          }
1052 1040  
1053 1041          /**
1054 1042           * Resolves instances being deserialized to the predefined constants.
1055 1043           *
1056 1044           * @throws InvalidObjectException if the constant could not be resolved.
1057 1045           * @return resolved NumberFormat.Field constant
1058 1046           */
     1047 +        @Override
1059 1048          protected Object readResolve() throws InvalidObjectException {
1060 1049              if (this.getClass() != NumberFormat.Field.class) {
1061 1050                  throw new InvalidObjectException("subclass didn't correctly implement readResolve");
1062 1051              }
1063 1052  
1064 1053              Object instance = instanceMap.get(getName());
1065 1054              if (instance != null) {
1066 1055                  return instance;
1067 1056              } else {
1068 1057                  throw new InvalidObjectException("unknown attribute name");
↓ open down ↓ 51 lines elided ↑ open up ↑
1120 1109          /**
1121 1110           * Constant identifying the currency field.
1122 1111           */
1123 1112          public static final Field CURRENCY = new Field("currency");
1124 1113  
1125 1114          /**
1126 1115           * Constant identifying the exponent sign field.
1127 1116           */
1128 1117          public static final Field EXPONENT_SIGN = new Field("exponent sign");
1129 1118      }
1130      -
1131      -    /**
1132      -     * Obtains a NumberFormat instance from a NumberFormatProvider implementation.
1133      -     */
1134      -    private static class NumberFormatGetter
1135      -        implements LocaleServiceProviderPool.LocalizedObjectGetter<NumberFormatProvider,
1136      -                                                                   NumberFormat> {
1137      -        private static final NumberFormatGetter INSTANCE = new NumberFormatGetter();
1138      -
1139      -        public NumberFormat getObject(NumberFormatProvider numberFormatProvider,
1140      -                                Locale locale,
1141      -                                String key,
1142      -                                Object... params) {
1143      -            assert params.length == 1;
1144      -            int choice = (Integer)params[0];
1145      -
1146      -            switch (choice) {
1147      -            case NUMBERSTYLE:
1148      -                return numberFormatProvider.getNumberInstance(locale);
1149      -            case PERCENTSTYLE:
1150      -                return numberFormatProvider.getPercentInstance(locale);
1151      -            case CURRENCYSTYLE:
1152      -                return numberFormatProvider.getCurrencyInstance(locale);
1153      -            case INTEGERSTYLE:
1154      -                return numberFormatProvider.getIntegerInstance(locale);
1155      -            default:
1156      -                assert false : choice;
1157      -            }
1158      -
1159      -            return null;
1160      -        }
1161      -    }
1162 1119  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX