8167273: Calendar.getDisplayNames inconsistent with DateFormatSymbols
authorrgoel
Tue, 24 Jan 2017 12:06:03 +0530
changeset 43295 58870c7a62e0
parent 43282 45b751afd11e
child 43296 0f1ac3527db2
8167273: Calendar.getDisplayNames inconsistent with DateFormatSymbols Reviewed-by: naoto
jdk/make/gensrc/GensrcLocaleData.gmk
jdk/make/src/classes/build/tools/cldrconverter/Bundle.java
jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java
jdk/test/java/util/Calendar/Bug8167273.java
jdk/test/sun/util/locale/provider/Bug8038436.java
--- a/jdk/make/gensrc/GensrcLocaleData.gmk	Wed Jul 05 22:44:47 2017 +0200
+++ b/jdk/make/gensrc/GensrcLocaleData.gmk	Tue Jan 24 12:06:03 2017 +0530
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -89,8 +89,8 @@
   $1_NON_BASE_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_BASE_LOCALES))
   $1_NON_BASE_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_BASE_LOCALES))
 
-# Adding implict locales nn-NO and nb-NO
-  $1_NON_BASE_LOCALES += nn-NO  nb-NO
+# Adding implict locales nb nn-NO and nb-NO
+  $1_NON_BASE_LOCALES += nb  nn-NO  nb-NO
   $1_NON_BASE_LOCALES := $$(sort $$($1_NON_BASE_LOCALES))
 
   ALL_BASE_LOCALES += $$($1_BASE_LOCALES)
--- a/jdk/make/src/classes/build/tools/cldrconverter/Bundle.java	Wed Jul 05 22:44:47 2017 +0200
+++ b/jdk/make/src/classes/build/tools/cldrconverter/Bundle.java	Tue Jan 24 12:06:03 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -389,6 +389,18 @@
                 }
             }
         }
+        // replace empty era names with parentMap era names
+        for (String key : ERA_KEYS) {
+            Object value = myMap.get(key);
+            if (value != null && value instanceof String[]) {
+                String[] eraStrings = (String[]) value;
+                for (String eraString : eraStrings) {
+                    if (eraString == null || eraString.isEmpty()) {
+                        fillInElements(parentsMap, key, value);
+                    }
+                }
+            }
+        }
 
         // Remove all duplicates
         if (Objects.nonNull(parentsMap)) {
--- a/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java	Wed Jul 05 22:44:47 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java	Tue Jan 24 12:06:03 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -195,9 +195,26 @@
         return parent;
     }
 
+    /**
+     * This method returns equivalent CLDR supported locale for zh-HK,
+     * no, no-NO locales so that COMPAT locales do not precede
+     * those locales during ResourceBundle search path.
+     */
+    private static Locale getEquivalentLoc(Locale locale) {
+        switch (locale.toString()) {
+            case "zh_HK":
+                return Locale.forLanguageTag("zh-Hant-HK");
+            case "no":
+            case "no_NO":
+                return Locale.forLanguageTag("nb");
+        }
+        return locale;
+    }
+
     @Override
     public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
