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