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)

Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/text/Collator.java
          +++ new/src/share/classes/java/text/Collator.java
   1    1  /*
   2      - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
        2 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
   3    3   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4    4   *
   5    5   * This code is free software; you can redistribute it and/or modify it
   6    6   * under the terms of the GNU General Public License version 2 only, as
   7    7   * published by the Free Software Foundation.  Oracle designates this
   8    8   * particular file as subject to the "Classpath" exception as provided
   9    9   * by Oracle in the LICENSE file that accompanied this code.
  10   10   *
  11   11   * This code is distributed in the hope that it will be useful, but WITHOUT
  12   12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
↓ open down ↓ 18 lines elided ↑ open up ↑
  31   31   * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  32   32   * materials are provided under terms of a License Agreement between Taligent
  33   33   * and Sun. This technology is protected by multiple US and International
  34   34   * patents. This notice and attribution to Taligent may not be removed.
  35   35   *   Taligent is a registered trademark of Taligent, Inc.
  36   36   *
  37   37   */
  38   38  
  39   39  package java.text;
  40   40  
       41 +import java.lang.ref.SoftReference;
  41   42  import java.text.spi.CollatorProvider;
  42   43  import java.util.Locale;
  43      -import java.util.MissingResourceException;
  44   44  import java.util.ResourceBundle;
  45      -import java.util.spi.LocaleServiceProvider;
  46      -import sun.misc.SoftCache;
  47      -import sun.util.resources.LocaleData;
  48      -import sun.util.LocaleServiceProviderPool;
       45 +import java.util.concurrent.ConcurrentHashMap;
       46 +import java.util.concurrent.ConcurrentMap;
       47 +import sun.util.locale.provider.LocaleProviderAdapter;
       48 +import sun.util.locale.provider.LocaleServiceProviderPool;
  49   49  
  50   50  
  51   51  /**
  52   52   * The <code>Collator</code> class performs locale-sensitive
  53   53   * <code>String</code> comparison. You use this class to build
  54   54   * searching and sorting routines for natural language text.
  55   55   *
  56   56   * <p>
  57   57   * <code>Collator</code> is an abstract base class. Subclasses
  58   58   * implement specific collation strategies. One subclass,
↓ open down ↓ 165 lines elided ↑ open up ↑
 224  224          return getInstance(Locale.getDefault());
 225  225      }
 226  226  
 227  227      /**
 228  228       * Gets the Collator for the desired locale.
 229  229       * @param desiredLocale the desired locale.
 230  230       * @return the Collator for the desired locale.
 231  231       * @see java.util.Locale
 232  232       * @see java.util.ResourceBundle
 233  233       */
 234      -    public static synchronized
 235      -    Collator getInstance(Locale desiredLocale)
 236      -    {
 237      -        Collator result = (Collator) cache.get(desiredLocale);
 238      -        if (result != null) {
 239      -                 return (Collator)result.clone();  // make the world safe
 240      -        }
 241      -
 242      -        // Check whether a provider can provide an implementation that's closer
 243      -        // to the requested locale than what the Java runtime itself can provide.
 244      -        LocaleServiceProviderPool pool =
 245      -            LocaleServiceProviderPool.getPool(CollatorProvider.class);
 246      -        if (pool.hasProviders()) {
 247      -            Collator providersInstance = pool.getLocalizedObject(
 248      -                                            CollatorGetter.INSTANCE,
 249      -                                            desiredLocale,
 250      -                                            desiredLocale);
 251      -            if (providersInstance != null) {
 252      -                return providersInstance;
      234 +    public static Collator getInstance(Locale desiredLocale) {
      235 +        SoftReference<Collator> ref = cache.get(desiredLocale);
      236 +        Collator result = (ref != null) ? ref.get() : null;
      237 +        if (result == null) {
      238 +            LocaleProviderAdapter adapter;
      239 +            adapter = LocaleProviderAdapter.getAdapter(CollatorProvider.class,
      240 +                                                       desiredLocale);
      241 +            CollatorProvider provider = adapter.getCollatorProvider();
      242 +            result = provider.getInstance(desiredLocale);
      243 +            if (result == null) {
      244 +                result = LocaleProviderAdapter.forJRE()
      245 +                             .getCollatorProvider().getInstance(desiredLocale);
 253  246              }
 254      -        }
 255      -
 256      -        // Load the resource of the desired locale from resource
 257      -        // manager.
 258      -        String colString = "";
 259      -        try {
 260      -            ResourceBundle resource = LocaleData.getCollationData(desiredLocale);
 261      -
 262      -            colString = resource.getString("Rule");
 263      -        } catch (MissingResourceException e) {
 264      -            // Use default values
 265      -        }
 266      -        try
 267      -        {
 268      -            result = new RuleBasedCollator( CollationRules.DEFAULTRULES +
 269      -                                            colString,
 270      -                                            CANONICAL_DECOMPOSITION );
 271      -        }
 272      -        catch(ParseException foo)
 273      -        {
 274      -            // predefined tables should contain correct grammar
 275      -            try {
 276      -                result = new RuleBasedCollator( CollationRules.DEFAULTRULES );
 277      -            } catch (ParseException bar) {
 278      -                // do nothing
      247 +            while (true) {
      248 +                if (ref != null) {
      249 +                    // Remove the empty SoftReference if any
      250 +                    cache.remove(desiredLocale, ref);
      251 +                }
      252 +                ref = cache.putIfAbsent(desiredLocale, new SoftReference<>(result));
      253 +                if (ref == null) {
      254 +                    break;
      255 +                }
      256 +                Collator cachedColl = ref.get();
      257 +                if (cachedColl != null) {
      258 +                    result = cachedColl;
      259 +                    break;
      260 +                }
 279  261              }
 280  262          }
 281      -        // Now that RuleBasedCollator adds expansions for pre-composed characters
 282      -        // into their decomposed equivalents, the default collators don't need
 283      -        // to have decomposition turned on.  Laura, 5/5/98, bug 4114077
 284      -        result.setDecomposition(NO_DECOMPOSITION);
 285      -
 286      -        cache.put(desiredLocale,result);
 287      -        return (Collator)result.clone();
      263 +        return (Collator) result.clone(); // make the world safe
 288  264      }
 289  265  
 290  266      /**
 291  267       * Compares the source string to the target string according to the
 292  268       * collation rules for this Collator.  Returns an integer less than,
 293  269       * equal to or greater than zero depending on whether the source String is
 294  270       * less than, equal to or greater than the target string.  See the Collator
 295  271       * class description for an example of use.
 296  272       * <p>
 297  273       * For a one time comparison, this method has the best performance. If a
↓ open down ↓ 18 lines elided ↑ open up ↑
 316  292       * This implementation merely returns
 317  293       *  <code> compare((String)o1, (String)o2) </code>.
 318  294       *
 319  295       * @return a negative integer, zero, or a positive integer as the
 320  296       *         first argument is less than, equal to, or greater than the
 321  297       *         second.
 322  298       * @exception ClassCastException the arguments cannot be cast to Strings.
 323  299       * @see java.util.Comparator
 324  300       * @since   1.2
 325  301       */
      302 +    @Override
 326  303      public int compare(Object o1, Object o2) {
 327  304      return compare((String)o1, (String)o2);
 328  305      }
 329  306  
 330  307      /**
 331  308       * Transforms the String into a series of bits that can be compared bitwise
 332  309       * to other CollationKeys. CollationKeys provide better performance than
 333  310       * Collator.compare when Strings are involved in multiple comparisons.
 334  311       * See the Collator class description for an example using CollationKeys.
 335  312       * @param source the string to be transformed into a collation key.
↓ open down ↓ 44 lines elided ↑ open up ↑
 380  357       * @see java.text.Collator#SECONDARY
 381  358       * @see java.text.Collator#TERTIARY
 382  359       * @see java.text.Collator#IDENTICAL
 383  360       * @exception  IllegalArgumentException If the new strength value is not one of
 384  361       * PRIMARY, SECONDARY, TERTIARY or IDENTICAL.
 385  362       */
 386  363      public synchronized void setStrength(int newStrength) {
 387  364          if ((newStrength != PRIMARY) &&
 388  365              (newStrength != SECONDARY) &&
 389  366              (newStrength != TERTIARY) &&
 390      -            (newStrength != IDENTICAL))
      367 +            (newStrength != IDENTICAL)) {
 391  368              throw new IllegalArgumentException("Incorrect comparison level.");
      369 +        }
 392  370          strength = newStrength;
 393  371      }
 394  372  
 395  373      /**
 396  374       * Get the decomposition mode of this Collator. Decomposition mode
 397  375       * determines how Unicode composed characters are handled. Adjusting
 398  376       * decomposition mode allows the user to select between faster and more
 399  377       * complete collation behavior.
 400  378       * <p>The three values for decomposition mode are:
 401  379       * <UL>
↓ open down ↓ 20 lines elided ↑ open up ↑
 422  400       * @see java.text.Collator#getDecomposition
 423  401       * @see java.text.Collator#NO_DECOMPOSITION
 424  402       * @see java.text.Collator#CANONICAL_DECOMPOSITION
 425  403       * @see java.text.Collator#FULL_DECOMPOSITION
 426  404       * @exception IllegalArgumentException If the given value is not a valid decomposition
 427  405       * mode.
 428  406       */
 429  407      public synchronized void setDecomposition(int decompositionMode) {
 430  408          if ((decompositionMode != NO_DECOMPOSITION) &&
 431  409              (decompositionMode != CANONICAL_DECOMPOSITION) &&
 432      -            (decompositionMode != FULL_DECOMPOSITION))
      410 +            (decompositionMode != FULL_DECOMPOSITION)) {
 433  411              throw new IllegalArgumentException("Wrong decomposition mode.");
      412 +        }
 434  413          decmp = decompositionMode;
 435  414      }
 436  415  
 437  416      /**
 438  417       * Returns an array of all locales for which the
 439  418       * <code>getInstance</code> methods of this class can return
 440  419       * localized instances.
 441  420       * The returned array represents the union of locales supported
 442  421       * by the Java runtime and by installed
 443  422       * {@link java.text.spi.CollatorProvider CollatorProvider} implementations.
↓ open down ↓ 5 lines elided ↑ open up ↑
 449  428       */
 450  429      public static synchronized Locale[] getAvailableLocales() {
 451  430          LocaleServiceProviderPool pool =
 452  431              LocaleServiceProviderPool.getPool(CollatorProvider.class);
 453  432          return pool.getAvailableLocales();
 454  433      }
 455  434  
 456  435      /**
 457  436       * Overrides Cloneable
 458  437       */
      438 +    @Override
 459  439      public Object clone()
 460  440      {
 461  441          try {
 462  442              return (Collator)super.clone();
 463  443          } catch (CloneNotSupportedException e) {
 464  444              throw new InternalError(e);
 465  445          }
 466  446      }
 467  447  
 468  448      /**
 469  449       * Compares the equality of two Collators.
 470  450       * @param that the Collator to be compared with this.
 471  451       * @return true if this Collator is the same as that Collator;
 472  452       * false otherwise.
 473  453       */
      454 +    @Override
 474  455      public boolean equals(Object that)
 475  456      {
 476      -        if (this == that) return true;
 477      -        if (that == null) return false;
 478      -        if (getClass() != that.getClass()) return false;
      457 +        if (this == that) {
      458 +            return true;
      459 +        }
      460 +        if (that == null) {
      461 +            return false;
      462 +        }
      463 +        if (getClass() != that.getClass()) {
      464 +            return false;
      465 +        }
 479  466          Collator other = (Collator) that;
 480  467          return ((strength == other.strength) &&
 481  468                  (decmp == other.decmp));
 482  469      }
 483  470  
 484  471      /**
 485  472       * Generates the hash code for this Collator.
 486  473       */
      474 +    @Override
 487  475      abstract public int hashCode();
 488  476  
 489  477      /**
 490  478       * Default constructor.  This constructor is
 491  479       * protected so subclasses can get access to it. Users typically create
 492  480       * a Collator sub-class by calling the factory method getInstance.
 493  481       * @see java.text.Collator#getInstance
 494  482       */
 495  483      protected Collator()
 496  484      {
 497  485          strength = TERTIARY;
 498  486          decmp = CANONICAL_DECOMPOSITION;
 499  487      }
 500  488  
 501  489      private int strength = 0;
 502  490      private int decmp = 0;
 503      -    private static SoftCache cache = new SoftCache();
      491 +    private static final ConcurrentMap<Locale, SoftReference<Collator>> cache
      492 +            = new ConcurrentHashMap<>();
 504  493  
 505  494      //
 506  495      // FIXME: These three constants should be removed.
 507  496      //
 508  497      /**
 509  498       * LESS is returned if source string is compared to be less than target
 510  499       * string in the compare() method.
 511  500       * @see java.text.Collator#compare
 512  501       */
 513  502      final static int LESS = -1;
↓ open down ↓ 2 lines elided ↑ open up ↑
 516  505       * string in the compare() method.
 517  506       * @see java.text.Collator#compare
 518  507       */
 519  508      final static int EQUAL = 0;
 520  509      /**
 521  510       * GREATER is returned if source string is compared to be greater than
 522  511       * target string in the compare() method.
 523  512       * @see java.text.Collator#compare
 524  513       */
 525  514      final static int GREATER = 1;
 526      -
 527      -    /**
 528      -     * Obtains a Collator instance from a CollatorProvider
 529      -     * implementation.
 530      -     */
 531      -    private static class CollatorGetter
 532      -        implements LocaleServiceProviderPool.LocalizedObjectGetter<CollatorProvider, Collator> {
 533      -        private static final CollatorGetter INSTANCE = new CollatorGetter();
 534      -
 535      -        public Collator getObject(CollatorProvider collatorProvider,
 536      -                                Locale locale,
 537      -                                String key,
 538      -                                Object... params) {
 539      -            assert params.length == 1;
 540      -            Collator result = collatorProvider.getInstance(locale);
 541      -            if (result != null) {
 542      -                // put this Collator instance in the cache for two locales, one
 543      -                // is for the desired locale, and the other is for the actual
 544      -                // locale where the provider is found, which may be a fall back locale.
 545      -                cache.put((Locale)params[0], result);
 546      -                cache.put(locale, result);
 547      -                return (Collator)result.clone();
 548      -            }
 549      -
 550      -            return null;
 551      -        }
 552      -    }
 553  515   }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX