1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 8159943 8154797 27 * @modules java.base/sun.util.locale.provider 28 * java.base/sun.util.resources 29 * jdk.localedata 30 * @summary Test for checking consistency between CLDR and COMPAT locale data 31 * for java.time. 32 */ 33 34import java.util.Arrays; 35import java.util.HashMap; 36import java.util.List; 37import java.util.Locale; 38import java.util.Map; 39import java.util.Objects; 40import java.util.ResourceBundle; 41import java.util.Set; 42import java.util.TreeSet; 43import java.util.stream.Collectors; 44import sun.util.locale.provider.LocaleProviderAdapter.Type; 45import sun.util.locale.provider.LocaleProviderAdapter; 46 47public class JavaTimeSupplementaryTest { 48 // COMPAT-to-CLDR locale mapping 49 private static final Map<Locale, Locale> LOCALEMAP; 50 static { 51 LOCALEMAP = new HashMap<>(); 52 LOCALEMAP.put(new Locale("hi", "IN"), new Locale("hi")); 53 LOCALEMAP.put(new Locale("no", "NO", "NY"), new Locale("nn", "NO")); 54 LOCALEMAP.put(new Locale("no"), new Locale("nb")); 55 LOCALEMAP.put(Locale.TAIWAN, Locale.forLanguageTag("zh-Hant")); 56 LOCALEMAP.put(new Locale("zh", "HK"), Locale.forLanguageTag("zh-Hant-HK")); 57 LOCALEMAP.put(new Locale("zh", "SG"), Locale.forLanguageTag("zh-Hans-SG")); 58 LOCALEMAP.put(new Locale("sr", "BA"), Locale.forLanguageTag("sr-Cyrl-BA")); 59 } 60 61 private static final String[] PREFIXES = { 62 "Quarter", 63 "java.time.", 64 "calendarname.", 65 "field.", 66 "islamic.", 67 "roc.", 68 "timezone." 69 }; 70 71 // All available locales for the COMPAT FormatData resource bundles 72 static final List<Locale> COMPAT_LOCALES 73 = Arrays.asList(LocaleProviderAdapter.forJRE() 74 .getDateFormatSymbolsProvider().getAvailableLocales()); 75 76 static int errors; 77 78 public static void main(String... args) { 79 for (Locale locale : COMPAT_LOCALES) { 80 ResourceBundle compat 81 = LocaleProviderAdapter.forJRE() 82 .getLocaleResources(locale).getJavaTimeFormatData(); 83 if (!compat.getLocale().equals(locale)) { 84 continue; 85 } 86 Locale cldrLocale = toCldrLocale(locale); 87 ResourceBundle cldr 88 = LocaleProviderAdapter.forType(Type.CLDR) 89 .getLocaleResources(locale).getJavaTimeFormatData(); 90 if (!cldr.getLocale().equals(cldrLocale)) { 91 continue; 92 } 93 compareResources(compat, cldr); 94 } 95 if (errors > 0) { 96 throw new RuntimeException(errors + " failure(s)"); 97 } 98 } 99 100 private static Locale toCldrLocale(Locale compatLocale) { 101 Locale loc = LOCALEMAP.get(compatLocale); 102 return loc != null ? loc: compatLocale; 103 } 104 105 private static void compareResources(ResourceBundle compat, ResourceBundle cldr) { 106 Set<String> supplementalKeys = getSupplementalKeys(compat); 107 for (String key : supplementalKeys) { 108 Object compatData = compat.getObject(key); 109 String cldrKey = toCldrKey(key); 110 Object cldrData = cldr.containsKey(cldrKey) ? cldr.getObject(cldrKey) : null; 111 if (!Objects.deepEquals(compatData, cldrData)) { 112 // OK if key is for the Buddhist or Japanese calendars which had been 113 // supported before java.time, or if key is "java.time.short.Eras" due 114 // to legacy era names. 115 if (!(key.contains("buddhist") || key.contains("japanese") 116 || key.equals("java.time.short.Eras"))) { 117 errors++; 118 System.out.print("Failure: "); 119 } 120 System.out.println("diff: " + compat.getLocale().toLanguageTag() + "\n" 121 + " COMPAT: " + key + " -> " + toString(compatData) + "\n" 122 + " CLDR: " + cldrKey + " -> " + toString(cldrData)); 123 } 124 } 125 } 126 127 private static Set<String> getSupplementalKeys(ResourceBundle rb) { 128 // Collect keys starting with any of PREFIXES 129 Set<String> keys = rb.keySet().stream() 130 .filter(k -> Arrays.stream(PREFIXES).anyMatch(p -> k.startsWith(p))) 131 .collect(Collectors.toCollection(TreeSet::new)); 132 return keys; 133 } 134 135 /** 136 * Removes "java.time." prefix where it's unused in CLDR. 137 */ 138 private static String toCldrKey(String key) { 139 if (key.contains("short.Eras")) { 140 key = key.replace("short.", ""); 141 } 142 if (key.startsWith("java.time.") && key.endsWith(".Eras")) { 143 return key.substring("java.time.".length()); 144 } 145 return key; 146 } 147 148 private static String toString(Object data) { 149 if (data instanceof String[]) { 150 return Arrays.toString((String[]) data); 151 } 152 return data.toString(); 153 } 154} 155