1 package org.unicode.cldr.unittest; 2 3 import com.google.common.collect.ImmutableMultimap; 4 import com.google.common.collect.ImmutableSet; 5 import com.google.common.collect.Multimap; 6 import com.google.common.collect.Multimaps; 7 import com.google.common.collect.TreeMultimap; 8 import com.ibm.icu.dev.test.TestFmwk; 9 import com.ibm.icu.util.ULocale; 10 import java.util.Collection; 11 import java.util.HashSet; 12 import java.util.List; 13 import java.util.Map.Entry; 14 import java.util.Set; 15 import java.util.TreeSet; 16 import org.unicode.cldr.util.CLDRConfig; 17 import org.unicode.cldr.util.CLDRFile; 18 import org.unicode.cldr.util.Containment; 19 import org.unicode.cldr.util.LanguageGroup; 20 import org.unicode.cldr.util.LanguageTagParser; 21 import org.unicode.cldr.util.SupplementalDataInfo; 22 23 public class TestLanguageGroup extends TestFmwk { 24 static CLDRConfig CONF = CLDRConfig.getInstance(); 25 static CLDRFile ENGLISH = CONF.getEnglish(); 26 static SupplementalDataInfo SDI = CONF.getSupplementalDataInfo(); 27 static Multimap<String, String> PARENT_TO_CHILDREN = SDI.getLanguageGroups(); 28 static Multimap<String, String> CHILDREN_TO_PARENT = 29 ImmutableMultimap.copyOf( 30 Multimaps.invertFrom(PARENT_TO_CHILDREN, TreeMultimap.create())); 31 main(String[] args)32 public static void main(String[] args) { 33 System.out.println( 34 "See the class description for GenerateLanguageContainment.java about fixing problems, or the javadoc for the test code"); 35 new TestLanguageGroup().run(args); 36 } 37 38 static final Set<String> ISOLATES = ImmutableSet.of("ko", "qu", "root", "ce", "kgp", "und"); 39 40 /** Checks that items with no parent are not in that category by mistake. */ TestCodes()41 public void TestCodes() { 42 LanguageTagParser ltp = new LanguageTagParser(); 43 Set<String> seen = new HashSet<>(); 44 for (String locale : CONF.getCldrFactory().getAvailableLanguages()) { 45 String lang = ltp.set(locale).getLanguage(); 46 if (lang.equals("root")) { 47 continue; 48 } 49 if (seen.contains(lang)) { 50 continue; 51 } 52 seen.add(lang); 53 Set<List<String>> targets = getAllAncestors(lang); 54 assertEquals(getName(lang) + " has multiple ancestors: " + targets, 1, targets.size()); 55 List<String> target = targets.iterator().next(); 56 if ((target.size() == 1) && !ISOLATES.contains(lang)) { 57 errln("Single ancestor but not in ISOLATES: " + getName(lang) + "\t" + target); 58 /** If this fails, check the ancestors on wikipedia, and if none of them have */ 59 } else if (!(target.size() == 1) && ISOLATES.contains(lang)) { 60 errln("Multiple ancestors but in ISOLATES: " + getName(lang) + "\t" + target); 61 } else { 62 logln(getName(lang) + "\t" + target); 63 } 64 } 65 } 66 67 static final Set<String> MIXED_LANGUAGES = ImmutableSet.of("sth"); 68 TestSingleParent()69 public void TestSingleParent() { 70 for (Entry<String, Collection<String>> entry : CHILDREN_TO_PARENT.asMap().entrySet()) { 71 String child = entry.getKey(); 72 Collection<String> parents = entry.getValue(); 73 if (parents.size() != 1) { 74 StringBuilder parentsString = new StringBuilder(); 75 parents.forEach(code -> parentsString.append(getName(code) + "; ")); 76 msg( 77 "\tThere are multiple parents\t" 78 + parentsString 79 + "\tfor\t" 80 + getName(child), 81 MIXED_LANGUAGES.contains(child) ? LOG : ERR, 82 true, 83 true); 84 } 85 } 86 } 87 88 public static Set<LanguageGroup> OLD_SPECIALS = 89 ImmutableSet.of( 90 LanguageGroup.root, 91 LanguageGroup.cjk, 92 LanguageGroup.other, 93 LanguageGroup.american, 94 LanguageGroup.caucasian); 95 TestOldLangaugeGroup()96 public void TestOldLangaugeGroup() { 97 for (LanguageGroup item : LanguageGroup.values()) { 98 if (OLD_SPECIALS.contains(item)) { // special cases 99 continue; 100 } 101 Set<ULocale> locales = LanguageGroup.getLocales(item); 102 String parent = item.iso; 103 parent = parent.replace("_001", ""); 104 logln(parent + ": " + new TreeSet<>(locales)); 105 logln(parent + ": " + getAllChildren(parent)); 106 for (ULocale child : locales) { 107 String childString = child.toLanguageTag(); 108 if (!assertTrue( 109 getName(parent) + " contains " + getName(childString), 110 isAncestorOf(parent, childString))) { 111 System.out.println( 112 "superclasses of " + childString + ": " + getAllAncestors(childString)); 113 System.out.println( 114 "subclasses of " + parent + ": " + getAllChildren(childString)); 115 } 116 } 117 } 118 } 119 getName(String code)120 String getName(String code) { 121 return code + " [" + fixedName(code) + "]"; 122 } 123 fixedName(String code)124 private String fixedName(String code) { 125 switch (code) { 126 case "grk": 127 return "Hellenic"; 128 default: 129 return ENGLISH.getName(code).replace(" [Other]", ""); 130 } 131 } 132 isAncestorOf(String ancestor, String lang)133 boolean isAncestorOf(String ancestor, String lang) { 134 while (true) { 135 Collection<String> parents = CHILDREN_TO_PARENT.get(lang); 136 if (parents == null || parents.isEmpty()) { 137 return false; 138 } 139 if (parents.size() != 1) { // recurse with 2 since is simpler 140 for (String parent : parents) { 141 if (parent.equals(ancestor) || isAncestorOf(ancestor, parent)) { 142 return true; 143 } 144 } 145 return false; 146 } 147 lang = parents.iterator().next(); 148 if (lang.equals(ancestor)) { 149 return true; 150 } 151 } 152 } 153 154 // <T extends Collection<String>> T getAllDirected(Multimap<String, String> multimap, String 155 // lang, T target) { 156 // Collection<String> parents = multimap.get(lang); 157 // if (!parents.isEmpty()) { 158 // target.addAll(parents); 159 // for (String parent : parents) { 160 // getAllDirected(multimap, parent, target); 161 // } 162 // } 163 // return target; 164 // } 165 getAllAncestors(String lang)166 <T extends Collection<String>> Set<List<String>> getAllAncestors(String lang) { 167 return Containment.getAllDirected(CHILDREN_TO_PARENT, lang); 168 } 169 getAllChildren(String lang)170 <T extends Collection<String>> Set<List<String>> getAllChildren(String lang) { 171 return Containment.getAllDirected(PARENT_TO_CHILDREN, lang); 172 } 173 } 174