Save This Page
Home » openjdk-7 » java » util » [javadoc | source]
    1   /*
    2    * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   /*
   27    * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
   28    * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
   29    *
   30    * The original version of this source code and documentation
   31    * is copyrighted and owned by Taligent, Inc., a wholly-owned
   32    * subsidiary of IBM. These materials are provided under terms
   33    * of a License Agreement between Taligent and Sun. This technology
   34    * is protected by multiple US and International patents.
   35    *
   36    * This notice and attribution to Taligent may not be removed.
   37    * Taligent is a registered trademark of Taligent, Inc.
   38    *
   39    */
   40   
   41   package java.util;
   42   
   43   import java.io;
   44   import java.security.AccessController;
   45   import java.text.MessageFormat;
   46   import java.util.List;
   47   import java.util.concurrent.ConcurrentHashMap;
   48   import java.util.spi.LocaleNameProvider;
   49   import java.util.spi.LocaleServiceProvider;
   50   import sun.security.action.GetPropertyAction;
   51   import sun.util.LocaleServiceProviderPool;
   52   import sun.util.resources.LocaleData;
   53   import sun.util.resources.OpenListResourceBundle;
   54   
   55   /**
   56    *
   57    * A <code>Locale</code> object represents a specific geographical, political,
   58    * or cultural region. An operation that requires a <code>Locale</code> to perform
   59    * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
   60    * to tailor information for the user. For example, displaying a number
   61    * is a locale-sensitive operation--the number should be formatted
   62    * according to the customs/conventions of the user's native country,
   63    * region, or culture.
   64    *
   65    * <P>
   66    * Create a <code>Locale</code> object using the constructors in this class:
   67    * <blockquote>
   68    * <pre>
   69    * Locale(String language)
   70    * Locale(String language, String country)
   71    * Locale(String language, String country, String variant)
   72    * </pre>
   73    * </blockquote>
   74    * The language argument is a valid <STRONG>ISO Language Code.</STRONG>
   75    * These codes are the lower-case, two-letter codes as defined by ISO-639.
   76    * You can find a full list of these codes at a number of sites, such as:
   77    * <BR><a href ="http://www.loc.gov/standards/iso639-2/php/English_list.php">
   78    * <code>http://www.loc.gov/standards/iso639-2/php/English_list.php</code></a>
   79    *
   80    * <P>
   81    * The country argument is a valid <STRONG>ISO Country Code.</STRONG> These
   82    * codes are the upper-case, two-letter codes as defined by ISO-3166.
   83    * You can find a full list of these codes at a number of sites, such as:
   84    * <BR><a href="http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">
   85    * <code>http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html</code></a>
   86    *
   87    * <P>
   88    * The variant argument is a vendor or browser-specific code.
   89    * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX.
   90    * Where there are two variants, separate them with an underscore, and
   91    * put the most important one first. For example, a Traditional Spanish collation
   92    * might construct a locale with parameters for language, country and variant as:
   93    * "es", "ES", "Traditional_WIN".
   94    *
   95    * <P>
   96    * Because a <code>Locale</code> object is just an identifier for a region,
   97    * no validity check is performed when you construct a <code>Locale</code>.
   98    * If you want to see whether particular resources are available for the
   99    * <code>Locale</code> you construct, you must query those resources. For
  100    * example, ask the <code>NumberFormat</code> for the locales it supports
  101    * using its <code>getAvailableLocales</code> method.
  102    * <BR><STRONG>Note:</STRONG> When you ask for a resource for a particular
  103    * locale, you get back the best available match, not necessarily
  104    * precisely what you asked for. For more information, look at
  105    * {@link ResourceBundle}.
  106    *
  107    * <P>
  108    * The <code>Locale</code> class provides a number of convenient constants
  109    * that you can use to create <code>Locale</code> objects for commonly used
  110    * locales. For example, the following creates a <code>Locale</code> object
  111    * for the United States:
  112    * <blockquote>
  113    * <pre>
  114    * Locale.US
  115    * </pre>
  116    * </blockquote>
  117    *
  118    * <P>
  119    * Once you've created a <code>Locale</code> you can query it for information about
  120    * itself. Use <code>getCountry</code> to get the ISO Country Code and
  121    * <code>getLanguage</code> to get the ISO Language Code. You can
  122    * use <code>getDisplayCountry</code> to get the
  123    * name of the country suitable for displaying to the user. Similarly,
  124    * you can use <code>getDisplayLanguage</code> to get the name of
  125    * the language suitable for displaying to the user. Interestingly,
  126    * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
  127    * and have two versions: one that uses the default locale and one
  128    * that uses the locale specified as an argument.
  129    *
  130    * <P>
  131    * The Java Platform provides a number of classes that perform locale-sensitive
  132    * operations. For example, the <code>NumberFormat</code> class formats
  133    * numbers, currency, or percentages in a locale-sensitive manner. Classes
  134    * such as <code>NumberFormat</code> have a number of convenience methods
  135    * for creating a default object of that type. For example, the
  136    * <code>NumberFormat</code> class provides these three convenience methods
  137    * for creating a default <code>NumberFormat</code> object:
  138    * <blockquote>
  139    * <pre>
  140    * NumberFormat.getInstance()
  141    * NumberFormat.getCurrencyInstance()
  142    * NumberFormat.getPercentInstance()
  143    * </pre>
  144    * </blockquote>
  145    * These methods have two variants; one with an explicit locale
  146    * and one without; the latter using the default locale.
  147    * <blockquote>
  148    * <pre>
  149    * NumberFormat.getInstance(myLocale)
  150    * NumberFormat.getCurrencyInstance(myLocale)
  151    * NumberFormat.getPercentInstance(myLocale)
  152    * </pre>
  153    * </blockquote>
  154    * A <code>Locale</code> is the mechanism for identifying the kind of object
  155    * (<code>NumberFormat</code>) that you would like to get. The locale is
  156    * <STRONG>just</STRONG> a mechanism for identifying objects,
  157    * <STRONG>not</STRONG> a container for the objects themselves.
  158    *
  159    * @see         ResourceBundle
  160    * @see         java.text.Format
  161    * @see         java.text.NumberFormat
  162    * @see         java.text.Collator
  163    * @author      Mark Davis
  164    * @since       1.1
  165    */
  166   
  167   public final class Locale implements Cloneable, Serializable {
  168   
  169       // cache to store singleton Locales
  170       private final static ConcurrentHashMap<String, Locale> cache =
  171           new ConcurrentHashMap<String, Locale>(32);
  172   
  173       /** Useful constant for language.
  174        */
  175       static public final Locale ENGLISH = createSingleton("en__", "en", "");
  176   
  177       /** Useful constant for language.
  178        */
  179       static public final Locale FRENCH = createSingleton("fr__", "fr", "");
  180   
  181       /** Useful constant for language.
  182        */
  183       static public final Locale GERMAN = createSingleton("de__", "de", "");
  184   
  185       /** Useful constant for language.
  186        */
  187       static public final Locale ITALIAN = createSingleton("it__", "it", "");
  188   
  189       /** Useful constant for language.
  190        */
  191       static public final Locale JAPANESE = createSingleton("ja__", "ja", "");
  192   
  193       /** Useful constant for language.
  194        */
  195       static public final Locale KOREAN = createSingleton("ko__", "ko", "");
  196   
  197       /** Useful constant for language.
  198        */
  199       static public final Locale CHINESE = createSingleton("zh__", "zh", "");
  200   
  201       /** Useful constant for language.
  202        */
  203       static public final Locale SIMPLIFIED_CHINESE = createSingleton("zh_CN_", "zh", "CN");
  204   
  205       /** Useful constant for language.
  206        */
  207       static public final Locale TRADITIONAL_CHINESE = createSingleton("zh_TW_", "zh", "TW");
  208   
  209       /** Useful constant for country.
  210        */
  211       static public final Locale FRANCE = createSingleton("fr_FR_", "fr", "FR");
  212   
  213       /** Useful constant for country.
  214        */
  215       static public final Locale GERMANY = createSingleton("de_DE_", "de", "DE");
  216   
  217       /** Useful constant for country.
  218        */
  219       static public final Locale ITALY = createSingleton("it_IT_", "it", "IT");
  220   
  221       /** Useful constant for country.
  222        */
  223       static public final Locale JAPAN = createSingleton("ja_JP_", "ja", "JP");
  224   
  225       /** Useful constant for country.
  226        */
  227       static public final Locale KOREA = createSingleton("ko_KR_", "ko", "KR");
  228   
  229       /** Useful constant for country.
  230        */
  231       static public final Locale CHINA = SIMPLIFIED_CHINESE;
  232   
  233       /** Useful constant for country.
  234        */
  235       static public final Locale PRC = SIMPLIFIED_CHINESE;
  236   
  237       /** Useful constant for country.
  238        */
  239       static public final Locale TAIWAN = TRADITIONAL_CHINESE;
  240   
  241       /** Useful constant for country.
  242        */
  243       static public final Locale UK = createSingleton("en_GB_", "en", "GB");
  244   
  245       /** Useful constant for country.
  246        */
  247       static public final Locale US = createSingleton("en_US_", "en", "US");
  248   
  249       /** Useful constant for country.
  250        */
  251       static public final Locale CANADA = createSingleton("en_CA_", "en", "CA");
  252   
  253       /** Useful constant for country.
  254        */
  255       static public final Locale CANADA_FRENCH = createSingleton("fr_CA_", "fr", "CA");
  256   
  257       /**
  258        * Useful constant for the root locale.  The root locale is the locale whose
  259        * language, country, and variant are empty ("") strings.  This is regarded
  260        * as the base locale of all locales, and is used as the language/country
  261        * neutral locale for the locale sensitive operations.
  262        *
  263        * @since 1.6
  264        */
  265       static public final Locale ROOT = createSingleton("__", "", "");
  266   
  267       /** serialization ID
  268        */
  269       static final long serialVersionUID = 9149081749638150636L;
  270   
  271       /**
  272        * Display types for retrieving localized names from the name providers.
  273        */
  274       private static final int DISPLAY_LANGUAGE = 0;
  275       private static final int DISPLAY_COUNTRY  = 1;
  276       private static final int DISPLAY_VARIANT  = 2;
  277   
  278       /**
  279        * Construct a locale from language, country, variant.
  280        * NOTE:  ISO 639 is not a stable standard; some of the language codes it defines
  281        * (specifically iw, ji, and in) have changed.  This constructor accepts both the
  282        * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
  283        * API on Locale will return only the OLD codes.
  284        * @param language lowercase two-letter ISO-639 code.
  285        * @param country uppercase two-letter ISO-3166 code.
  286        * @param variant vendor and browser specific code. See class description.
  287        * @exception NullPointerException thrown if any argument is null.
  288        */
  289       public Locale(String language, String country, String variant) {
  290           this.language = convertOldISOCodes(language);
  291           this.country = toUpperCase(country).intern();
  292           this.variant = variant.intern();
  293       }
  294   
  295       /**
  296        * Construct a locale from language, country.
  297        * NOTE:  ISO 639 is not a stable standard; some of the language codes it defines
  298        * (specifically iw, ji, and in) have changed.  This constructor accepts both the
  299        * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
  300        * API on Locale will return only the OLD codes.
  301        * @param language lowercase two-letter ISO-639 code.
  302        * @param country uppercase two-letter ISO-3166 code.
  303        * @exception NullPointerException thrown if either argument is null.
  304        */
  305       public Locale(String language, String country) {
  306           this(language, country, "");
  307       }
  308   
  309       /**
  310        * Construct a locale from a language code.
  311        * NOTE:  ISO 639 is not a stable standard; some of the language codes it defines
  312        * (specifically iw, ji, and in) have changed.  This constructor accepts both the
  313        * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
  314        * API on Locale will return only the OLD codes.
  315        * @param language lowercase two-letter ISO-639 code.
  316        * @exception NullPointerException thrown if argument is null.
  317        * @since 1.4
  318        */
  319       public Locale(String language) {
  320           this(language, "", "");
  321       }
  322   
  323       /**
  324        * Constructs a <code>Locale</code> using <code>language</code>
  325        * and <code>country</code>.  This constructor assumes that
  326        * <code>language</code> and <code>contry</code> are interned and
  327        * it is invoked by createSingleton only. (flag is just for
  328        * avoiding the conflict with the public constructors.
  329        */
  330       private Locale(String language, String country, boolean flag) {
  331           this.language = language;
  332           this.country = country;
  333           this.variant = "";
  334       }
  335   
  336       /**
  337        * Creates a <code>Locale</code> instance with the given
  338        * <code>language</code> and <code>counry</code> and puts the
  339        * instance under the given <code>key</code> in the cache. This
  340        * method must be called only when initializing the Locale
  341        * constants.
  342        */
  343       private static Locale createSingleton(String key, String language, String country) {
  344           Locale locale = new Locale(language, country, false);
  345           cache.put(key, locale);
  346           return locale;
  347       }
  348   
  349       /**
  350        * Returns a <code>Locale</code> constructed from the given
  351        * <code>language</code>, <code>country</code> and
  352        * <code>variant</code>. If the same <code>Locale</code> instance
  353        * is available in the cache, then that instance is
  354        * returned. Otherwise, a new <code>Locale</code> instance is
  355        * created and cached.
  356        *
  357        * @param language lowercase two-letter ISO-639 code.
  358        * @param country uppercase two-letter ISO-3166 code.
  359        * @param variant vendor and browser specific code. See class description.
  360        * @return the <code>Locale</code> instance requested
  361        * @exception NullPointerException if any argument is null.
  362        */
  363       static Locale getInstance(String language, String country, String variant) {
  364           if (language== null || country == null || variant == null) {
  365               throw new NullPointerException();
  366           }
  367   
  368           StringBuilder sb = new StringBuilder();
  369           sb.append(language).append('_').append(country).append('_').append(variant);
  370           String key = sb.toString();
  371           Locale locale = cache.get(key);
  372           if (locale == null) {
  373               locale = new Locale(language, country, variant);
  374               Locale l = cache.putIfAbsent(key, locale);
  375               if (l != null) {
  376                   locale = l;
  377               }
  378           }
  379           return locale;
  380       }
  381   
  382       /**
  383        * Gets the current value of the default locale for this instance
  384        * of the Java Virtual Machine.
  385        * <p>
  386        * The Java Virtual Machine sets the default locale during startup
  387        * based on the host environment. It is used by many locale-sensitive
  388        * methods if no locale is explicitly specified.
  389        * It can be changed using the
  390        * {@link #setDefault(java.util.Locale) setDefault} method.
  391        *
  392        * @return the default locale for this instance of the Java Virtual Machine
  393        */
  394       public static Locale getDefault() {
  395           // do not synchronize this method - see 4071298
  396           // it's OK if more than one default locale happens to be created
  397           if (defaultLocale == null) {
  398               String language, region, country, variant;
  399               language = AccessController.doPrivileged(
  400                   new GetPropertyAction("user.language", "en"));
  401               // for compatibility, check for old user.region property
  402               region = AccessController.doPrivileged(
  403                   new GetPropertyAction("user.region"));
  404               if (region != null) {
  405                   // region can be of form country, country_variant, or _variant
  406                   int i = region.indexOf('_');
  407                   if (i >= 0) {
  408                       country = region.substring(0, i);
  409                       variant = region.substring(i + 1);
  410                   } else {
  411                       country = region;
  412                       variant = "";
  413                   }
  414               } else {
  415                   country = AccessController.doPrivileged(
  416                       new GetPropertyAction("user.country", ""));
  417                   variant = AccessController.doPrivileged(
  418                       new GetPropertyAction("user.variant", ""));
  419               }
  420               defaultLocale = getInstance(language, country, variant);
  421           }
  422           return defaultLocale;
  423       }
  424   
  425       /**
  426        * Sets the default locale for this instance of the Java Virtual Machine.
  427        * This does not affect the host locale.
  428        * <p>
  429        * If there is a security manager, its <code>checkPermission</code>
  430        * method is called with a <code>PropertyPermission("user.language", "write")</code>
  431        * permission before the default locale is changed.
  432        * <p>
  433        * The Java Virtual Machine sets the default locale during startup
  434        * based on the host environment. It is used by many locale-sensitive
  435        * methods if no locale is explicitly specified.
  436        * <p>
  437        * Since changing the default locale may affect many different areas
  438        * of functionality, this method should only be used if the caller
  439        * is prepared to reinitialize locale-sensitive code running
  440        * within the same Java Virtual Machine.
  441        *
  442        * @throws SecurityException
  443        *        if a security manager exists and its
  444        *        <code>checkPermission</code> method doesn't allow the operation.
  445        * @throws NullPointerException if <code>newLocale</code> is null
  446        * @param newLocale the new default locale
  447        * @see SecurityManager#checkPermission
  448        * @see java.util.PropertyPermission
  449        */
  450       public static synchronized void setDefault(Locale newLocale) {
  451           if (newLocale == null)
  452               throw new NullPointerException("Can't set default locale to NULL");
  453   
  454           SecurityManager sm = System.getSecurityManager();
  455           if (sm != null) sm.checkPermission(new PropertyPermission
  456                           ("user.language", "write"));
  457               defaultLocale = newLocale;
  458       }
  459   
  460       /**
  461        * Returns an array of all installed locales.
  462        * The returned array represents the union of locales supported
  463        * by the Java runtime environment and by installed
  464        * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
  465        * implementations.  It must contain at least a <code>Locale</code>
  466        * instance equal to {@link java.util.Locale#US Locale.US}.
  467        *
  468        * @return An array of installed locales.
  469        */
  470       public static Locale[] getAvailableLocales() {
  471           return LocaleServiceProviderPool.getAllAvailableLocales();
  472       }
  473   
  474       /**
  475        * Returns a list of all 2-letter country codes defined in ISO 3166.
  476        * Can be used to create Locales.
  477        */
  478       public static String[] getISOCountries() {
  479           if (isoCountries == null) {
  480               isoCountries = getISO2Table(LocaleISOData.isoCountryTable);
  481           }
  482           String[] result = new String[isoCountries.length];
  483           System.arraycopy(isoCountries, 0, result, 0, isoCountries.length);
  484           return result;
  485       }
  486   
  487       /**
  488        * Returns a list of all 2-letter language codes defined in ISO 639.
  489        * Can be used to create Locales.
  490        * [NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
  491        * The list this function returns includes both the new and the old codes for the
  492        * languages whose codes have changed.]
  493        */
  494       public static String[] getISOLanguages() {
  495           if (isoLanguages == null) {
  496               isoLanguages = getISO2Table(LocaleISOData.isoLanguageTable);
  497           }
  498           String[] result = new String[isoLanguages.length];
  499           System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
  500           return result;
  501       }
  502   
  503       private static final String[] getISO2Table(String table) {
  504           int len = table.length() / 5;
  505           String[] isoTable = new String[len];
  506           for (int i = 0, j = 0; i < len; i++, j += 5) {
  507               isoTable[i] = table.substring(j, j + 2);
  508           }
  509           return isoTable;
  510       }
  511   
  512       /**
  513        * Returns the language code for this locale, which will either be the empty string
  514        * or a lowercase ISO 639 code.
  515        * <p>NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
  516        * Locale's constructor recognizes both the new and the old codes for the languages
  517        * whose codes have changed, but this function always returns the old code.  If you
  518        * want to check for a specific language whose code has changed, don't do <pre>
  519        * if (locale.getLanguage().equals("he"))
  520        *    ...
  521        * </pre>Instead, do<pre>
  522        * if (locale.getLanguage().equals(new Locale("he", "", "").getLanguage()))
  523        *    ...</pre>
  524        * @see #getDisplayLanguage
  525        */
  526       public String getLanguage() {
  527           return language;
  528       }
  529   
  530       /**
  531        * Returns the country/region code for this locale, which will
  532        * either be the empty string or an uppercase ISO 3166 2-letter code.
  533        * @see #getDisplayCountry
  534        */
  535       public String getCountry() {
  536           return country;
  537       }
  538   
  539       /**
  540        * Returns the variant code for this locale.
  541        * @see #getDisplayVariant
  542        */
  543       public String getVariant() {
  544           return variant;
  545       }
  546   
  547       /**
  548        * Getter for the programmatic name of the entire locale,
  549        * with the language, country and variant separated by underbars.
  550        * Language is always lower case, and country is always upper case.
  551        * If the language is missing, the string will begin with an underbar.
  552        * If both the language and country fields are missing, this function
  553        * will return the empty string, even if the variant field is filled in
  554        * (you can't have a locale with just a variant-- the variant must accompany
  555        * a valid language or country code).
  556        * Examples: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC"
  557        * @see #getDisplayName
  558        */
  559       public final String toString() {
  560           boolean l = language.length() != 0;
  561           boolean c = country.length() != 0;
  562           boolean v = variant.length() != 0;
  563           StringBuilder result = new StringBuilder(language);
  564           if (c||(l&&v)) {
  565               result.append('_').append(country); // This may just append '_'
  566           }
  567           if (v&&(l||c)) {
  568               result.append('_').append(variant);
  569           }
  570           return result.toString();
  571       }
  572   
  573       /**
  574        * Returns a three-letter abbreviation for this locale's language.  If the locale
  575        * doesn't specify a language, this will be the empty string.  Otherwise, this will
  576        * be a lowercase ISO 639-2/T language code.
  577        * The ISO 639-2 language codes can be found on-line at
  578        * <a href="http://www.loc.gov/standards/iso639-2/englangn.html">
  579        * <code>http://www.loc.gov/standards/iso639-2/englangn.html</code>.</a>
  580        * @exception MissingResourceException Throws MissingResourceException if the
  581        * three-letter language abbreviation is not available for this locale.
  582        */
  583       public String getISO3Language() throws MissingResourceException {
  584           String language3 = getISO3Code(language, LocaleISOData.isoLanguageTable);
  585           if (language3 == null) {
  586               throw new MissingResourceException("Couldn't find 3-letter language code for "
  587                       + language, "FormatData_" + toString(), "ShortLanguage");
  588           }
  589           return language3;
  590       }
  591   
  592       /**
  593        * Returns a three-letter abbreviation for this locale's country.  If the locale
  594        * doesn't specify a country, this will be the empty string.  Otherwise, this will
  595        * be an uppercase ISO 3166 3-letter country code.
  596        * The ISO 3166-2 country codes can be found on-line at
  597        * <a href="http://www.davros.org/misc/iso3166.txt">
  598        * <code>http://www.davros.org/misc/iso3166.txt</code>.</a>
  599        * @exception MissingResourceException Throws MissingResourceException if the
  600        * three-letter country abbreviation is not available for this locale.
  601        */
  602       public String getISO3Country() throws MissingResourceException {
  603           String country3 = getISO3Code(country, LocaleISOData.isoCountryTable);
  604           if (country3 == null) {
  605               throw new MissingResourceException("Couldn't find 3-letter country code for "
  606                       + country, "FormatData_" + toString(), "ShortCountry");
  607           }
  608           return country3;
  609       }
  610   
  611       private static final String getISO3Code(String iso2Code, String table) {
  612           int codeLength = iso2Code.length();
  613           if (codeLength == 0) {
  614               return "";
  615           }
  616   
  617           int tableLength = table.length();
  618           int index = tableLength;
  619           if (codeLength == 2) {
  620               char c1 = iso2Code.charAt(0);
  621               char c2 = iso2Code.charAt(1);
  622               for (index = 0; index < tableLength; index += 5) {
  623                   if (table.charAt(index) == c1
  624                       && table.charAt(index + 1) == c2) {
  625                       break;
  626                   }
  627               }
  628           }
  629           return index < tableLength ? table.substring(index + 2, index + 5) : null;
  630       }
  631   
  632       /**
  633        * Returns a name for the locale's language that is appropriate for display to the
  634        * user.
  635        * If possible, the name returned will be localized for the default locale.
  636        * For example, if the locale is fr_FR and the default locale
  637        * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
  638        * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
  639        * If the name returned cannot be localized for the default locale,
  640        * (say, we don't have a Japanese name for Croatian),
  641        * this function falls back on the English name, and uses the ISO code as a last-resort
  642        * value.  If the locale doesn't specify a language, this function returns the empty string.
  643        */
  644       public final String getDisplayLanguage() {
  645           return getDisplayLanguage(getDefault());
  646       }
  647   
  648       /**
  649        * Returns a name for the locale's language that is appropriate for display to the
  650        * user.
  651        * If possible, the name returned will be localized according to inLocale.
  652        * For example, if the locale is fr_FR and inLocale
  653        * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
  654        * inLocale is fr_FR, getDisplayLanguage() will return "anglais".
  655        * If the name returned cannot be localized according to inLocale,
  656        * (say, we don't have a Japanese name for Croatian),
  657        * this function falls back on the English name, and finally
  658        * on the ISO code as a last-resort value.  If the locale doesn't specify a language,
  659        * this function returns the empty string.
  660        *
  661        * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  662        */
  663       public String getDisplayLanguage(Locale inLocale) {
  664           return getDisplayString(language, inLocale, DISPLAY_LANGUAGE);
  665       }
  666   
  667       /**
  668        * Returns a name for the locale's country that is appropriate for display to the
  669        * user.
  670        * If possible, the name returned will be localized for the default locale.
  671        * For example, if the locale is fr_FR and the default locale
  672        * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
  673        * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis".
  674        * If the name returned cannot be localized for the default locale,
  675        * (say, we don't have a Japanese name for Croatia),
  676        * this function falls back on the English name, and uses the ISO code as a last-resort
  677        * value.  If the locale doesn't specify a country, this function returns the empty string.
  678        */
  679       public final String getDisplayCountry() {
  680           return getDisplayCountry(getDefault());
  681       }
  682   
  683       /**
  684        * Returns a name for the locale's country that is appropriate for display to the
  685        * user.
  686        * If possible, the name returned will be localized according to inLocale.
  687        * For example, if the locale is fr_FR and inLocale
  688        * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
  689        * inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis".
  690        * If the name returned cannot be localized according to inLocale.
  691        * (say, we don't have a Japanese name for Croatia),
  692        * this function falls back on the English name, and finally
  693        * on the ISO code as a last-resort value.  If the locale doesn't specify a country,
  694        * this function returns the empty string.
  695        *
  696        * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  697        */
  698       public String getDisplayCountry(Locale inLocale) {
  699           return getDisplayString(country, inLocale, DISPLAY_COUNTRY);
  700       }
  701   
  702       private String getDisplayString(String code, Locale inLocale, int type) {
  703           if (code.length() == 0) {
  704               return "";
  705           }
  706   
  707           if (inLocale == null) {
  708               throw new NullPointerException();
  709           }
  710   
  711           try {
  712               OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  713               String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
  714               String result = null;
  715   
  716               // Check whether a provider can provide an implementation that's closer
  717               // to the requested locale than what the Java runtime itself can provide.
  718               LocaleServiceProviderPool pool =
  719                   LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
  720               if (pool.hasProviders()) {
  721                   result = pool.getLocalizedObject(
  722                                       LocaleNameGetter.INSTANCE,
  723                                       inLocale, bundle, key,
  724                                       type, code);
  725               }
  726   
  727               if (result == null) {
  728                   result = bundle.getString(key);
  729               }
  730   
  731               if (result != null) {
  732                   return result;
  733               }
  734           }
  735           catch (Exception e) {
  736               // just fall through
  737           }
  738           return code;
  739       }
  740   
  741       /**
  742        * Returns a name for the locale's variant code that is appropriate for display to the
  743        * user.  If possible, the name will be localized for the default locale.  If the locale
  744        * doesn't specify a variant code, this function returns the empty string.
  745        */
  746       public final String getDisplayVariant() {
  747           return getDisplayVariant(getDefault());
  748       }
  749   
  750       /**
  751        * Returns a name for the locale's variant code that is appropriate for display to the
  752        * user.  If possible, the name will be localized for inLocale.  If the locale
  753        * doesn't specify a variant code, this function returns the empty string.
  754        *
  755        * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  756        */
  757       public String getDisplayVariant(Locale inLocale) {
  758           if (variant.length() == 0)
  759               return "";
  760   
  761           OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  762   
  763           String names[] = getDisplayVariantArray(bundle, inLocale);
  764   
  765           // Get the localized patterns for formatting a list, and use
  766           // them to format the list.
  767           String listPattern = null;
  768           String listCompositionPattern = null;
  769           try {
  770               listPattern = bundle.getString("ListPattern");
  771               listCompositionPattern = bundle.getString("ListCompositionPattern");
  772           } catch (MissingResourceException e) {
  773           }
  774           return formatList(names, listPattern, listCompositionPattern);
  775       }
  776   
  777       /**
  778        * Returns a name for the locale that is appropriate for display to the
  779        * user.  This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
  780        * and getDisplayVariant() assembled into a single string.  The display name will have
  781        * one of the following forms:<p><blockquote>
  782        * language (country, variant)<p>
  783        * language (country)<p>
  784        * language (variant)<p>
  785        * country (variant)<p>
  786        * language<p>
  787        * country<p>
  788        * variant<p></blockquote>
  789        * depending on which fields are specified in the locale.  If the language, country,
  790        * and variant fields are all empty, this function returns the empty string.
  791        */
  792       public final String getDisplayName() {
  793           return getDisplayName(getDefault());
  794       }
  795   
  796       /**
  797        * Returns a name for the locale that is appropriate for display to the
  798        * user.  This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
  799        * and getDisplayVariant() assembled into a single string.  The display name will have
  800        * one of the following forms:<p><blockquote>
  801        * language (country, variant)<p>
  802        * language (country)<p>
  803        * language (variant)<p>
  804        * country (variant)<p>
  805        * language<p>
  806        * country<p>
  807        * variant<p></blockquote>
  808        * depending on which fields are specified in the locale.  If the language, country,
  809        * and variant fields are all empty, this function returns the empty string.
  810        *
  811        * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
  812        */
  813       public String getDisplayName(Locale inLocale) {
  814           OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  815   
  816           String languageName = getDisplayLanguage(inLocale);
  817           String countryName = getDisplayCountry(inLocale);
  818           String[] variantNames = getDisplayVariantArray(bundle, inLocale);
  819   
  820           // Get the localized patterns for formatting a display name.
  821           String displayNamePattern = null;
  822           String listPattern = null;
  823           String listCompositionPattern = null;
  824           try {
  825               displayNamePattern = bundle.getString("DisplayNamePattern");
  826               listPattern = bundle.getString("ListPattern");
  827               listCompositionPattern = bundle.getString("ListCompositionPattern");
  828           } catch (MissingResourceException e) {
  829           }
  830   
  831           // The display name consists of a main name, followed by qualifiers.
  832           // Typically, the format is "MainName (Qualifier, Qualifier)" but this
  833           // depends on what pattern is stored in the display locale.
  834           String   mainName       = null;
  835           String[] qualifierNames = null;
  836   
  837           // The main name is the language, or if there is no language, the country.
  838           // If there is neither language nor country (an anomalous situation) then
  839           // the display name is simply the variant's display name.
  840           if (languageName.length() != 0) {
  841               mainName = languageName;
  842               if (countryName.length() != 0) {
  843                   qualifierNames = new String[variantNames.length + 1];
  844                   System.arraycopy(variantNames, 0, qualifierNames, 1, variantNames.length);
  845                   qualifierNames[0] = countryName;
  846               }
  847               else qualifierNames = variantNames;
  848           }
  849           else if (countryName.length() != 0) {
  850               mainName = countryName;
  851               qualifierNames = variantNames;
  852           }
  853           else {
  854               return formatList(variantNames, listPattern, listCompositionPattern);
  855           }
  856   
  857           // Create an array whose first element is the number of remaining
  858           // elements.  This serves as a selector into a ChoiceFormat pattern from
  859           // the resource.  The second and third elements are the main name and
  860           // the qualifier; if there are no qualifiers, the third element is
  861           // unused by the format pattern.
  862           Object[] displayNames = {
  863               new Integer(qualifierNames.length != 0 ? 2 : 1),
  864               mainName,
  865               // We could also just call formatList() and have it handle the empty
  866               // list case, but this is more efficient, and we want it to be
  867               // efficient since all the language-only locales will not have any
  868               // qualifiers.
  869               qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null
  870           };
  871   
  872           if (displayNamePattern != null) {
  873               return new MessageFormat(displayNamePattern).format(displayNames);
  874           }
  875           else {
  876               // If we cannot get the message format pattern, then we use a simple
  877               // hard-coded pattern.  This should not occur in practice unless the
  878               // installation is missing some core files (FormatData etc.).
  879               StringBuilder result = new StringBuilder();
  880               result.append((String)displayNames[1]);
  881               if (displayNames.length > 2) {
  882                   result.append(" (");
  883                   result.append((String)displayNames[2]);
  884                   result.append(')');
  885               }
  886               return result.toString();
  887           }
  888       }
  889   
  890       /**
  891        * Overrides Cloneable
  892        */
  893       public Object clone()
  894       {
  895           try {
  896               Locale that = (Locale)super.clone();
  897               return that;
  898           } catch (CloneNotSupportedException e) {
  899               throw new InternalError();
  900           }
  901       }
  902   
  903       /**
  904        * Override hashCode.
  905        * Since Locales are often used in hashtables, caches the value
  906        * for speed.
  907        */
  908       public int hashCode() {
  909           int hc = hashCodeValue;
  910           if (hc == 0) {
  911               hc = (language.hashCode() << 8) ^ country.hashCode() ^ (variant.hashCode() << 4);
  912               hashCodeValue = hc;
  913           }
  914           return hc;
  915       }
  916   
  917       // Overrides
  918   
  919       /**
  920        * Returns true if this Locale is equal to another object.  A Locale is
  921        * deemed equal to another Locale with identical language, country,
  922        * and variant, and unequal to all other objects.
  923        *
  924        * @return true if this Locale is equal to the specified object.
  925        */
  926   
  927       public boolean equals(Object obj) {
  928           if (this == obj)                      // quick check
  929               return true;
  930           if (!(obj instanceof Locale))
  931               return false;
  932           Locale other = (Locale) obj;
  933           return language == other.language
  934               && country == other.country
  935               && variant == other.variant;
  936       }
  937   
  938       // ================= privates =====================================
  939   
  940       // XXX instance and class variables. For now keep these separate, since it is
  941       // faster to match. Later, make into single string.
  942   
  943       /**
  944        * @serial
  945        * @see #getLanguage
  946        */
  947       private final String language;
  948   
  949       /**
  950        * @serial
  951        * @see #getCountry
  952        */
  953       private final String country;
  954   
  955       /**
  956        * @serial
  957        * @see #getVariant
  958        */
  959       private final String variant;
  960   
  961       /**
  962        * Placeholder for the object's hash code.  Always -1.
  963        * @serial
  964        */
  965       private volatile int hashcode = -1;        // lazy evaluate
  966   
  967       /**
  968        * Calculated hashcode to fix 4518797.
  969        */
  970       private transient volatile int hashCodeValue = 0;
  971   
  972       private static Locale defaultLocale = null;
  973   
  974       /**
  975        * Return an array of the display names of the variant.
  976        * @param bundle the ResourceBundle to use to get the display names
  977        * @return an array of display names, possible of zero length.
  978        */
  979       private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
  980           // Split the variant name into tokens separated by '_'.
  981           StringTokenizer tokenizer = new StringTokenizer(variant, "_");
  982           String[] names = new String[tokenizer.countTokens()];
  983   
  984           // For each variant token, lookup the display name.  If
  985           // not found, use the variant name itself.
  986           for (int i=0; i<names.length; ++i) {
  987               names[i] = getDisplayString(tokenizer.nextToken(),
  988                                   inLocale, DISPLAY_VARIANT);
  989           }
  990   
  991           return names;
  992       }
  993   
  994       /**
  995        * Format a list using given pattern strings.
  996        * If either of the patterns is null, then a the list is
  997        * formatted by concatenation with the delimiter ','.
  998        * @param stringList the list of strings to be formatted.
  999        * @param listPattern should create a MessageFormat taking 0-3 arguments
 1000        * and formatting them into a list.
 1001        * @param listCompositionPattern should take 2 arguments
 1002        * and is used by composeList.
 1003        * @return a string representing the list.
 1004        */
 1005       private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
 1006           // If we have no list patterns, compose the list in a simple,
 1007           // non-localized way.
 1008           if (listPattern == null || listCompositionPattern == null) {
 1009               StringBuffer result = new StringBuffer();
 1010               for (int i=0; i<stringList.length; ++i) {
 1011                   if (i>0) result.append(',');
 1012                   result.append(stringList[i]);
 1013               }
 1014               return result.toString();
 1015           }
 1016   
 1017           // Compose the list down to three elements if necessary
 1018           if (stringList.length > 3) {
 1019               MessageFormat format = new MessageFormat(listCompositionPattern);
 1020               stringList = composeList(format, stringList);
 1021           }
 1022   
 1023           // Rebuild the argument list with the list length as the first element
 1024           Object[] args = new Object[stringList.length + 1];
 1025           System.arraycopy(stringList, 0, args, 1, stringList.length);
 1026           args[0] = new Integer(stringList.length);
 1027   
 1028           // Format it using the pattern in the resource
 1029           MessageFormat format = new MessageFormat(listPattern);
 1030           return format.format(args);
 1031       }
 1032   
 1033       /**
 1034        * Given a list of strings, return a list shortened to three elements.
 1035        * Shorten it by applying the given format to the first two elements
 1036        * recursively.
 1037        * @param format a format which takes two arguments
 1038        * @param list a list of strings
 1039        * @return if the list is three elements or shorter, the same list;
 1040        * otherwise, a new list of three elements.
 1041        */
 1042       private static String[] composeList(MessageFormat format, String[] list) {
 1043           if (list.length <= 3) return list;
 1044   
 1045           // Use the given format to compose the first two elements into one
 1046           String[] listItems = { list[0], list[1] };
 1047           String newItem = format.format(listItems);
 1048   
 1049           // Form a new list one element shorter
 1050           String[] newList = new String[list.length-1];
 1051           System.arraycopy(list, 2, newList, 1, newList.length-1);
 1052           newList[0] = newItem;
 1053   
 1054           // Recurse
 1055           return composeList(format, newList);
 1056       }
 1057   
 1058       /**
 1059        * Replace the deserialized Locale object with a newly
 1060        * created object. Newer language codes are replaced with older ISO
 1061        * codes. The country and variant codes are replaced with internalized
 1062        * String copies.
 1063        */
 1064       private Object readResolve() throws java.io.ObjectStreamException {
 1065           return getInstance(language, country, variant);
 1066       }
 1067   
 1068       private static volatile String[] isoLanguages = null;
 1069   
 1070       private static volatile String[] isoCountries = null;
 1071   
 1072       /*
 1073        * Locale needs its own, locale insensitive version of toLowerCase to
 1074        * avoid circularity problems between Locale and String.
 1075        * The most straightforward algorithm is used. Look at optimizations later.
 1076        */
 1077       private String toLowerCase(String str) {
 1078           char[] buf = new char[str.length()];
 1079           for (int i = 0; i < buf.length; i++) {
 1080               buf[i] = Character.toLowerCase(str.charAt(i));
 1081           }
 1082           return new String( buf );
 1083       }
 1084   
 1085       /*
 1086        * Locale needs its own, locale insensitive version of toUpperCase to
 1087        * avoid circularity problems between Locale and String.
 1088        * The most straightforward algorithm is used. Look at optimizations later.
 1089        */
 1090       private String toUpperCase(String str) {
 1091           char[] buf = new char[str.length()];
 1092           for (int i = 0; i < buf.length; i++) {
 1093               buf[i] = Character.toUpperCase(str.charAt(i));
 1094           }
 1095           return new String( buf );
 1096       }
 1097   
 1098       private String convertOldISOCodes(String language) {
 1099           // we accept both the old and the new ISO codes for the languages whose ISO
 1100           // codes have changed, but we always store the OLD code, for backward compatibility
 1101           language = toLowerCase(language).intern();
 1102           if (language == "he") {
 1103               return "iw";
 1104           } else if (language == "yi") {
 1105               return "ji";
 1106           } else if (language == "id") {
 1107               return "in";
 1108           } else {
 1109               return language;
 1110           }
 1111       }
 1112   
 1113       /**
 1114        * Obtains a localized locale names from a LocaleNameProvider
 1115        * implementation.
 1116        */
 1117       private static class LocaleNameGetter
 1118           implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
 1119           private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
 1120   
 1121           public String getObject(LocaleNameProvider localeNameProvider,
 1122                                   Locale locale,
 1123                                   String key,
 1124                                   Object... params) {
 1125               assert params.length == 2;
 1126               int type = (Integer)params[0];
 1127               String code = (String)params[1];
 1128   
 1129               switch(type) {
 1130               case DISPLAY_LANGUAGE:
 1131                   return localeNameProvider.getDisplayLanguage(code, locale);
 1132               case DISPLAY_COUNTRY:
 1133                   return localeNameProvider.getDisplayCountry(code, locale);
 1134               case DISPLAY_VARIANT:
 1135                   return localeNameProvider.getDisplayVariant(code, locale);
 1136               default:
 1137                   assert false; // shouldn't happen
 1138               }
 1139   
 1140               return null;
 1141           }
 1142       }
 1143   }

Save This Page
Home » openjdk-7 » java » util » [javadoc | source]