ICU-12085 Implement J support for new CLDR locale key "rg"
authorPeter Edberg <pedberg@unicode.org>
Tue, 16 Feb 2016 07:11:10 +0000 (07:11 +0000)
committerPeter Edberg <pedberg@unicode.org>
Tue, 16 Feb 2016 07:11:10 +0000 (07:11 +0000)
X-SVN-Rev: 38313

icu4j/main/classes/core/src/com/ibm/icu/impl/CalendarUtil.java
icu4j/main/classes/core/src/com/ibm/icu/impl/locale/KeyTypeData.java
icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java
icu4j/main/classes/core/src/com/ibm/icu/util/LocaleData.java
icu4j/main/classes/core/src/com/ibm/icu/util/ULocale.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/IBMCalendarTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/LocaleDataTest.java

index c43675be412effba67e9f631cb1b34d2c412a153..ba46800acab8d54f3d60674aab3cae4000def7a7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2009, International Business Machines Corporation and         *
+ * Copyright (C) 2009,2016 International Business Machines Corporation and         *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -44,56 +44,51 @@ public class CalendarUtil {
             return calType;
         }
 
-        String baseLoc = loc.getBaseName();
-
-        // Check the cache
-        calType = CALTYPE_CACHE.get(baseLoc);
+        // Canonicalize, so grandfathered variant will be transformed to keywords
+        ULocale canonical = ULocale.createCanonical(loc.toString());
+        calType = canonical.getKeywordValue(CALKEY);
         if (calType != null) {
             return calType;
         }
 
-        // Canonicalize, so grandfathered variant will be transformed to keywords
-        ULocale canonical = ULocale.createCanonical(loc.toString());
-        calType = canonical.getKeywordValue("calendar");
+        // When calendar keyword is not available, use the locale's
+        // region to get the default calendar type
+        String region = ULocale.getRegionForSupplementalData(canonical, true);
 
-        if (calType == null) {
-            // When calendar keyword is not available, use the locale's
-            // region to get the default calendar type
-            String region = canonical.getCountry();
-            if (region.length() == 0) {
-                ULocale fullLoc = ULocale.addLikelySubtags(canonical);
-                region = fullLoc.getCountry();
-            }
+        // Check the cache (now we cache by region, not base locale)
+        calType = CALTYPE_CACHE.get(region);
+        if (calType != null) {
+            return calType;
+        }
 
-            // Read supplementalData to get the default calendar type for
-            // the locale's region
+        // Read supplementalData to get the default calendar type for
+        // the locale's region
+        try {
+            UResourceBundle rb = UResourceBundle.getBundleInstance(
+                                    ICUResourceBundle.ICU_BASE_NAME,
+                                    "supplementalData",
+                                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
+            UResourceBundle calPref = rb.get("calendarPreferenceData");
+            UResourceBundle order = null;
             try {
-                UResourceBundle rb = UResourceBundle.getBundleInstance(
-                                        ICUResourceBundle.ICU_BASE_NAME,
-                                        "supplementalData",
-                                        ICUResourceBundle.ICU_DATA_CLASS_LOADER);
-                UResourceBundle calPref = rb.get("calendarPreferenceData");
-                UResourceBundle order = null;
-                try {
-                    order = calPref.get(region);
-                } catch (MissingResourceException mre) {
-                    // use "001" as fallback
-                    order = calPref.get("001");
-                }
-                // the first calendar type is the default for the region
-                calType = order.getString(0);
+                order = calPref.get(region);
             } catch (MissingResourceException mre) {
-                // fall through
+                // use "001" as fallback
+                order = calPref.get("001");
             }
+            // the first calendar type is the default for the region
+            calType = order.getString(0);
+        } catch (MissingResourceException mre) {
+            // fall through
+        }
 
-            if (calType == null) {
-                // Use "gregorian" as the last resort fallback.
-                calType = DEFCAL;
-            }
+        if (calType == null) {
+            // Use "gregorian" as the last resort fallback.
+            calType = DEFCAL;
         }
 
         // Cache the resolved value for the next time
-        CALTYPE_CACHE.put(baseLoc, calType);
+        CALTYPE_CACHE.put(region, calType);
 
         return calType;
     }
index f1de704254582591ae5881d47dabb13dd5cf3d8b..72819f141da62c9ed876e617be9a7f288b8a50c9 100644 (file)
@@ -46,9 +46,17 @@ public class KeyTypeData {
         }
     }
 
