]> gitweb.fperrin.net Git - Dictionary.git/blobdiff - jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/util/ULocale.java
Upgrade ICU4J.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / core / src / com / ibm / icu / util / ULocale.java
similarity index 94%
rename from jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/util/ULocale.java
rename to jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/util/ULocale.java
index c533e8c297e462dc006b5015fcbac0db48fa3755..f6e8f0bfdeb0ea24e72cdb993975d3d524a3bd27 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
-* Copyright (C) 2003-2011, International Business Machines Corporation and   *
-* others. All Rights Reserved.                                               *
+* Copyright (C) 2003-2013, International Business Machines Corporation and
+* others. All Rights Reserved.
 ******************************************************************************
 */
 
@@ -10,6 +10,9 @@ package com.ibm.icu.util;
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.text.ParseException;
 import java.util.Iterator;
 import java.util.List;
@@ -528,26 +531,92 @@ public final class ULocale implements Serializable {
      * Keep our own default ULocale.
      */
     private static Locale defaultLocale = Locale.getDefault();
-    private static ULocale defaultULocale = forLocale(defaultLocale);
+    private static ULocale defaultULocale;
 
     private static Locale[] defaultCategoryLocales = new Locale[Category.values().length];
     private static ULocale[] defaultCategoryULocales = new ULocale[Category.values().length];
 
     static {
-        for (Category cat: Category.values()) {
-            int idx = cat.ordinal();
-            defaultCategoryLocales[idx] = JDKLocaleHelper.getDefault(cat);
-            defaultCategoryULocales[idx] = forLocale(defaultCategoryLocales[idx]);
+        defaultULocale = forLocale(defaultLocale);
+
+        // For Java 6 or older JRE, ICU initializes the default script from
+        // "user.script" system property. The system property was added
+        // in Java 7. On JRE 7, Locale.getDefault() should reflect the
+        // property value to the Locale's default. So ICU just relies on
+        // Locale.getDefault().
+        
+        // Note: The "user.script" property is only used by initialization.
+        // 
+        if (JDKLocaleHelper.isJava7orNewer()) {
+            for (Category cat: Category.values()) {
+                int idx = cat.ordinal();
+                defaultCategoryLocales[idx] = JDKLocaleHelper.getDefault(cat);
+                defaultCategoryULocales[idx] = forLocale(defaultCategoryLocales[idx]);
+            }
+        } else {
+            // Make sure the current default Locale is original.
+            // If not, it means that someone updated the default Locale.
+            // In this case, user.XXX properties are already out of date
+            // and we should not use user.script.
+            if (JDKLocaleHelper.isOriginalDefaultLocale(defaultLocale)) {
+                // Use "user.script" if available
+                String userScript = JDKLocaleHelper.getSystemProperty("user.script");
+                if (userScript != null && LanguageTag.isScript(userScript)) {
+                    // Note: Builder or forLanguageTag cannot be used here
+                    // when one of Locale fields is not well-formed.
+                    BaseLocale base = defaultULocale.base();
+                    BaseLocale newBase = BaseLocale.getInstance(base.getLanguage(), userScript,
+                            base.getRegion(), base.getVariant());
+                    defaultULocale = getInstance(newBase, defaultULocale.extensions());
+                }
+            }
+
+            // Java 6 or older does not have separated category locales,
+            // use the non-category default for all
+            for (Category cat: Category.values()) {
+                int idx = cat.ordinal();
+                defaultCategoryLocales[idx] = defaultLocale;
+                defaultCategoryULocales[idx] = defaultULocale;
+            }
         }
     }
 
     /**
      * Returns the current default ULocale.
+     * <p>
+     * The default ULocale is synchronized to the default Java Locale. This method checks
+     * the current default Java Locale and returns an equivalent ULocale.
+     * <p>
+     * <b>Note:</b> Before Java 7, the JDK Locale was not able to represent a locale's script.
+     * Therefore, the script field in the default ULocale is always empty unless
+     * a ULocale with non-empty script is explicitly set by {@link #setDefault(ULocale)}
+     * on Java 6 or older systems.
+     * <p>
+     * <b>Note for ICU 49 or later:</b> Some JRE implementations allow users to override the default
+     * JDK Locale using system properties - <code>user.language</code>, <code>user.country</code>
+     * and <code>user.variant</code>. In addition to these system properties, some Java 7
+     * implementations support <code>user.script</code> for overriding the default Locale's script.
+     * ICU 49 and later versions use the <code>user.script</code> system property on Java 6
+     * or older systems supporting other <code>user.*</code> system properties to initialize
+     * the default ULocale. The <code>user.script</code> override for default ULocale is not
+     * used on Java 7, or if the current Java default Locale is changed after start up.
+     * 
      * @return the default ULocale.
      * @stable ICU 2.8
      */
     public static ULocale getDefault() {
         synchronized (ULocale.class) {
+            if (defaultULocale == null) {
+                // When Java's default locale has extensions (such as ja-JP-u-ca-japanese),
+                // Locale -> ULocale mapping requires BCP47 keyword mapping data that is currently
+                // stored in a resource bundle. However, UResourceBundle currently requires
+                // non-null default ULocale. For now, this implementation returns ULocale.ROOT
+                // to avoid the problem.
+
+                // TODO: Consider moving BCP47 mapping data out of resource bundle later.
+
+                return ULocale.ROOT;
+            }
             Locale currentDefault = Locale.getDefault();
             if (!defaultLocale.equals(currentDefault)) {
                 defaultLocale = currentDefault;
@@ -689,7 +758,7 @@ public final class ULocale implements Serializable {
 
     /**
      * Returns true if the other object is another ULocale with the
-     * same full name, or is a String localeID that matches the full name.
+     * same full name.
      * Note that since names are not canonicalized, two ULocales that
      * function identically might not compare equal.
      *
@@ -700,9 +769,6 @@ public final class ULocale implements Serializable {
         if (this == obj) {
             return true;
         }
-        if (obj instanceof String) {
-            return localeID.equals((String)obj);
-        }
         if (obj instanceof ULocale) {
             return localeID.equals(((ULocale)obj).localeID);
         }
@@ -871,7 +937,9 @@ public final class ULocale implements Serializable {
     }
 
     /**
-     * {@icu} Returns the (normalized) base name for this locale.
+     * {@icu} Returns the (normalized) base name for this locale,
+     * like {@link #getName()}, but without keywords.
+     *
      * @return the base name as a String.
      * @stable ICU 3.0
      */
@@ -880,7 +948,9 @@ public final class ULocale implements Serializable {
     }
 
     /**
-     * {@icu} Returns the (normalized) base name for the specified locale.
+     * {@icu} Returns the (normalized) base name for the specified locale,
+     * like {@link #getName(String)}, but without keywords.
+     *
      * @param localeID the locale ID as a string
      * @return the base name as a String.
      * @stable ICU 3.0
@@ -1077,10 +1147,13 @@ public final class ULocale implements Serializable {
 
     /**
      * Given a keyword and a value, return a new locale with an updated
-     * keyword and value.  If keyword is null, this removes all keywords from the locale id.
+     * keyword and value.  If the keyword is null, this removes all keywords from the locale id.
      * Otherwise, if the value is null, this removes the value for this keyword from the
      * locale id.  Otherwise, this adds/replaces the value for this keyword in the locale id.
      * The keyword and value must not be empty.
+     *
+     * <p>Related: {@link #getBaseName()} returns the locale ID string with all keywords removed.
+     *
      * @param keyword the keyword to add/remove, or null to remove all keywords.
      * @param value the value to add/set, or null to remove this particular keyword.
      * @return the updated locale
@@ -1092,10 +1165,13 @@ public final class ULocale implements Serializable {
 
     /**
      * Given a locale id, a keyword, and a value, return a new locale id with an updated
-     * keyword and value.  If keyword is null, this removes all keywords from the locale id.
+     * keyword and value.  If the keyword is null, this removes all keywords from the locale id.
      * Otherwise, if the value is null, this removes the value for this keyword from the
      * locale id.  Otherwise, this adds/replaces the value for this keyword in the locale id.
      * The keyword and value must not be empty.
+     *
+     * <p>Related: {@link #getBaseName(String)} returns the locale ID string with all keywords removed.
+     *
      * @param localeID the locale id to modify
      * @param keyword the keyword to add/remove, or null to remove all keywords.
      * @param value the value to add/set, or null to remove this particular keyword.
@@ -1286,6 +1362,17 @@ public final class ULocale implements Serializable {
         return getDisplayScriptInternal(this, getDefault(Category.DISPLAY));
     }
 
+    /**
+     * {@icu} Returns this locale's script localized for display in the default <code>DISPLAY</code> locale.
+     * @return the localized script name.
+     * @see Category#DISPLAY
+     * @internal ICU 49
+     * @deprecated This API is ICU internal only.
+     */
+    public String getDisplayScriptInContext() {
+        return getDisplayScriptInContextInternal(this, getDefault(Category.DISPLAY));
+    }
+
     /**
      * {@icu} Returns this locale's script localized for display in the provided locale.
      * @param displayLocale the locale in which to display the name.
@@ -1296,6 +1383,17 @@ public final class ULocale implements Serializable {
         return getDisplayScriptInternal(this, displayLocale);
     }
 
+    /**
+     * {@icu} Returns this locale's script localized for display in the provided locale.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized script name.
+     * @internal ICU 49
+     * @deprecated This API is ICU internal only.
+     */
+    public String getDisplayScriptInContext(ULocale displayLocale) {
+        return getDisplayScriptInContextInternal(this, displayLocale);
+    }
+
     /**
      * {@icu} Returns a locale's script localized for display in the provided locale.
      * This is a cover for the ICU4C API.
@@ -1307,6 +1405,18 @@ public final class ULocale implements Serializable {
     public static String getDisplayScript(String localeID, String displayLocaleID) {
         return getDisplayScriptInternal(new ULocale(localeID), new ULocale(displayLocaleID));
     }
+    /**
+     * {@icu} Returns a locale's script localized for display in the provided locale.
+     * This is a cover for the ICU4C API.
+     * @param localeID the id of the locale whose script will be displayed
+     * @param displayLocaleID the id of the locale in which to display the name.
+     * @return the localized script name.
+     * @internal ICU 49
+     * @deprecated This API is ICU internal only.
+     */
+    public static String getDisplayScriptInContext(String localeID, String displayLocaleID) {
+        return getDisplayScriptInContextInternal(new ULocale(localeID), new ULocale(displayLocaleID));
+    }
 
     /**
      * {@icu} Returns a locale's script localized for display in the provided locale.
@@ -1318,6 +1428,17 @@ public final class ULocale implements Serializable {
     public static String getDisplayScript(String localeID, ULocale displayLocale) {
         return getDisplayScriptInternal(new ULocale(localeID), displayLocale);
     }
+    /**
+     * {@icu} Returns a locale's script localized for display in the provided locale.
+     * @param localeID the id of the locale whose script will be displayed.
+     * @param displayLocale the locale in which to display the name.
+     * @return the localized script name.
+     * @internal ICU 49
+     * @deprecated This API is ICU internal only.
+     */
+    public static String getDisplayScriptInContext(String localeID, ULocale displayLocale) {
+        return getDisplayScriptInContextInternal(new ULocale(localeID), displayLocale);
+    }
 
     // displayLocaleID is canonical, localeID need not be since parsing will fix this.
     private static String getDisplayScriptInternal(ULocale locale, ULocale displayLocale) {
@@ -1325,6 +1446,11 @@ public final class ULocale implements Serializable {
             .scriptDisplayName(locale.getScript());
     }
 
+    private static String getDisplayScriptInContextInternal(ULocale locale, ULocale displayLocale) {
+        return LocaleDisplayNames.getInstance(displayLocale)
+            .scriptDisplayNameInContext(locale.getScript());
+    }
+
     /**
      * Returns this locale's country localized for display in the default <code>DISPLAY</code> locale.
      * @return the localized country name.
@@ -2680,8 +2806,7 @@ public final class ULocale implements Serializable {
      * @see #getExtension(char)
      * @see Builder#setExtension(char, String)
      *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public static final char PRIVATE_USE_EXTENSION = 'x';
 
@@ -2691,8 +2816,7 @@ public final class ULocale implements Serializable {
      * @see #getExtension(char)
      * @see Builder#setExtension(char, String)
      *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public static final char UNICODE_LOCALE_EXTENSION = 'u';
 
@@ -2710,8 +2834,7 @@ public final class ULocale implements Serializable {
      * @see #PRIVATE_USE_EXTENSION
      * @see #UNICODE_LOCALE_EXTENSION
      *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public String getExtension(char key) {
         if (!LocaleExtensions.isValidKey(key)) {
@@ -2727,8 +2850,7 @@ public final class ULocale implements Serializable {
      *
      * @return the set of extension keys, or the empty set if this locale has
      * no extensions
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public Set<Character> getExtensionKeys() {
         return extensions().getKeys();
@@ -2740,8 +2862,7 @@ public final class ULocale implements Serializable {
      * returned set is unmodifiable.
      *
      * @return The set of attributes.
-     * @draft ICU 4.6
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.6
      */
     public Set<String> getUnicodeLocaleAttributes() {
         return extensions().getUnicodeLocaleAttributes();
@@ -2760,8 +2881,7 @@ public final class ULocale implements Serializable {
      * @throws IllegalArgumentException if the key is not well-formed
      * @throws NullPointerException if <code>key</code> is null
      * 
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.4
      */
     public String getUnicodeLocaleType(String key) {
         if (!LocaleExtensions.isValidUnicodeLocaleKey(key)) {
@@ -2777,8 +2897,7 @@ public final class ULocale implements Serializable {
      * @return The set of Unicode locale keys, or the empty set if this locale has
      * no Unicode locale keywords.
      * 
-     * @draft ICU 4.4
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.4
      */
     public Set<String> getUnicodeLocaleKeys() {
         return extensions().getUnicodeLocaleKeys();
@@ -2837,8 +2956,7 @@ public final class ULocale implements Serializable {
      * @return a BCP47 language tag representing the locale
      * @see #forLanguageTag(String)
      *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public String toLanguageTag() {
         BaseLocale base = base();
@@ -3008,8 +3126,7 @@ public final class ULocale implements Serializable {
      * @see #toLanguageTag()
      * @see ULocale.Builder#setLanguageTag(String)
      *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public static ULocale forLanguageTag(String languageTag) {
         LanguageTag tag = LanguageTag.parse(languageTag, null);
@@ -3051,8 +3168,7 @@ public final class ULocale implements Serializable {
      *
      * @see ULocale#toLanguageTag()
      *
-     * @draft ICU 4.2
-     * @provisional This API might change or be removed in a future release.
+     * @stable ICU 4.2
      */
     public static final class Builder {
 
@@ -3063,8 +3179,7 @@ public final class ULocale implements Serializable {
          * fields, extensions, and private use information is the
          * empty string.
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder() {
             _locbld = new InternalLocaleBuilder();
@@ -3085,8 +3200,7 @@ public final class ULocale implements Serializable {
          * any ill-formed fields.
          * @throws NullPointerException if <code>locale</code> is null.
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setLocale(ULocale locale) {
             try {
@@ -3114,8 +3228,7 @@ public final class ULocale implements Serializable {
          * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed
          * @see ULocale#forLanguageTag(String)
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setLanguageTag(String languageTag) {
             ParseStatus sts = new ParseStatus();
@@ -3141,8 +3254,7 @@ public final class ULocale implements Serializable {
          * @return This builder.
          * @throws IllformedLocaleException if <code>language</code> is ill-formed
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setLanguage(String language) {
             try {
@@ -3164,8 +3276,7 @@ public final class ULocale implements Serializable {
          * @return This builder.
          * @throws IllformedLocaleException if <code>script</code> is ill-formed
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setScript(String script) {
             try {
@@ -3191,8 +3302,7 @@ public final class ULocale implements Serializable {
          * @return This builder.
          * @throws IllformedLocaleException if <code>region</code> is ill-formed
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setRegion(String region) {
             try {
@@ -3219,8 +3329,7 @@ public final class ULocale implements Serializable {
          * @return This builder.
          * @throws IllformedLocaleException if <code>variant</code> is ill-formed
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setVariant(String variant) {
             try {
@@ -3253,8 +3362,7 @@ public final class ULocale implements Serializable {
          * or <code>value</code> is ill-formed
          * @see #setUnicodeLocaleKeyword(String, String)
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder setExtension(char key, String value) {
             try {
@@ -3285,8 +3393,7 @@ public final class ULocale implements Serializable {
          * @throws NullPointerException if <code>key</code> is null
          * @see #setExtension(char, String)
          *
-         * @draft ICU 4.4
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.4
          */
         public Builder setUnicodeLocaleKeyword(String key, String type) {
             try {
@@ -3308,8 +3415,7 @@ public final class ULocale implements Serializable {
          * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
          * @see #setExtension(char, String)
          *
-         * @draft ICU 4.6
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.6
          */
         public Builder addUnicodeLocaleAttribute(String attribute) {
             try {
@@ -3333,8 +3439,7 @@ public final class ULocale implements Serializable {
          * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
          * @see #setExtension(char, String)
          *
-         * @draft ICU 4.6
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.6
          */
         public Builder removeUnicodeLocaleAttribute(String attribute) {
             try {
@@ -3350,8 +3455,7 @@ public final class ULocale implements Serializable {
          *
          * @return this builder
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder clear() {
             _locbld.clear();
@@ -3365,8 +3469,7 @@ public final class ULocale implements Serializable {
          * @return this builder
          * @see #setExtension(char, String)
          *
-         * @draft ICU 4.2
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.2
          */
         public Builder clearExtensions() {
             _locbld.clearExtensions();
@@ -3379,8 +3482,7 @@ public final class ULocale implements Serializable {
          *
          * @return a new Locale
          *
-         * @draft ICU 4.4
-         * @provisional This API might change or be removed in a future release.
+         * @stable ICU 4.4
          */
         public ULocale build() {
             return getInstance(_locbld.getBaseLocale(), _locbld.getLocaleExtensions());
@@ -3407,7 +3509,7 @@ public final class ULocale implements Serializable {
                         String bcpType = uext.getUnicodeLocaleType(bcpKey);
                         // convert to legacy key/type
                         String lkey = bcp47ToLDMLKey(bcpKey);
-                        String ltype = bcp47ToLDMLType(lkey, ((bcpType.length() == 0) ? "true" : bcpType)); // use "true" as the value of typeless keywords
+                        String ltype = bcp47ToLDMLType(lkey, ((bcpType.length() == 0) ? "yes" : bcpType)); // use "yes" as the value of typeless keywords
                         // special handling for u-va-posix, since this is a variant, not a keyword
                         if (lkey.equals("va") && ltype.equals("posix") && base.getVariant().length() == 0) {
                             id = id + "_POSIX";
@@ -3861,8 +3963,8 @@ public final class ULocale implements Serializable {
                     if (kwKey.length() != 1) {
                         // Unicode locale key
                         kwKey = bcp47ToLDMLKey(kwKey);
-                        // use "true" as the value of typeless keywords
-                        kwVal = bcp47ToLDMLType(kwKey, ((kwVal.length() == 0) ? "true" : kwVal));
+                        // use "yes" as the value of typeless keywords
+                        kwVal = bcp47ToLDMLType(kwKey, ((kwVal.length() == 0) ? "yes" : kwVal));
                     }
 
                     if (addSep) {
@@ -4011,5 +4113,47 @@ public final class ULocale implements Serializable {
                 }
             }
         }
+
+        // Returns true if the given Locale matches the original
+        // default locale initialized by JVM by checking user.XXX
+        // system properties. When the system properties are not accessible,
+        // this method returns false.
+        public static boolean isOriginalDefaultLocale(Locale loc) {
+            if (isJava7orNewer) {
+                String script = "";
+                try {
+                    script = (String) mGetScript.invoke(loc, (Object[]) null);
+                } catch (Exception e) {
+                    return false;
+                }
+
+                return loc.getLanguage().equals(getSystemProperty("user.language"))
+                        && loc.getCountry().equals(getSystemProperty("user.country"))
+                        && loc.getVariant().equals(getSystemProperty("user.variant"))
+                        && script.equals(getSystemProperty("user.script"));
+            }
+            return loc.getLanguage().equals(getSystemProperty("user.language"))
+                    && loc.getCountry().equals(getSystemProperty("user.country"))
+                    && loc.getVariant().equals(getSystemProperty("user.variant"));
+        }
+
+        public static String getSystemProperty(String key) {
+            String val = null;
+            final String fkey = key;
+            if (System.getSecurityManager() != null) {
+                try {
+                    val = AccessController.doPrivileged(new PrivilegedAction<String>() {
+                        public String run() {
+                            return System.getProperty(fkey);
+                        }
+                    });
+                } catch (AccessControlException e) {
+                    // ignore
+                }
+            } else {
+                val = System.getProperty(fkey);
+            }
+            return val;
+        }
     }
 }