-        return Locale.ROOT.equals(locale) ||
-            langtags.contains(locale.stripExtensions().toLanguageTag());
+        return Locale.ROOT.equals(locale)
+                || langtags.contains(locale.stripExtensions().toLanguageTag())
+                || langtags.contains(getEquivalentLoc(locale).toLanguageTag());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug8167273.java	Tue Jan 24 12:06:03 2017 +0530
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8167273
+ * @summary Test
+ * Era names retrieved from Calendar and DateFormatSymbols class
+ * should match for default providers preference
+ * as well as when  preference list is [COMPAT, CLDR],
+ * Empty era names are not retrieved from DateformatSymbols class.
+ * Equivalent locales specified for [zh-HK, no-NO, no] for
+ * CLDR Provider works correctly.
+ * Implict COMPAT Locale nb is reflected in available locales
+ * for all Providers for COMPAT.
+ * @modules java.base/sun.util.locale.provider
+ *          java.base/sun.util.spi
+ *          jdk.localedata
+ * @run main/othervm -Djava.locale.providers=COMPAT,CLDR Bug8167273 testEraName
+ * @run main/othervm  Bug8167273 testEraName
+ * @run main/othervm -Djava.locale.providers=CLDR Bug8167273 testCldr
+ * @run main/othervm  Bug8167273 testEmptyEraNames
+ * @run main/othervm  -Djava.locale.providers=COMPAT Bug8167273 testCompat
+ */
+import java.text.DateFormatSymbols;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.LocaleProviderAdapter.Type;
+
+public class Bug8167273 {
+
+    public static void main(String[] args) throws Exception {
+        switch (args[0]) {
+            case "testEraName":
+                testEraName();
+                break;
+            case "testEmptyEraNames":
+                testEmptyEraNames();
+                break;
+            case "testCldr":
+                testCldrSupportedLocales();
+                break;
+            case "testCompat":
+                testCompatSupportedLocale();
+                break;
+            default:
+                throw new RuntimeException("no test was specified.");
+        }
+    }
+
+    /**
+     * tests that era names retrieved from Calendar.getDisplayNames map should
+     * match with that of Era names retrieved from DateFormatSymbols.getEras()
+     * method for all Gregorian Calendar locales .
+     */
+    public static void testEraName() {
+        Set<Locale> allLocales = Set.of(Locale.getAvailableLocales());
+        Set<Locale> JpThlocales = Set.of(
+                new Locale("th", "TH"),
+                new Locale("ja", "JP", "JP"), new Locale("th", "TH", "TH")
+        );
+        Set<Locale> allLocs = new HashSet<>(allLocales);
+        // Removing Japense and Thai Locales to check  Gregorian Calendar Locales
+        allLocs.removeAll(JpThlocales);
+        allLocs.forEach((locale) -> {
+            Calendar cal = Calendar.getInstance(locale);
+            Map<String, Integer> names = cal.getDisplayNames(Calendar.ERA, Calendar.ALL_STYLES, locale);
+            DateFormatSymbols symbols = new DateFormatSymbols(locale);
+            String[] eras = symbols.getEras();
+            for (String era : eras) {
+                if (!names.containsKey(era)) {
+                    reportMismatch(names.keySet(), eras, locale);
+                }
+            }
+        });
+    }
+
+    private static void reportMismatch(Set<String> CalendarEras, String[] dfsEras, Locale locale) {
+        System.out.println("For Locale  " + locale + "era names in calendar map are  " + CalendarEras);
+        for (String era : dfsEras) {
+            System.out.println("For Locale  " + locale + " era names in DateFormatSymbols era array are  " + era);
+        }
+        throw new RuntimeException(" Era name retrived from Calendar class do not match with"
+                + " retrieved from DateFormatSymbols  for Locale   " + locale);
+
+    }
+
+    /**
+     * tests that Eras names returned from DateFormatSymbols.getEras()
+     * and Calendar.getDisplayNames() should not be empty for any Locale.
+     */
+    private static void testEmptyEraNames() {
+        Set<Locale> allLocales = Set.of(Locale.getAvailableLocales());
+        allLocales.forEach((loc) -> {
+            DateFormatSymbols dfs = new DateFormatSymbols(loc);
+            Calendar cal = Calendar.getInstance(loc);
+            Map<String, Integer> names = cal.getDisplayNames(Calendar.ERA, Calendar.ALL_STYLES, loc);
+            Set<String> CalendarEraNames = names.keySet();
+            String[] eras = dfs.getEras();
+            for (String era : eras) {
+                if (era.isEmpty()) {
+                    throw new RuntimeException("Empty era names retrieved for DateFomatSymbols.getEras"
+                            + " for locale " + loc);
+                }
+            }
+            CalendarEraNames.stream().filter((erakey) -> (erakey.isEmpty())).forEachOrdered((l) -> {
+                throw new RuntimeException("Empty era names retrieved for Calendar.getDisplayName"
+                        + " for locale " + loc);
+            });
+        });
+
+    }
+
+    /**
+     * tests that CLDR provider should return true for locale zh_HK, no-NO and
+     * no.
+     */
+    private static void testCldrSupportedLocales() {
+        Set<Locale> locales = Set.of(Locale.forLanguageTag("zh-HK"),
+                Locale.forLanguageTag("no-NO"),
+                Locale.forLanguageTag("no"));
+        LocaleProviderAdapter cldr = LocaleProviderAdapter.forType(Type.CLDR);
+        Set<Locale> availableLocs = Set.of(cldr.getAvailableLocales());
+        Set<String> langtags = new HashSet<>();
+        availableLocs.forEach((loc) -> {
+            langtags.add(loc.toLanguageTag());
+        });
+
+        locales.stream().filter((loc) -> (!cldr.isSupportedProviderLocale(loc, langtags))).forEachOrdered((loc) -> {
+            throw new RuntimeException("Locale " + loc + "  is not supported by CLDR Locale Provider");
+        });
+    }
+
+    /**
+     * Tests that locale nb should be supported by JRELocaleProvider .
+     */
+    private static void testCompatSupportedLocale() {
+        LocaleProviderAdapter jre = LocaleProviderAdapter.forJRE();
+        checkPresenceCompat("BreakIteratorProvider",
+                jre.getBreakIteratorProvider().getAvailableLocales());
+        checkPresenceCompat("CollatorProvider",
+                jre.getCollatorProvider().getAvailableLocales());
+        checkPresenceCompat("DateFormatProvider",
+                jre.getDateFormatProvider().getAvailableLocales());
+        checkPresenceCompat("DateFormatSymbolsProvider",
+                jre.getDateFormatSymbolsProvider().getAvailableLocales());
+        checkPresenceCompat("DecimalFormatSymbolsProvider",
+                jre.getDecimalFormatSymbolsProvider().getAvailableLocales());
+        checkPresenceCompat("NumberFormatProvider",
+                jre.getNumberFormatProvider().getAvailableLocales());
+        checkPresenceCompat("CurrencyNameProvider",
+                jre.getCurrencyNameProvider().getAvailableLocales());
+        checkPresenceCompat("LocaleNameProvider",
+                jre.getLocaleNameProvider().getAvailableLocales());
+        checkPresenceCompat("TimeZoneNameProvider",
+                jre.getTimeZoneNameProvider().getAvailableLocales());
+        checkPresenceCompat("CalendarDataProvider",
+                jre.getCalendarDataProvider().getAvailableLocales());
+        checkPresenceCompat("CalendarNameProvider",
+                jre.getCalendarNameProvider().getAvailableLocales());
+        checkPresenceCompat("CalendarProvider",
+                jre.getCalendarProvider().getAvailableLocales());
+    }
+
+    private static void checkPresenceCompat(String testName, Locale[] got) {
+        List<Locale> gotLocalesList = Arrays.asList(got);
+        Locale nb = Locale.forLanguageTag("nb");
+        if (!gotLocalesList.contains(nb)) {
+            throw new RuntimeException("Locale nb not supported by JREProvider for "
+                    + testName + " test ");
+        }
+    }
+}
--- a/jdk/test/sun/util/locale/provider/Bug8038436.java	Wed Jul 05 22:44:47 2017 +0200
+++ b/jdk/test/sun/util/locale/provider/Bug8038436.java	Tue Jan 24 12:06:03 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8038436 8158504 8065555 8167143
+ * @bug 8038436 8158504 8065555 8167143 8167273
  * @summary Test for changes in 8038436
  * @modules java.base/sun.util.locale.provider
  *          java.base/sun.util.spi
