| package org.unicode.cldr.tool; |
| |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.util.Comparator; |
| import java.util.EnumMap; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| |
| import org.unicode.cldr.draft.FileUtilities; |
| import org.unicode.cldr.util.Builder; |
| import org.unicode.cldr.util.Builder.CBuilder; |
| import org.unicode.cldr.util.CLDRConfig; |
| import org.unicode.cldr.util.CLDRFile; |
| import org.unicode.cldr.util.CLDRFile.Status; |
| import org.unicode.cldr.util.CLDRPaths; |
| import org.unicode.cldr.util.Counter; |
| import org.unicode.cldr.util.CoverageInfo; |
| import org.unicode.cldr.util.DtdType; |
| import org.unicode.cldr.util.Factory; |
| import org.unicode.cldr.util.LanguageTagParser; |
| import org.unicode.cldr.util.Level; |
| import org.unicode.cldr.util.SupplementalDataInfo; |
| import org.unicode.cldr.util.SupplementalDataInfo.PluralType; |
| import org.unicode.cldr.util.XPathParts; |
| |
| import com.ibm.icu.impl.Relation; |
| import com.ibm.icu.impl.Row; |
| import com.ibm.icu.impl.Row.R2; |
| import com.ibm.icu.impl.Row.R3; |
| import com.ibm.icu.impl.Row.R5; |
| import com.ibm.icu.impl.Utility; |
| import com.ibm.icu.text.NumberFormat; |
| import com.ibm.icu.text.Transform; |
| |
| public class GenerateCoverageLevels { |
| // see ShowLocaleCoverage.java |
| private static boolean SKIP_UNCONFIRMED = true; |
| private static int SHOW_EXAMPLES = 5; |
| private static final String FILES = ".*"; |
| private static final String MAIN_DIRECTORY = CLDRPaths.MAIN_DIRECTORY;// CldrUtility.SUPPLEMENTAL_DIRECTORY; |
| // //CldrUtility.MAIN_DIRECTORY; |
| private static final String COLLATION_DIRECTORY = CLDRPaths.COMMON_DIRECTORY + "/collation/";// CldrUtility.SUPPLEMENTAL_DIRECTORY; |
| // //CldrUtility.MAIN_DIRECTORY; |
| private static final String RBNF_DIRECTORY = CLDRPaths.COMMON_DIRECTORY + "/rbnf/";// CldrUtility.SUPPLEMENTAL_DIRECTORY; |
| // //CldrUtility.MAIN_DIRECTORY; |
| private static final String OUT_DIRECTORY = CLDRPaths.GEN_DIRECTORY + "/coverage/"; // CldrUtility.MAIN_DIRECTORY; |
| private static final Factory cldrFactory = Factory.make(MAIN_DIRECTORY, FILES); |
| private static final Comparator<String> attributeComparator = CLDRFile.getAttributeOrdering(); |
| private static final CLDRFile english = cldrFactory.make("en", true); |
| private static SupplementalDataInfo supplementalData = CLDRConfig.getInstance().getSupplementalDataInfo(); |
| // SupplementalDataInfo.getInstance(english.getSupplementalDirectory()); |
| private static Set<String> defaultContents = supplementalData.getDefaultContentLocales(); |
| private static Map<String, R2<List<String>, String>> languageAliasInfo = supplementalData.getLocaleAliasInfo().get( |
| "language"); |
| private static LocaleFilter localeFilter = new LocaleFilter(true); |
| private static BooleanLocaleFilter nonAliasLocaleFilter = new BooleanLocaleFilter(); |
| |
| private static final long COLLATION_WEIGHT = 50; |
| private static final Level COLLATION_LEVEL = Level.POSIX; |
| private static final long PLURALS_WEIGHT = 20; |
| private static final Level PLURALS_LEVEL = Level.MINIMAL; |
| private static final long RBNF_WEIGHT = 20; |
| private static final Level RBNF_LEVEL = Level.MODERATE; |
| |
| static int totalCount = 0; |
| |
| enum Inheritance { |
| actual, inherited |
| } |
| |
| public static void main(String[] args) throws IOException { |
| if (true) { |
| throw new IllegalArgumentException("See ShowLocaleCoverage (TODO: merge these)."); |
| } |
| PrintWriter out = FileUtilities.openUTF8Writer(OUT_DIRECTORY, "fullpaths.txt"); |
| showEnglish(out); |
| out.close(); |
| |
| System.out.println("*** TODO check collations, RBNF, Transforms (if non-Latin)"); |
| PrintWriter summary = FileUtilities.openUTF8Writer(OUT_DIRECTORY, "summary.txt"); |
| PrintWriter samples = FileUtilities.openUTF8Writer(OUT_DIRECTORY, "samples.txt"); |
| PrintWriter counts = FileUtilities.openUTF8Writer(OUT_DIRECTORY, "counts.txt"); |
| summarizeCoverage(summary, samples, counts); |
| summary.close(); |
| samples.close(); |
| counts.close(); |
| } |
| |
| private static void showEnglish(PrintWriter out) throws IOException { |
| CLDRFile cldrFile = english; |
| String locale = "en"; |
| Set<String> sorted = Builder.with(new TreeSet<String>()).addAll(cldrFile.iterator()) |
| .addAll(cldrFile.getExtraPaths()).get(); |
| Set<R3<Level, String, Inheritance>> items = new TreeSet<R3<Level, String, Inheritance>>(new RowComparator()); |
| for (String path : sorted) { |
| if (path.endsWith("/alias")) { |
| continue; |
| } |
| String source = cldrFile.getSourceLocaleID(path, null); |
| Inheritance inherited = !source.equals(locale) ? Inheritance.inherited : Inheritance.actual; |
| |
| // Level level = supplementalData.getCoverageLevel(path, locale); |
| Level level = CLDRConfig.getInstance().getCoverageInfo().getCoverageLevel(path, locale); |
| |
| items.add(Row.of(level, path, inherited)); |
| } |
| |
| PathStore store = new PathStore(); |
| for (R3<Level, String, Inheritance> item : items) { |
| show(out, cldrFile, item, store); |
| } |
| show(out, cldrFile, null, store); |
| } |
| |
| private static class RowComparator implements Comparator<R3<Level, String, Inheritance>> { |
| |
| public int compare(R3<Level, String, Inheritance> o1, R3<Level, String, Inheritance> o2) { |
| int result = o1.get0().compareTo(o2.get0()); |
| if (result != 0) return result; |
| result = CLDRFile.getComparator(DtdType.ldml).compare(o1.get1(), o2.get1()); |
| if (result != 0) return result; |
| result = o1.get2().compareTo(o2.get2()); |
| return result; |
| } |
| } |
| |
| private static void show(PrintWriter out, CLDRFile cldrFile, R3<Level, String, Inheritance> next, PathStore store) { |
| R5<Level, Inheritance, Integer, String, TreeMap<String, Relation<String, String>>> results = store.add(next); |
| if (results != null) { |
| Level lastLevel = results.get0(); |
| int count = results.get2(); |
| String path = results.get3(); |
| totalCount += count; |
| try { |
| StringBuilder resultString = new StringBuilder(); |
| TreeMap<String, Relation<String, String>> types = results.get4(); |
| for (String key : types.keySet()) { |
| Relation<String, String> attr_values = types.get(key); |
| for (String attr : attr_values.keySet()) { |
| resultString.append("\t").append(key + ":\u200b" + attr).append("=\u200b") |
| .append(attr_values.getAll(attr)); |
| } |
| } |
| out.println(lastLevel.ordinal() |
| + "\t" + lastLevel |
| + "\t" + count |
| + "\t" + totalCount |
| + "\t" + path + resultString); |
| } catch (RuntimeException e) { |
| throw e; |
| } |
| } |
| } |
| |
| static class PathStore { |
| XPathParts lastParts = new XPathParts(); |
| XPathParts nextParts = new XPathParts(); |
| Level lastLevel; |
| Inheritance lastInheritance; |
| int count = 0; |
| |
| TreeMap<String, Relation<String, String>> differences = new TreeMap<String, Relation<String, String>>(); |
| |
| R5<Level, Inheritance, Integer, String, TreeMap<String, Relation<String, String>>> add( |
| R3<Level, String, Inheritance> next) { |
| count++; |
| boolean wasNull = lastLevel == null; |
| Level level = null; |
| String path = null; |
| Inheritance inherited = null; |
| |
| if (next != null) { |
| level = next.get0(); |
| path = next.get1(); |
| inherited = next.get2(); |
| |
| setParts(nextParts, path); |
| if (sameElements()) { |
| addDifferences(); |
| return null; |
| } |
| } |
| // clear the values |
| clean(lastParts, differences); |
| R5<Level, Inheritance, Integer, String, TreeMap<String, Relation<String, String>>> results = Row.of( |
| lastLevel, lastInheritance, count - 1, lastParts.toString().replace("/", "\u200B/"), differences); |
| lastParts = nextParts; |
| differences = new TreeMap<String, Relation<String, String>>(); |
| nextParts = new XPathParts(); |
| lastLevel = level; |
| lastInheritance = inherited; |
| count = 1; |
| if (wasNull) return null; |
| return results; |
| } |
| |
| private void clean(XPathParts lastParts2, TreeMap<String, Relation<String, String>> differences2) { |
| for (int i = 0; i < lastParts.size(); ++i) { |
| String element = lastParts.getElement(i); |
| Relation<String, String> attr_values = differences2.get(element); |
| if (attr_values == null) continue; |
| for (String attr : attr_values.keySet()) { |
| lastParts.putAttributeValue(i, attr, "*"); |
| } |
| } |
| } |
| |
| private void setParts(XPathParts parts, String path) { |
| parts.set(path); |
| if (path.startsWith("//ldml/dates/timeZoneNames/metazone") |
| || path.startsWith("//ldml/dates/timeZoneNames/zone")) { |
| String element = nextParts.getElement(-1); |
| nextParts.setElement(-1, "zoneChoice"); |
| nextParts.putAttributeValue(-1, "type", element); |
| element = nextParts.getElement(-2); |
| nextParts.setElement(-2, "zoneLength"); |
| nextParts.putAttributeValue(-2, "type", element); |
| } else if (path.startsWith("//ldml/dates/calendars/calendar")) { |
| if (!"gregorian".equals(parts.getAttributeValue(3, "type"))) { |
| for (int i = parts.size() - 1; i > 3; --i) { |
| parts.removeElement(i); |
| } |
| parts.addElement("*"); |
| } |
| } |
| } |
| |
| private void addDifferences() { |
| for (int i = 0; i < lastParts.size(); ++i) { |
| Map<String, String> lastAttrs = lastParts.getAttributes(i); |
| Map<String, String> nextAttrs = nextParts.getAttributes(i); |
| if (!lastAttrs.equals(nextAttrs)) { |
| String element = lastParts.getElement(i); |
| Relation<String, String> old = differences.get(element); |
| if (old == null) { |
| old = Relation.of(new TreeMap<String, Set<String>>(attributeComparator), TreeSet.class); |
| differences.put(element, old); |
| } |
| Set<String> union = Builder.with(new TreeSet<String>()).addAll(lastAttrs.keySet()) |
| .addAll(nextAttrs.keySet()).get(); |
| for (String key : union) { |
| String lastValue = lastAttrs.get(key); |
| String nextValue = nextAttrs.get(key); |
| if (!Utility.objectEquals(lastValue, nextValue)) { |
| if (lastValue != null) old.put(key, lastValue); |
| if (nextValue != null) old.put(key, nextValue); |
| } |
| } |
| } |
| } |
| } |
| |
| private boolean sameElements() { |
| if (lastParts.size() != nextParts.size()) return false; |
| for (int i = 0; i < lastParts.size(); ++i) { |
| if (!lastParts.getElement(i).equals(nextParts.getElement(i))) return false; |
| } |
| return true; |
| } |
| |
| } |
| |
| private static void summarizeCoverage(PrintWriter summary, PrintWriter samples2, PrintWriter counts) { |
| final Factory cldrFactory = Factory.make(MAIN_DIRECTORY, FILES); |
| final Factory collationFactory = Factory.make(COLLATION_DIRECTORY, FILES); |
| final Factory rbnfFactory = Factory.make(RBNF_DIRECTORY, FILES); |
| |
| // CLDRFile sd = CLDRFile.make(CLDRFile.SUPPLEMENTAL_NAME, CldrUtility.SUPPLEMENTAL_DIRECTORY, true); |
| // CLDRFile smd = CLDRFile.make(CLDRFile.SUPPLEMENTAL_METADATA, CldrUtility.SUPPLEMENTAL_DIRECTORY, true); |
| // |
| // CoverageLevel.init(sd, smd); |
| |
| NumberFormat percent = NumberFormat.getPercentInstance(); |
| NumberFormat decimal = NumberFormat.getInstance(); |
| decimal.setGroupingUsed(true); |
| decimal.setMaximumFractionDigits(2); |
| percent.setMaximumFractionDigits(2); |
| NumberFormat integer = NumberFormat.getIntegerInstance(); |
| Set<String> localesFound = new TreeSet<String>(); |
| |
| // get list of locales |
| LocaleLevelData mapLevelData = new LocaleLevelData(); |
| TreeSet<String> mainAvailableSource = new TreeSet<String>(cldrFactory.getAvailable()); |
| TreeSet<String> mainAvailable = new TreeSet<String>(); |
| Relation<String, String> localeToVariants = Relation.of(new HashMap(), HashSet.class); |
| for (String locale : mainAvailableSource) { |
| if (localeFilter.skipLocale(locale, localeToVariants)) { |
| continue; |
| } |
| mainAvailable.add(locale); |
| } |
| |
| System.out.println("gathering rbnf data"); |
| Set<String> ordinals = new TreeSet<String>(); |
| Set<String> spellout = new TreeSet<String>(); |
| localesFound.clear(); |
| for (String locale : rbnfFactory.getAvailable()) { |
| if (localeFilter.skipLocale(locale, null)) continue; |
| System.out.println(locale + "\t" + english.getName(locale)); |
| getRBNFData(locale, rbnfFactory.make(locale, true), ordinals, spellout, localesFound); |
| } |
| markData("RBNF-Ordinals", ordinals, mapLevelData, mainAvailable, RBNF_LEVEL, RBNF_WEIGHT, |
| Row.of("//ldml/rbnf/ordinals", "?")); |
| markData("RBNF-Spellout", spellout, mapLevelData, mainAvailable, RBNF_LEVEL, RBNF_WEIGHT, |
| Row.of("//ldml/rbnf/spellout", "?")); |
| if (localesFound.size() != 0) { |
| System.out.println("Other rbnf found:\t" + localesFound); |
| } |
| |
| System.out.println("gathering plural data"); |
| localesFound = new TreeSet<String>(supplementalData.getPluralLocales(PluralType.cardinal)); |
| markData("Plurals", localesFound, mapLevelData, mainAvailable, PLURALS_LEVEL, PLURALS_WEIGHT, |
| Row.of("//supplementalData/plurals", "UCA")); |
| |
| System.out.println("gathering collation data"); |
| localesFound.clear(); |
| for (String locale : collationFactory.getAvailable()) { |
| if (localeFilter.skipLocale(locale, null)) continue; |
| System.out.println(locale + "\t" + english.getName(locale)); |
| getCollationData(locale, collationFactory.make(locale, true), localesFound); |
| } |
| markData("Collation", localesFound, mapLevelData, mainAvailable, COLLATION_LEVEL, COLLATION_WEIGHT, |
| Row.of("//ldml/collations", "UCA")); |
| |
| System.out.println("gathering main data"); |
| for (String locale : mainAvailable) { |
| System.out.println(locale + "\t" + english.getName(locale)); |
| LevelData levelData = mapLevelData.get(locale); |
| getMainData(locale, levelData, cldrFactory.make(locale, true)); |
| } |
| |
| System.out.println("printing data"); |
| String summaryLineHeader = "Code\tName\tWeighted Missing:\tFound:\tScore:"; |
| summary.println(summaryLineHeader); |
| LanguageTagParser languageTagParser = new LanguageTagParser(); |
| |
| StringBuilder header = new StringBuilder(); |
| //EnumSet<Level> skipLevels = EnumSet.of(Level.CORE, Level.POSIX, Level.COMPREHENSIVE, Level.OPTIONAL); |
| for (String locale : mapLevelData.keySet()) { |
| LevelData levelData = mapLevelData.get(locale); |
| String max = LikelySubtags.maximize(locale, supplementalData.getLikelySubtags()); |
| String lang = languageTagParser.set(max).getLanguage(); |
| String script = languageTagParser.set(max).getScript(); |
| |
| Counter<Level> missing = levelData.missing; |
| Counter<Level> found = levelData.found; |
| Relation<Level, R2<String, String>> samples = levelData.samples; |
| StringBuilder countLine = new StringBuilder( |
| script |
| + "\t" + english.getName(CLDRFile.SCRIPT_NAME, script) |
| + "\t" + lang |
| + "\t" + english.getName(CLDRFile.LANGUAGE_NAME, lang) |
| ); |
| if (header != null) { |
| header.append("Code\tScript\tCode\tLocale"); |
| } |
| // Now print the information |
| samples2.println(); |
| samples2.println(locale + "\t" + english.getName(locale)); |
| double weightedFound = 0; |
| double weightedMissing = 0; |
| long missingCountTotal = 0; |
| long foundCountTotal = 0; |
| |
| for (Level level : Level.values()) { |
| if (level == Level.UNDETERMINED) { |
| continue; |
| } |
| long missingCount = missing.get(level); |
| missingCountTotal += missingCount; |
| long foundCount = found.get(level); |
| foundCountTotal += foundCount; |
| weightedFound += foundCount * level.getValue(); |
| weightedMissing += missingCount * level.getValue(); |
| |
| countLine.append('\t').append(missingCountTotal).append('\t').append(foundCountTotal); |
| if (header != null) { |
| header.append("\t" + level + "-Missing\tFound"); |
| } |
| |
| samples2.println(level + "\tMissing:\t" + integer.format(missingCount) + "\tFound:\t" |
| + integer.format(foundCount) |
| + "\tScore:\t" + percent.format(foundCount / (double) (foundCount + missingCount)) |
| + "\tLevel-Value:\t" + level.getValue()); |
| Set<R2<String, String>> samplesAlready = samples.getAll(level); |
| if (samplesAlready != null) { |
| for (R2<String, String> row : samplesAlready) { |
| samples2.println("\t" + row); |
| } |
| if (samplesAlready.size() >= SHOW_EXAMPLES) { |
| samples2.println("\t..."); |
| } |
| } |
| } |
| int base = Level.POSIX.getValue(); |
| double foundCount = weightedFound / base; |
| double missingCount = weightedMissing / base; |
| String summaryLine = "Weighted Missing:\t" + decimal.format(missingCount) + "\tFound:\t" |
| + decimal.format(foundCount) + "\tScore:\t" |
| + percent.format(foundCount / (foundCount + missingCount)); |
| String summaryLine2 = "\t" + decimal.format(missingCount) + "\t" + decimal.format(foundCount) + "\t" |
| + percent.format(foundCount / (foundCount + missingCount)); |
| samples2.println(summaryLine); |
| summary.println(locale + "\t" + english.getName(locale) + "\t" + summaryLine2); |
| if (header != null) { |
| counts.println(header); |
| header = null; |
| } |
| counts.println(countLine); |
| } |
| } |
| |
| private static void getRBNFData(String locale, CLDRFile cldrFile, Set<String> ordinals, Set<String> spellout, |
| Set<String> others) { |
| XPathParts parts = new XPathParts(); |
| for (String path : cldrFile) { |
| if (path.endsWith("/alias")) { |
| continue; |
| } |
| if (!path.contains("rulesetGrouping")) { |
| continue; |
| } |
| if (skipUnconfirmed(path)) { |
| continue; |
| } |
| parts.set(path); |
| String ruleSetGrouping = parts.getAttributeValue(2, "type"); |
| if (ruleSetGrouping.equals("SpelloutRules")) { |
| spellout.add(locale); |
| } else if (ruleSetGrouping.equals("OrdinalRules")) { |
| ordinals.add(locale); |
| } else { |
| others.add(ruleSetGrouping); |
| } |
| } |
| } |
| |
| private static void markData(String title, Set<String> localesFound, LocaleLevelData mapLevelData, |
| TreeSet<String> mainAvailable, Level level, long weight, R2<String, String> samples) { |
| if (!mainAvailable.containsAll(localesFound)) { |
| final CBuilder<String, TreeSet<String>> cb = Builder.with(new TreeSet<String>()); |
| System.out.println(title + " Locales that are not in main: " + cb |
| .addAll(localesFound) |
| .removeAll(mainAvailable) |
| .filter(nonAliasLocaleFilter).get()); |
| } |
| for (String locale : mainAvailable) { |
| if (localesFound.contains(locale)) { |
| mapLevelData.get(locale).found.add(level, weight); |
| } else { |
| System.out.println(locale + "\t" + english.getName(locale) + "\t" + "missing " + title); |
| mapLevelData.get(locale).missing.add(level, weight); |
| mapLevelData.get(locale).samples.put(level, samples); |
| } |
| } |
| } |
| |
| enum LocaleStatus { |
| BASE, ALIAS, VARIANT, DEFAULT_CONTENTS |
| } |
| |
| private static class LocaleFilter implements Transform<String, LocaleStatus> { |
| private final LanguageTagParser ltp = new LanguageTagParser(); |
| private final boolean checkAliases; |
| |
| public LocaleFilter(boolean checkAliases) { |
| this.checkAliases = checkAliases; |
| } |
| |
| private boolean skipLocale(String locale, Relation<String, String> localeToVariants) { |
| LocaleStatus result = transform(locale); |
| if (localeToVariants != null) { |
| localeToVariants.put(ltp.getLanguageScript(), ltp.getRegion()); |
| } |
| return result != LocaleStatus.BASE; |
| } |
| |
| public LocaleStatus transform(String locale) { |
| ltp.set(locale); |
| if (checkAliases) { |
| String language = ltp.getLanguage(); |
| if (languageAliasInfo.get(language) != null) { |
| return LocaleStatus.ALIAS; |
| } |
| } |
| if (ltp.getRegion().length() != 0 || !ltp.getVariants().isEmpty()) { |
| // skip country locales, variants |
| return LocaleStatus.VARIANT; |
| } |
| if (defaultContents.contains(locale)) { |
| return LocaleStatus.DEFAULT_CONTENTS; |
| } |
| return LocaleStatus.BASE; |
| } |
| } |
| |
| private static class BooleanLocaleFilter implements Transform<String, Boolean> { |
| private final LocaleFilter filter = new LocaleFilter(false); |
| |
| public Boolean transform(String locale) { |
| return filter.transform(locale) == LocaleStatus.BASE ? Boolean.TRUE : Boolean.FALSE; |
| } |
| } |
| |
| private static void getCollationData(String locale, CLDRFile cldrFile, Set<String> localesFound) { |
| XPathParts parts = new XPathParts(); |
| for (String path : cldrFile) { |
| if (path.endsWith("/alias")) { |
| continue; |
| } |
| if (!path.contains("collations")) { |
| continue; |
| } |
| if (skipUnconfirmed(path)) { |
| continue; |
| } |
| localesFound.add(locale); |
| |
| String fullPath = cldrFile.getFullXPath(path); |
| if (fullPath == null) fullPath = path; |
| try { |
| parts.set(fullPath); |
| } catch (RuntimeException e) { |
| throw e; |
| } |
| String validSubLocales = parts.getAttributeValue(1, "validSubLocales"); |
| if (validSubLocales != null) { |
| String[] sublocales = validSubLocales.split("\\s+"); |
| for (String sublocale : sublocales) { |
| if (localeFilter.skipLocale(locale, null)) continue; |
| localesFound.add(sublocale); |
| } |
| } |
| break; |
| } |
| } |
| |
| public static boolean skipUnconfirmed(String path) { |
| return SKIP_UNCONFIRMED && (path.contains("unconfirmed") || path.contains("provisional")); |
| } |
| |
| private static void getMainData(String locale, LevelData levelData, CLDRFile cldrFile) { |
| Status status = new Status(); |
| Set<String> sorted = Builder.with(new TreeSet<String>()).addAll(cldrFile.iterator()) |
| .addAll(cldrFile.getExtraPaths()).get(); |
| CoverageInfo coverageInfo = CLDRConfig.getInstance().getCoverageInfo(); |
| for (String path : sorted) { |
| if (path.endsWith("/alias")) { |
| continue; |
| } |
| |
| String fullPath = cldrFile.getFullXPath(path); |
| String source = cldrFile.getSourceLocaleID(path, status); |
| Inheritance inherited = !source.equals(locale) || skipUnconfirmed(path) |
| ? Inheritance.inherited |
| : Inheritance.actual; |
| |
| // Level level = sdi.getCoverageLevel(fullPath, locale); |
| Level level = coverageInfo.getCoverageLevel(fullPath, locale); |
| if (inherited == Inheritance.actual) { |
| levelData.found.add(level, 1); |
| } else { |
| levelData.missing.add(level, 1); |
| if (SHOW_EXAMPLES > 0) { |
| Set<R2<String, String>> samplesAlready = levelData.samples.getAll(level); |
| if (samplesAlready == null || samplesAlready.size() < SHOW_EXAMPLES) { |
| levelData.samples.put(level, Row.of(path, cldrFile.getStringValue(path))); |
| } |
| } |
| } |
| } |
| } |
| |
| static class LevelData { |
| Counter<Level> missing = new Counter<Level>(); |
| Relation<Level, R2<String, String>> samples = Relation.of(new EnumMap<Level, Set<R2<String, String>>>( |
| Level.class), LinkedHashSet.class); |
| Counter<Level> found = new Counter<Level>(); |
| } |
| |
| static class LocaleLevelData { |
| Map<String, LevelData> locale_levelData = new TreeMap<String, LevelData>(); |
| |
| public LevelData get(String locale) { |
| if (locale.equals("zh_Hans") || locale.equals("iw")) { |
| throw new IllegalArgumentException(); |
| } |
| LevelData result = locale_levelData.get(locale); |
| if (result == null) { |
| locale_levelData.put(locale, result = new LevelData()); |
| } |
| return result; |
| } |
| |
| public Set<String> keySet() { |
| return locale_levelData.keySet(); |
| } |
| } |
| |
| } |