1 package org.unicode.cldr.unittest; 2 3 import java.util.Arrays; 4 import java.util.Collections; 5 import java.util.Locale; 6 import java.util.Map; 7 import java.util.Set; 8 import java.util.TreeMap; 9 10 import org.unicode.cldr.util.CLDRConfig; 11 import org.unicode.cldr.util.CLDRFile; 12 import org.unicode.cldr.util.ChainedMap; 13 import org.unicode.cldr.util.CldrUtility; 14 import org.unicode.cldr.util.SupplementalDataInfo; 15 import org.unicode.cldr.util.With; 16 import org.unicode.cldr.util.XPathParts; 17 18 import com.google.common.collect.ImmutableSet; 19 import com.ibm.icu.dev.test.TestFmwk; 20 import com.ibm.icu.impl.Relation; 21 import com.ibm.icu.impl.Row; 22 import com.ibm.icu.impl.Row.R2; 23 import com.ibm.icu.impl.Row.R3; 24 25 public class TestBCP47 extends TestFmwk { 26 private static final int WARNING = LOG; // change to WARN to enable checking for non-bcp47 attributes 27 private static final int ERROR = WARN; // change to ERR to enable test 28 29 private static final CLDRConfig testInfo = CLDRConfig.getInstance(); 30 private static final SupplementalDataInfo SUPPLEMENTAL_DATA_INFO = testInfo.getSupplementalDataInfo(); 31 private static final CLDRFile ENGLISH = testInfo.getEnglish(); 32 private static final Relation<String, String> bcp47key_types = SUPPLEMENTAL_DATA_INFO.getBcp47Keys(); 33 private static final Relation<R2<String, String>, String> bcp47keyType_aliases = SUPPLEMENTAL_DATA_INFO.getBcp47Aliases(); 34 private static final Map<R2<String, String>, String> deprecated = SUPPLEMENTAL_DATA_INFO.getBcp47Deprecated(); 35 36 public static void main(String[] args) { 37 new TestBCP47().run(args); 38 } 39 40 private static final ChainedMap.M3<String, String, String> keyTypeTranslations = ChainedMap.of( 41 new TreeMap<String, Object>(), 42 new TreeMap<String, Object>(), 43 String.class); 44 static { 45 for (String path : With.in(ENGLISH.iterator("//ldml/localeDisplayNames/keys/key"))) { 46 XPathParts parts = XPathParts.getInstance(path); 47 String value = ENGLISH.getStringValue(path); 48 String key = parts.getAttributeValue(-1, "type"); 49 keyTypeTranslations.put(key, "", value); 50 } 51 for (String path : With.in(ENGLISH.iterator("//ldml/localeDisplayNames/types/type"))) { 52 XPathParts parts = XPathParts.getInstance(path); 53 String value = ENGLISH.getStringValue(path); 54 String key = parts.getAttributeValue(-1, "key"); 55 String type = parts.getAttributeValue(-1, "type"); 56 keyTypeTranslations.put(key, type, value); 57 } 58 for (String path : With.in(ENGLISH.iterator("//ldml/localeDisplayNames/transformNames/transformName"))) { 59 XPathParts parts = XPathParts.getInstance(path); 60 String value = ENGLISH.getStringValue(path); 61 String type = parts.getAttributeValue(-1, "type"); 62 keyTypeTranslations.put("d0", type, value); 63 } 64 } 65 66 public void TestEnglishKeyTranslations() { 67 logKnownIssue("cldr7631", "Using just warnings for now, until issues are resolved. Change WARNING/ERROR when removing this."); 68 ChainedMap.M3<String, String, String> foundEnglish = ChainedMap.of( 69 new TreeMap<String, Object>(), 70 new TreeMap<String, Object>(), 71 String.class); 72 for (String bcp47Key : bcp47key_types.keySet()) { 73 final R2<String, String> keyRow = Row.of(bcp47Key, ""); 74 if ("true".equals(deprecated.get(keyRow))) { 75 logln("Skipping deprecated key:\t" + bcp47Key); 76 continue; 77 } 78 String keyTrans = keyTypeTranslations.get(bcp47Key, ""); 79 Set<String> keyAliases = CldrUtility.ifNull(bcp47keyType_aliases.get(keyRow), Collections.<String> emptySet()); 80 String engKey = bcp47Key; 81 if (keyTrans != null) { 82 foundEnglish.put(engKey, "", keyTrans); 83 } else { 84 for (String keyAlias : keyAliases) { 85 keyTrans = keyTypeTranslations.get(keyAlias, ""); 86 if (keyTrans != null) { 87 engKey = keyAlias; 88 foundEnglish.put(engKey, "", keyTrans); 89 msg("Type for English 'key' translation is " + engKey + ", while bcp47 is " + bcp47Key, WARNING, true, true); 90 break; 91 } 92 } 93 } 94 if (keyTrans != null) { 95 logln(showData(bcp47Key, "", SUPPLEMENTAL_DATA_INFO.getBcp47Descriptions().get(keyRow), keyAliases, Collections.<String> emptySet(), keyTrans)); 96 } else { 97 msg(showData(bcp47Key, "", SUPPLEMENTAL_DATA_INFO.getBcp47Descriptions().get(keyRow), keyAliases, Collections.<String> emptySet(), "MISSING"), 98 ERROR, true, true); 99 } 100 if (bcp47Key.equals("tz")) { 101 continue; 102 // handled elsewhere 103 } 104 for (String bcp47Type : bcp47key_types.get(bcp47Key)) { 105 checkKeyType(bcp47Key, keyAliases, engKey, bcp47Type, foundEnglish); 106 if (bcp47Type.equals("REORDER_CODE")) { 107 for (String subtype : Arrays.asList("space", "punct", "symbol", "currency", "digit")) { 108 checkKeyType(bcp47Key, keyAliases, engKey, subtype, foundEnglish); 109 } 110 } 111 } 112 } 113 for (R3<String, String, String> extra : keyTypeTranslations.rows()) { 114 final String key = extra.get0(); 115 final String type = extra.get1(); 116 final String trans = extra.get2(); 117 if (foundEnglish.get(key, type) == null) { 118 if (key.equals("x")) { 119 msg("OK Extra English: " + showData(key, type, "MISSING", Collections.<String> emptySet(), Collections.<String> emptySet(), trans), LOG, 120 true, true); 121 } else { 122 msg("*Extra English: " + showData(key, type, "MISSING", Collections.<String> emptySet(), Collections.<String> emptySet(), trans), ERROR, 123 true, true); 124 } 125 } 126 } 127 } 128 129 static final ImmutableSet<String> SKIP_TYPES = ImmutableSet.of("REORDER_CODE", "RG_KEY_VALUE", "SUBDIVISION_CODE", "CODEPOINTS", "PRIVATE_USE"); 130 131 private void checkKeyType( 132 String bcp47Key, 133 Set<String> keyAliases, 134 String engKey, 135 String bcp47Type, 136 ChainedMap.M3<String, String, String> foundEnglish) { 137 if (SKIP_TYPES.contains(bcp47Type)) { 138 logln("Skipping generic key/type:\t" + bcp47Key + "/" + bcp47Type); 139 return; 140 } 141 final R2<String, String> row = Row.of(bcp47Key, bcp47Type); 142 if ("true".equals(deprecated.get(row))) { 143 logln("Skipping deprecated key/type:\t" + bcp47Key + "/" + bcp47Type); 144 return; 145 } 146 Set<String> typeAliases = CldrUtility.ifNull(bcp47keyType_aliases.get(row), Collections.<String> emptySet()); 147 String engType = bcp47Type; 148 String trans = keyTypeTranslations.get(engKey, engType); 149 if (trans != null) { 150 foundEnglish.put(engKey, engType, trans); 151 } else { 152 for (String typeAlias : typeAliases) { 153 trans = keyTypeTranslations.get(engKey, typeAlias); 154 if (trans != null) { 155 engType = typeAlias; 156 foundEnglish.put(engKey, engType, trans); 157 msg("Type for English 'key+type' translation is " + engKey + "+" + engType + ", while bcp47 is " + bcp47Key + "+" + bcp47Type, WARNING, 158 true, true); 159 break; 160 } 161 } 162 } 163 if (trans == null) { 164 switch (bcp47Key) { 165 case "cu": 166 trans = ENGLISH.getStringValue("//ldml/numbers/currencies/currency[@type=\"" + bcp47Type.toUpperCase(Locale.ENGLISH) + "\"]/displayName"); 167 break; 168 } 169 } 170 if (trans != null) { 171 logln(showData(bcp47Key, bcp47Type, SUPPLEMENTAL_DATA_INFO.getBcp47Descriptions().get(row), keyAliases, typeAliases, trans)); 172 } else { 173 msg(showData(bcp47Key, bcp47Type, SUPPLEMENTAL_DATA_INFO.getBcp47Descriptions().get(row), keyAliases, typeAliases, "MISSING"), ERROR, true, true); 174 } 175 } 176 177 private String showData(String key, String type, String bcp47Description, Set<String> keyAliases, Set<String> typeAliases, String eng) { 178 return "key: " + key + "\taliases: " + keyAliases + (type.isEmpty() ? "" : "\ttype: " + type + "\taliases: " + typeAliases) + "\tbcp: " 179 + bcp47Description + ",\teng: " + eng; 180 } 181 } 182