+    private static class RgKeyValueTypeHandler extends SpecialTypeHandler {
+        private static final Pattern pat = Pattern.compile("[a-zA-Z]{2}[zZ]{4}");
+        boolean isValid(String value) {
+            return pat.matcher(value).matches();
+        }
+    }
+
     private enum SpecialType {
         CODEPOINTS(new CodepointsTypeHandler()),
-        REORDER_CODE(new ReorderCodeTypeHandler());
+        REORDER_CODE(new ReorderCodeTypeHandler()),
+        RG_KEY_VALUE(new RgKeyValueTypeHandler());
 
         SpecialTypeHandler handler;
         SpecialType(SpecialTypeHandler handler) {
index 61d8276e9152c6f9a216af83864e710edc80b3f9..5a6b3f11cee0897d155164050fbeafea06c83b8c 100644 (file)
@@ -1764,13 +1764,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
     }
 
     private static String getRegionForCalendar(ULocale loc) {
-        String region = loc.getCountry();
+        String region = ULocale.getRegionForSupplementalData(loc, true);
         if (region.length() == 0) {
-            ULocale maxLocale = ULocale.addLikelySubtags(loc);
-            region = maxLocale.getCountry();
-            if (region.length() == 0) {
-                region = "001";
-            }
+            region = "001";
         }
         return region;
     }
@@ -1930,11 +1926,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
     public static final String[] getKeywordValuesForLocale(String key, ULocale locale,
             boolean commonlyUsed) {
         // Resolve region
-        String prefRegion = locale.getCountry();
-        if (prefRegion.length() == 0){
-            ULocale loc = ULocale.addLikelySubtags(locale);
-            prefRegion = loc.getCountry();
-        }
+        String prefRegion = ULocale.getRegionForSupplementalData(locale, true);
 
         // Read preferred calendar values from supplementalData calendarPreferences
         ArrayList<String> values = new ArrayList<String>();
index 832b256c10c447a2c50196fc1a2a418ca89d9a53..081a4799bc46655a67112a16add5062812aa06df 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2001-2015, International Business Machines Corporation and
+ * Copyright (C) 2001-2016, International Business Machines Corporation and
  * others. All Rights Reserved.
  *******************************************************************************
  */
@@ -181,7 +181,8 @@ public class Currency extends MeasureUnit {
      * @stable ICU 4.0
      */
     public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) {
-        CurrencyFilter filter = CurrencyFilter.onDate(d).withRegion(loc.getCountry());
+        String region = ULocale.getRegionForSupplementalData(loc, false);
+        CurrencyFilter filter = CurrencyFilter.onDate(d).withRegion(region);
         List<String> list = getTenderCurrencies(filter);
         // Note: Prior to 4.4 the spec didn't say that we return null if there are no results, but 
         // the test assumed it did.  Kept the behavior and amended the spec.
@@ -240,7 +241,7 @@ public class Currency extends MeasureUnit {
         
         String code = currencyCodeCache.get(loc);
         if (code == null) {
-            String country = loc.getCountry();
+            String country = ULocale.getRegionForSupplementalData(loc, false);
         
             CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
             List<String> list = info.currencies(CurrencyFilter.onRegion(country));
@@ -404,14 +405,10 @@ public class Currency extends MeasureUnit {
         
         // Don't resolve region if the requested locale is 'und', it will resolve to US
         // which we don't want.
-        String prefRegion = locale.getCountry();
-        if (prefRegion.length() == 0) {
-            if (UND.equals(locale)) {
-                return EMPTY_STRING_ARRAY;
-            }
-            ULocale loc = ULocale.addLikelySubtags(locale);
-            prefRegion = loc.getCountry();
-       }
+        if (UND.equals(locale)) {
+            return EMPTY_STRING_ARRAY;
+        }
+        String prefRegion = ULocale.getRegionForSupplementalData(locale, true);
 
         CurrencyFilter filter = CurrencyFilter.now().withRegion(prefRegion);
         
index e5197273e81e54d181d9c28d2cab7b440b7191ed..54f8b75ba8905727e82fa4bd2d6471ead7edc4f2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  **************************************************************************************
- * Copyright (C) 2009-2014, Google, Inc.; International Business Machines Corporation *
- * and others. All Rights Reserved.                                                   *
+ * Copyright (C) 2009-2016, International Business Machines Corporation,              *
+ * Google, Inc. and others. All Rights Reserved.                                      *
  **************************************************************************************
  */
 package com.ibm.icu.util;
@@ -290,8 +290,7 @@ public final class LocaleData {
     private static UResourceBundle measurementTypeBundleForLocale(ULocale locale, String measurementType){
         // Much of this is taken from getCalendarType in impl/CalendarUtil.java
         UResourceBundle measTypeBundle = null;
-        ULocale fullLoc = ULocale.addLikelySubtags(locale);
-        String region = fullLoc.getCountry();
+        String region = ULocale.getRegionForSupplementalData(locale, true);
         try {
             UResourceBundle rb = UResourceBundle.getBundleInstance(
                     ICUResourceBundle.ICU_BASE_NAME,
index 5c65e44aa38319bb569d381e9e692d2814c7722f..719eb41ae63f4d615666cfcc68cb37f541f70899 100644 (file)
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (C) 2003-2015, International Business Machines Corporation and
+ * Copyright (C) 2003-2016, International Business Machines Corporation and
  * others. All Rights Reserved.
  ******************************************************************************
  */
@@ -976,6 +976,44 @@ public final class ULocale implements Serializable, Comparable<ULocale> {
         return new LocaleIDParser(localeID).getCountry();
     }
 
+    /**
+     * {@icu} Get the region to use for supplemental data lookup.
+     * Uses
+     * (1) any region specified by locale tag "rg"; if none then
+     * (2) any unicode_region_tag in the locale ID; if none then
+     * (3) if inferRegion is TRUE, the region suggested by
+     *     getLikelySubtags on the localeID.
+     * If no region is found, returns empty string ""
+     *
+     * @param locale
+     *     The locale (includes any keywords) from which
+     *     to get the region to use for supplemental data.
+     * @param inferRegion
+     *     If TRUE, will try to infer region from other
+     *     locale elements if not found any other way.
+     * @return
+     *     String with region to use ("" if none found).
+     * @internal ICU 57
+     * @deprecated This API is ICU internal only.
+     */
+    @Deprecated
+    public static String getRegionForSupplementalData(
+                            ULocale locale, boolean inferRegion) {
+        String region = locale.getKeywordValue("rg");
+        if (region != null && region.length() == 6) {
+            String regionUpper = AsciiUtil.toUpperString(region);
+            if (regionUpper.endsWith("ZZZZ")) {
+               return regionUpper.substring(0,2);
+            }
+        }
+        region = locale.getCountry();
+        if (region.length() == 0 && inferRegion) {
+            ULocale maximized = addLikelySubtags(locale);
+            region = maximized.getCountry();
+        }
+        return region;
+    }
+
     /**
      * Returns the variant code for this locale, which might be the empty string.
      * @see #getDisplayVariant()
index dbf3dbd64ea7b3742159bf6b001437c0905dce19..97cc20cdd1729b074c75208f2cc6b75cffc20f1d 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2000-2014, International Business Machines Corporation and    *
+ * Copyright (C) 2000-2016, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -2117,6 +2117,7 @@ public class CalendarRegression extends com.ibm.icu.dev.test.TestFmwk {
             {"en@calendar=islamic",     "gregorian"},
             {"zh_TW",       "gregorian", "roc", "chinese"},
             {"ar_IR",       "persian", "gregorian", "islamic", "islamic-civil", "islamic-tbla"},
+            {"th@rg=SAZZZZ", "islamic-umalqura", "gregorian", "islamic", "islamic-rgsa"},
         };
 
         String[] ALL = Calendar.getKeywordValuesForLocale("calendar", ULocale.getDefault(), false);
@@ -2372,6 +2373,8 @@ public class CalendarRegression extends com.ibm.icu.dev.test.TestFmwk {
         
         Calendar aCalendar = Calendar.getInstance(Locale.US);
         assertEquals("US", usWeekData, aCalendar.getWeekData());
+        Calendar rgusCalendar = Calendar.getInstance(new ULocale("hi_IN@rg=USzzzz"));
+        assertEquals("IN@rg=US", usWeekData, rgusCalendar.getWeekData());
         
         aCalendar.setWeekData(testWeekData);
         assertEquals("Custom", testWeekData, aCalendar.getWeekData());
index 94f8f0caa41888672c84120ac5d0cbba70e6b3cd..be508cd37ea7ba24366693564ead5d058767df3d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2000-2014, International Business Machines Corporation and
+ * Copyright (C) 2000-2016, International Business Machines Corporation and
  * others. All Rights Reserved.
  *******************************************************************************
  */
@@ -1021,6 +1021,12 @@ public class IBMCalendarTest extends CalendarTest {
                 "th",       // th's default region is TH and buddhist is used as default for TH
                 "en_TH",    // Default calendar for any locales with region TH is buddhist
                 "th_TH@calendar=iso8601",   // iso8601 calendar type
+                "fr_CH",
+                "fr_SA",
+                "fr_CH@rg=sazzzz",
+                "fr_CH@calendar=japanese;rg=sazzzz",
+                "fr_TH@rg=SA",  // ignore malformed rg tag, use buddhist
+                "th@rg=SA",            // ignore malformed rg tag, use buddhist
         };
 
         String[] types = {
@@ -1037,7 +1043,13 @@ public class IBMCalendarTest extends CalendarTest {
                 "buddhist",
                 "buddhist",
                 "buddhist",
-                "gregorian",    // iso8601 is a gregiran sub type
+                "gregorian",    // iso8601 is a gregorian sub type
+                "gregorian",
+                "islamic-umalqura",
+                "islamic-umalqura",
+                "japanese",
+                "buddhist",
+                "buddhist",
         };
 
         for (int i = 0; i < locs.length; i++) {
index 561f10b2a9c67c5353f84701942be89512c79cae..c3a96044eccaf2ba705d38bff75c5d70341c331d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  **********************************************************************
- * Copyright (c) 2002-2015, International Business Machines
+ * Copyright (c) 2002-2016, International Business Machines
  * Corporation and others.  All Rights Reserved.
  **********************************************************************
  * Author: Alan Liu
@@ -636,6 +636,9 @@ public class CurrencyTest extends TestFmwk {
             {"en@currency=CAD",     "USD", "USN"},
             {"fr@currency=ZZZ",     "EUR"},
             {"de_DE@currency=DEM",  "EUR"},
+            {"en_US@rg=THZZZZ",     "THB"},
+            {"de@rg=USZZZZ",        "USD", "USN"},
+            {"en_US@currency=CAD;rg=THZZZZ",  "THB"},
         };
 
         String[] ALL = Currency.getKeywordValuesForLocale("currency", ULocale.getDefault(), false);
index b03de30ae3672991040898c5f89bf1bdb9242f3c..489f7433ff40d5471b9f22c390505f85aa649d2e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2003-2015, International Business Machines Corporation and    *
+ * Copyright (C) 2003-2016, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -106,6 +106,31 @@ public class LocaleDataTest extends TestFmwk{
         }
     }
 
+    public void TestMeasurementSysForSpecificLocales(){
+        class TestMeasurementSysItem {
+            public String localeID;
+            public LocaleData.MeasurementSystem measureSys;
+            public TestMeasurementSysItem(String locID, LocaleData.MeasurementSystem ms) {
+                localeID = locID;
+                measureSys = ms;
+            }
+        };
+        final TestMeasurementSysItem[] items = {
+            new TestMeasurementSysItem("fr_FR",             LocaleData.MeasurementSystem.SI),
+            new TestMeasurementSysItem("en",                LocaleData.MeasurementSystem.US),
+            new TestMeasurementSysItem("en_GB",             LocaleData.MeasurementSystem.UK),
+            new TestMeasurementSysItem("fr_FR@rg=GBZZZZ",   LocaleData.MeasurementSystem.UK),
+            new TestMeasurementSysItem("en@rg=frzzzz",      LocaleData.MeasurementSystem.SI),
+            new TestMeasurementSysItem("en_GB@rg=USZZZZ",   LocaleData.MeasurementSystem.US),
+        };
+        for (TestMeasurementSysItem item: items) {
+            LocaleData.MeasurementSystem ms = LocaleData.getMeasurementSystem(new ULocale(item.localeID));
+            if (ms != item.measureSys) {
+                errln("For locale " + item.localeID + ", expected " + item.measureSys + ", got " + ms);
+            }
+        }
+    }
+
     // Simple test case for checking exemplar character type coverage
     public void TestEnglishExemplarCharacters() {
         final char[] testChars = {