@@ -120,7 +120,7 @@
         "fi, fi-FI, fr, fr-BE, fr-CA, fr-CH, fr-FR, ga, ga-IE, he, he-IL, " +
         "hi-IN, hr, hr-HR, hu, hu-HU, id, id-ID, is, is-IS, it, it-CH, it-IT, " +
         "ja, ja-JP, ko, ko-KR, lt, lt-LT, lv, lv-LV, mk, mk-MK, ms, ms-MY, mt, " +
-        "mt-MT, nb-NO, nl, nl-BE, nl-NL, nn-NO, no, no-NO, no-NO, pl, pl-PL, pt, pt-BR, " +
+        "mt-MT, nb, nb-NO, nl, nl-BE, nl-NL, nn-NO, no, no-NO, no-NO, pl, pl-PL, pt, pt-BR, " +
         "pt-PT, ro, ro-RO, ru, ru-RU, sk, sk-SK, sl, sl-SI, sq, sq-AL, sr, " +
         "sr-BA, sr-CS, sr-Latn, sr-Latn-ME, sr-ME, sr-RS, sv, sv-SE, th, th-TH, " +
         "tr, tr-TR, uk, uk-UA, und, vi, vi-VN, zh, zh-CN, zh-HK, zh-Hans-CN, " +
@@ -130,7 +130,7 @@
     static final String[] decimalfspLocs = bipLocs;
     static final String[] calnpLocs = bipLocs;
     static final String[] cpLocs = ("ar, be, bg, ca, cs, da, el, es, et, fi, " +
-        "fr, he, hi, hr, hu, is, ja, ko, lt, lv, mk, nb-NO, nn-NO, no, pl, ro, ru, sk, sl, " +
+        "fr, he, hi, hr, hu, is, ja, ko, lt, lv, mk, nb, nb-NO, nn-NO, no, pl, ro, ru, sk, sl, " +
         "sq, sr, sr-Latn, sv, th, tr, uk, und, vi, zh, zh-HK, zh-Hant-HK, " +
         "zh-Hant-TW, zh-TW, ").split(",\\s*");
     static final String[] nfpLocs = ("ar, ar-AE, ar-BH, ar-DZ, ar-EG, ar-IQ, " +
@@ -144,7 +144,7 @@
         "fr-LU, ga, ga-IE, he, he-IL, hi, hi-IN, hr, hr-HR, hu, hu-HU, id, " +
         "id-ID, is, is-IS, it, it-CH, it-IT, ja, ja-JP, " +
         "ja-JP-u-ca-japanese-x-lvariant-JP, ko, ko-KR, lt, lt-LT, lv, lv-LV, " +
-        "mk, mk-MK, ms, ms-MY, mt, mt-MT, nb-NO, nl, nl-BE, nl-NL, nn-NO, " +
+        "mk, mk-MK, ms, ms-MY, mt, mt-MT, nb, nb-NO, nl, nl-BE, nl-NL, nn-NO, " +
         "nn-NO, no, no-NO, pl, pl-PL, pt, pt-BR, pt-PT, ro, ro-RO, ru, ru-RU, " +
         "sk, sk-SK, sl, sl-SI, sq, sq-AL, sr, sr-BA, sr-CS, sr-Latn, " +
         "sr-Latn-BA, sr-Latn-ME, sr-Latn-RS, sr-ME, sr-RS, sv, sv-SE, th, " +
@@ -160,22 +160,22 @@
         "es-PA, es-PE, es-PR, es-PY, es-SV, es-US, es-UY, es-VE, et-EE, fi-FI, " +
         "fr, fr-BE, fr-CA, fr-CH, fr-FR, fr-LU, ga-IE, he-IL, hi-IN, hr-HR, " +
         "hu-HU, id-ID, is-IS, it, it-CH, it-IT, ja, ja-JP, ko, ko-KR, lt-LT, " +
-        "lv-LV, mk-MK, ms-MY, mt-MT, nb-NO, nl-BE, nl-NL, nn-NO, no-NO, pl-PL, pt, pt-BR, " +
+        "lv-LV, mk-MK, ms-MY, mt-MT, nb,  nb-NO, nl-BE, nl-NL, nn-NO, no-NO, pl-PL, pt, pt-BR, " +
         "pt-PT, ro-RO, ru-RU, sk-SK, sl-SI, sq-AL, sr-BA, sr-CS, sr-Latn-BA, " +
         "sr-Latn-ME, sr-Latn-RS, sr-ME, sr-RS, sv, sv-SE, th-TH, tr-TR, uk-UA, " +
         "und, vi-VN, zh-CN, zh-HK, zh-Hans-CN, zh-Hans-SG, zh-Hant-HK, " +
         "zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
     static final String[] lnpLocs = ("ar, be, bg, ca, cs, da, de, el, el-CY, " +
         "en, en-MT, en-PH, en-SG, es, es-US, et, fi, fr, ga, he, hi, hr, hu, " +
-        "id, is, it, ja, ko, lt, lv, mk, ms, mt, nb-NO, nl, nn-NO, no, no-NO, pl, pt, pt-BR, " +
+        "id, is, it, ja, ko, lt, lv, mk, ms, mt, nb, nb-NO, nl, nn-NO, no, no-NO, pl, pt, pt-BR, " +
         "pt-PT, ro, ru, sk, sl, sq, sr, sr-Latn, sv, th, tr, uk, und, vi, zh, " +
         "zh-HK, zh-Hans-SG, zh-Hant-HK, zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
     static final String[] tznpLocs = ("de, en, en-CA, en-GB, en-IE, es, fr, hi, " +
-        "it, ja, ko, nb-NO, nn-NO, pt-BR, sv, und, zh-CN, zh-HK, zh-Hans-CN, zh-Hant-HK, " +
+        "it, ja, ko, nb,  nb-NO, nn-NO, pt-BR, sv, und, zh-CN, zh-HK, zh-Hans-CN, zh-Hant-HK, " +
         "zh-Hant-TW, zh-TW, ").split(",\\s*");
     static final String[] caldpLocs = ("ar, be, bg, ca, cs, da, de, el, el-CY, " +
         "en, en-GB, en-IE, en-MT, es, es-ES, es-US, et, fi, fr, fr-CA, he, hi, " +
-        "hr, hu, id-ID, is, it, ja, ko, lt, lv, mk, ms-MY, mt, mt-MT, nb-NO, nl, nn-NO, no, " +
+        "hr, hu, id-ID, is, it, ja, ko, lt, lv, mk, ms-MY, mt, mt-MT, nb, nb-NO, nl, nn-NO, no, " +
         "pl, pt, pt-BR, pt-PT, ro, ru, sk, sl, sq, sr, sr-Latn-BA, sr-Latn-ME, " +
         "sr-Latn-RS, sv, th, tr, uk, und, vi, zh, ").split(",\\s*");
     static final String[] calpLocs = caldpLocs;