1 package org.unicode.cldr.test; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.PrintWriter; 6 import java.util.ArrayList; 7 import java.util.Arrays; 8 import java.util.Collection; 9 import java.util.Collections; 10 import java.util.Comparator; 11 import java.util.EnumSet; 12 import java.util.HashMap; 13 import java.util.HashSet; 14 import java.util.Iterator; 15 import java.util.List; 16 import java.util.Map; 17 import java.util.Set; 18 import java.util.TreeMap; 19 import java.util.TreeSet; 20 import java.util.concurrent.ConcurrentHashMap; 21 import java.util.regex.Matcher; 22 23 import org.unicode.cldr.draft.FileUtilities; 24 import org.unicode.cldr.test.CheckCLDR.CheckStatus; 25 import org.unicode.cldr.test.CheckCLDR.CheckStatus.Subtype; 26 import org.unicode.cldr.test.CheckCLDR.CompoundCheckCLDR; 27 import org.unicode.cldr.test.CheckCLDR.FormatDemo; 28 import org.unicode.cldr.test.CheckCLDR.Options; 29 import org.unicode.cldr.test.CheckCLDR.Phase; 30 import org.unicode.cldr.test.CheckCLDR.SimpleDemo; 31 import org.unicode.cldr.tool.Option; 32 import org.unicode.cldr.tool.Option.Params; 33 import org.unicode.cldr.tool.ShowData; 34 import org.unicode.cldr.tool.TablePrinter; 35 import org.unicode.cldr.util.CLDRConfig; 36 import org.unicode.cldr.util.CLDRConfig.Environment; 37 import org.unicode.cldr.util.CLDRFile; 38 import org.unicode.cldr.util.CLDRFile.Status; 39 import org.unicode.cldr.util.CLDRPaths; 40 import org.unicode.cldr.util.CLDRTool; 41 import org.unicode.cldr.util.CldrUtility; 42 import org.unicode.cldr.util.Counter; 43 import org.unicode.cldr.util.CoverageInfo; 44 import org.unicode.cldr.util.Factory; 45 import org.unicode.cldr.util.LanguageTagParser; 46 import org.unicode.cldr.util.Level; 47 import org.unicode.cldr.util.LocaleIDParser; 48 import org.unicode.cldr.util.LogicalGrouping; 49 import org.unicode.cldr.util.Organization; 50 import org.unicode.cldr.util.Pair; 51 import org.unicode.cldr.util.PathDescription; 52 import org.unicode.cldr.util.PathHeader; 53 import org.unicode.cldr.util.PathHeader.SectionId; 54 import org.unicode.cldr.util.PathUtilities; 55 import org.unicode.cldr.util.PatternCache; 56 import org.unicode.cldr.util.SimpleFactory; 57 import org.unicode.cldr.util.StandardCodes; 58 import org.unicode.cldr.util.StringId; 59 import org.unicode.cldr.util.SupplementalDataInfo; 60 import org.unicode.cldr.util.UnicodeSetPrettyPrinter; 61 import org.unicode.cldr.util.VoteResolver; 62 import org.unicode.cldr.util.VoteResolver.CandidateInfo; 63 import org.unicode.cldr.util.VoteResolver.UnknownVoterException; 64 import org.unicode.cldr.util.VoterInfoList; 65 import org.unicode.cldr.util.XMLSource; 66 import org.unicode.cldr.util.XMLSource.SourceLocation; 67 import org.unicode.cldr.util.XPathParts; 68 69 import com.ibm.icu.dev.tool.UOption; 70 import com.ibm.icu.dev.util.ElapsedTimer; 71 import com.ibm.icu.impl.Relation; 72 import com.ibm.icu.impl.Row; 73 import com.ibm.icu.lang.UCharacter; 74 import com.ibm.icu.text.Collator; 75 import com.ibm.icu.text.UnicodeSet; 76 import com.ibm.icu.util.ULocale; 77 78 /** 79 * Console test for CheckCLDR. <br> 80 * Some common source directories: 81 * 82 * <pre> 83 * -s C:/cvsdata/unicode/cldr/incoming/vetted/main 84 * -s C:/cvsdata/unicode/cldr/incoming/proposed/main 85 * -s C:/cvsdata/unicode/cldr/incoming/proposed/main 86 * -s C:/cvsdata/unicode/cldr/testdata/main 87 * </pre> 88 * 89 * @author markdavis 90 * 91 */ 92 @CLDRTool(alias = "check", 93 description = "Run CheckCLDR against CLDR data") 94 public class ConsoleCheckCLDR { 95 private static final CLDRConfig CLDR_CONFIG = CLDRConfig.getInstance(); 96 public static boolean showStackTrace = false; 97 public static boolean errorsOnly = false; 98 static boolean SHOW_LOCALE = true; 99 static boolean SHOW_EXAMPLES = false; 100 private static boolean CLDR_GITHUB_ANNOTATIONS = (Boolean.parseBoolean(System.getProperty("CLDR_GITHUB_ANNOTATIONS", "false"))); 101 102 // TODO get ride of these in favor of MyOptions 103 104 private static final int 105 COVERAGE = 2, 106 EXAMPLES = 3, 107 FILE_FILTER = 4, 108 TEST_FILTER = 5, 109 DATE_FORMATS = 6, 110 ORGANIZATION = 7, 111 SHOWALL = 8, 112 PATH_FILTER = 9, 113 ERRORS_ONLY = 10, 114 CHECK_ON_SUBMIT = 11, 115 NO_ALIASES = 12, 116 SOURCE_DIRECTORY = 13, 117 USER = 14, 118 PHASE = 15, 119 GENERATE_HTML = 16, 120 VOTE_RESOLVE = 17, 121 ID_VIEW = 18, 122 SUBTYPE_FILTER = 19, 123 BAILEY = 21 124 ; 125 126 static final String SOURCE_DIRS = CLDRPaths.MAIN_DIRECTORY + "," + CLDRPaths.ANNOTATIONS_DIRECTORY + "," + CLDRPaths.SEED_DIRECTORY; 127 128 enum MyOptions { 129 coverage(new Params().setHelp("Set the coverage: eg -c comprehensive") 130 .setMatch("comprehensive|modern|moderate|basic")), // UOption.REQUIRES_ARG 131 examples(new Params().setHelp("Turn on examples (actually a summary of the demo)") 132 .setFlag('x')), //, 'x', UOption.NO_ARG), 133 file_filter(new Params().setHelp("Pick the locales (files) to check: arg is a regular expression, eg -f fr, or -f fr.*, or -f (fr|en-.*)") 134 .setDefault(".*").setMatch(".*")), //, 'f', UOption.REQUIRES_ARG).setDefault(".*"), 135 test_filter(new Params() 136 .setHelp("Filter the Checks: arg is a regular expression, eg -t.*number.*. To check all BUT a given test, use the style -t ((?!.*CheckZones).*)") 137 .setDefault(".*").setMatch(".*")), //, 't', UOption.REQUIRES_ARG).setDefault(".*"), 138 date_formats(new Params().setHelp("Turn on special date format checks")), //, 'd', UOption.NO_ARG), 139 organization(new Params().setHelp("Organization: ibm, google, ....; Uses Locales.txt for to filter locales and set coverage levels") 140 .setDefault(".*").setMatch(".*")), //, 'o', UOption.REQUIRES_ARG), 141 showall(new Params().setHelp("Show all paths, including aliased").setFlag('a')), //, 'a', UOption.NO_ARG), 142 path_filter(new Params().setHelp("Pick the paths to check, eg -p.*languages.*") 143 .setDefault(".*").setMatch(".*")), //, 'p', UOption.REQUIRES_ARG).setDefault(".*"), 144 errors_only(new Params().setHelp("Show errors only (with -ef, only final processing errors)")), //, 'e', UOption.NO_ARG), 145 check_on_submit(new Params().setHelp("") 146 .setFlag('k')), //, 'k', UOption.NO_ARG), 147 noaliases(new Params().setHelp("No aliases")), //, 'n', UOption.NO_ARG), 148 source_directory(new Params().setHelp("Fully qualified source directories. (Conflicts with -S.)") 149 .setDefault(SOURCE_DIRS).setMatch(".*")), //, 's', UOption.REQUIRES_ARG).setDefault(SOURCE_DIRS), 150 user(new Params().setHelp("User, eg -uu148") 151 .setMatch(".*")), //, 'u', UOption.REQUIRES_ARG), 152 phase(new Params().setHelp("?") 153 .setMatch(Phase.class).setFlag('z')), //, 'z', UOption.REQUIRES_ARG), 154 generate_html(new Params().setHelp("Generate HTML-style chart in directory.") 155 .setDefault(CLDRPaths.CHART_DIRECTORY + "/errors/").setMatch(".*")), //, 'g', UOption.OPTIONAL_ARG).setDefault(CLDRPaths.CHART_DIRECTORY + "/errors/"), 156 vote_resolution(new Params().setHelp("")), //, 'v', UOption.NO_ARG), 157 id_view(new Params().setHelp("")), //, 'i', UOption.NO_ARG), 158 subtype_filter(new Params().setHelp("error/warning subtype filter, eg unexpectedOrderOfEraYear") 159 .setDefault(".*").setMatch(".*").setFlag('y')), //, 'y', UOption.REQUIRES_ARG), 160 source_all(new Params().setHelp( 161 "Partially qualified directories. Standard subdirectories added if not specified (/main, /annotations, /subdivisions). (Conflicts with -s.)") 162 .setMatch(".*").setFlag('S').setDefault("common,seed,exemplars")), //, 'S', <changed>), 163 bailey(new Params().setHelp("check bailey values (" + CldrUtility.INHERITANCE_MARKER + ")")), //, 'b', UOption.NO_ARG) 164 exemplarError(new Params().setFlag('E').setHelp("include to force strict Exemplar check")), 165 missingPaths(new Params().setHelp("include to show missing and provisional paths, at the specified level")); 166 167 // BOILERPLATE TO COPY 168 final Option option; 169 MyOptions(Params params)170 private MyOptions(Params params) { 171 option = new Option(this, params); 172 } 173 174 private static Option.Options myOptions = new Option.Options(); 175 static { 176 for (MyOptions option : MyOptions.values()) { myOptions.add(option, option.option)177 myOptions.add(option, option.option); 178 } 179 } 180 parse(String[] args, boolean showArguments)181 private static Set<String> parse(String[] args, boolean showArguments) { 182 return myOptions.parse(MyOptions.values()[0], args, true); 183 } 184 } 185 186 // TODO get ride of these in favor of MyOptions 187 188 private static final UOption[] options = { 189 UOption.HELP_H(), 190 UOption.HELP_QUESTION_MARK(), 191 UOption.create("coverage", 'c', UOption.REQUIRES_ARG), 192 UOption.create("examples", 'x', UOption.NO_ARG), 193 UOption.create("file_filter", 'f', UOption.REQUIRES_ARG).setDefault(".*"), 194 UOption.create("test_filter", 't', UOption.REQUIRES_ARG).setDefault(".*"), 195 UOption.create("date_formats", 'd', UOption.NO_ARG), 196 UOption.create("organization", 'o', UOption.REQUIRES_ARG), 197 UOption.create("showall", 'a', UOption.NO_ARG), 198 UOption.create("path_filter", 'p', UOption.REQUIRES_ARG).setDefault(".*"), 199 UOption.create("errors_only", 'e', UOption.NO_ARG), 200 UOption.create("check-on-submit", 'k', UOption.NO_ARG), 201 UOption.create("noaliases", 'n', UOption.NO_ARG), 202 UOption.create("source_directory", 's', UOption.REQUIRES_ARG).setDefault(SOURCE_DIRS), 203 UOption.create("user", 'u', UOption.REQUIRES_ARG), 204 UOption.create("phase", 'z', UOption.REQUIRES_ARG), 205 UOption.create("generate_html", 'g', UOption.OPTIONAL_ARG).setDefault(CLDRPaths.CHART_DIRECTORY + "/errors/"), 206 UOption.create("vote resolution", 'v', UOption.NO_ARG), 207 UOption.create("id view", 'i', UOption.NO_ARG), 208 UOption.create("subtype_filter", 'y', UOption.REQUIRES_ARG), 209 UOption.create("source_all", 'S', UOption.OPTIONAL_ARG).setDefault("common,seed,exemplars"), 210 UOption.create("bailey", 'b', UOption.NO_ARG), 211 UOption.create("exemplarError", 'E', UOption.NO_ARG), 212 UOption.create("missingPaths", 'm', UOption.NO_ARG) 213 }; 214 215 private static final Comparator<String> baseFirstCollator = new Comparator<String>() { 216 LanguageTagParser languageTagParser1 = new LanguageTagParser(); 217 LanguageTagParser languageTagParser2 = new LanguageTagParser(); 218 219 @Override 220 public int compare(String o1, String o2) { 221 String ls1 = languageTagParser1.set(o1).getLanguageScript(); 222 String ls2 = languageTagParser2.set(o2).getLanguageScript(); 223 int result = ls1.compareTo(ls2); 224 if (result != 0) return result; 225 return o1.compareTo(o2); 226 } 227 }; 228 private static final boolean PATH_IN_COUNT = false; 229 230 static Counter<ErrorType> subtotalCount = new Counter<>(true); // new ErrorCount(); 231 static Counter<ErrorType> totalCount = new Counter<>(true); 232 233 private enum RawStatus {missing, provisional, present} 234 /** 235 * This will be the test framework way of using these tests. 236 * 237 * @param args 238 * @throws IOException 239 */ main(String[] args)240 public static void main(String[] args) throws IOException { 241 MyOptions.parse(args, true); 242 ElapsedTimer totalTimer = new ElapsedTimer(); 243 UOption.parseArgs(args, options); 244 String factoryFilter = options[FILE_FILTER].value; 245 if (factoryFilter.equals("key")) { 246 factoryFilter = "(en|ru|nl|fr|de|it|pl|es|tr|th|ja|zh|ko|ar|bg|sr|uk|ca|hr|cs|da|fil|fi|hu|id|lv|lt|no|pt|ro|sk|sl|sv|vi|el|he|fa|hi|am|af|et|is|ms|sw|zu|bn|mr|ta|eu|gl|ur|gu|kn|ml|te|zh_Hant|pt_PT|en_GB)"; 247 } 248 String checkFilter = options[TEST_FILTER].value; 249 String subtypeFilterString = options[SUBTYPE_FILTER].value; 250 EnumSet<Subtype> subtypeFilter = null; 251 if (subtypeFilterString != null) { 252 subtypeFilter = EnumSet.noneOf(Subtype.class); 253 Matcher m = PatternCache.get(subtypeFilterString).matcher(""); 254 for (Subtype value : Subtype.values()) { 255 if (m.reset(value.toString()).find() || m.reset(value.name()).find()) { 256 subtypeFilter.add(value); 257 } 258 } 259 if (subtypeFilter.size() == 0) { 260 System.err.println("No subtype match for " + subtypeFilterString); 261 return; 262 } 263 } 264 265 errorsOnly = options[ERRORS_ONLY].doesOccur; 266 boolean showMissing = MyOptions.missingPaths.option.doesOccur(); 267 268 SHOW_EXAMPLES = options[EXAMPLES].doesOccur; 269 boolean showAll = options[SHOWALL].doesOccur; 270 boolean checkFlexibleDates = options[DATE_FORMATS].doesOccur; 271 String pathFilterString = options[PATH_FILTER].value; 272 Matcher pathFilter = null; 273 if (!pathFilterString.equals(".*")) { 274 pathFilter = PatternCache.get(pathFilterString).matcher(""); 275 } 276 boolean checkOnSubmit = options[CHECK_ON_SUBMIT].doesOccur; 277 boolean noaliases = options[NO_ALIASES].doesOccur; 278 279 Level coverageLevel = null; 280 String coverageLevelInput = options[COVERAGE].value; 281 if (coverageLevelInput != null) { 282 coverageLevel = Level.get(coverageLevelInput); 283 if (coverageLevel == Level.UNDETERMINED) { 284 throw new IllegalArgumentException("-c" + coverageLevelInput + "\t is invalid: must be one of: " 285 + "basic,moderate,..."); 286 } 287 } 288 289 Organization organization = options[ORGANIZATION].value == null ? null : Organization.fromString(options[ORGANIZATION].value); 290 if (organization != null) { 291 Set<Organization> organizations = StandardCodes.make().getLocaleCoverageOrganizations(); 292 if (!organizations.contains(organization)) { 293 throw new IllegalArgumentException("-o" + organization + "\t is invalid: must be one of: " 294 + organizations); 295 } 296 } 297 final CLDRConfig cldrConf = CLDR_CONFIG; 298 cldrConf.setEnvironment(Environment.UNITTEST); 299 final Phase phase; 300 if (options[PHASE].doesOccur) { 301 String phaseVal = options[PHASE].value; 302 try { 303 // no null check for argument; if it is is null, Phase.forString would return the one from CLDRConfig 304 phase = Phase.forString(phaseVal); 305 } catch (IllegalArgumentException e) { 306 StringBuilder sb = new StringBuilder("Incorrect Phase value"); 307 if (phaseVal != null && !phaseVal.isEmpty()) { 308 sb.append(" '"); 309 sb.append(phaseVal); 310 sb.append("'"); 311 } 312 sb.append(": should be one of "); 313 for (Phase curPhase : Phase.values()) { 314 // implicitly does a toString; 315 sb.append(curPhase); 316 sb.append(", "); 317 } 318 int lastIdx = sb.lastIndexOf(","); 319 // remove the last comma, if it occurs 320 if (lastIdx > -1) { 321 String tmpBuf = sb.substring(0, lastIdx); 322 sb.setLength(0); 323 sb.append(tmpBuf); 324 } 325 sb.append("."); 326 // TODO: Reporting should be similar to an error (wrong parameter...), and not actually an Exception 327 throw new IllegalArgumentException(sb.toString(), e); 328 } 329 } else { 330 phase = cldrConf.getPhase(); 331 } 332 333 boolean baileyTest = options[BAILEY].doesOccur; 334 335 File sourceDirectories[] = null; 336 337 if (MyOptions.source_all.option.doesOccur()) { 338 if (MyOptions.source_directory.option.doesOccur()) { 339 throw new IllegalArgumentException("Don't use -s and -S together."); 340 } 341 sourceDirectories = cldrConf.addStandardSubdirectories(cldrConf.getCLDRDataDirectories(MyOptions.source_all.option.getValue())); 342 } else { 343 String[] sdirs = options[SOURCE_DIRECTORY].value.split(",\\s*"); 344 sourceDirectories = new File[sdirs.length]; 345 for (int i = 0; i < sdirs.length; ++i) { 346 sourceDirectories[i] = new File(CldrUtility.checkValidDirectory(sdirs[i], 347 "Fix with -s. Use -h for help.")); 348 } 349 } 350 351 if (options[GENERATE_HTML].doesOccur) { 352 coverageLevel = Level.MODERN; // reset 353 ErrorFile.generated_html_directory = options[GENERATE_HTML].value; 354 ErrorFile.generated_html_count = FileUtilities.openUTF8Writer(ErrorFile.generated_html_directory, "count.txt"); 355 } 356 357 idView = options[ID_VIEW].doesOccur; 358 359 if (options[VOTE_RESOLVE].doesOccur) { 360 resolveVotesDirectory = CldrUtility.checkValidFile(CLDRPaths.BASE_DIRECTORY + "incoming/vetted/votes/", 361 true, null); 362 voterInfoList.setVoterToInfo(CldrUtility.checkValidFile(CLDRPaths.BASE_DIRECTORY 363 + "incoming/vetted/usersa/usersa.xml", false, null)); 364 voteResolver = new VoteResolver<>(voterInfoList); 365 } 366 367 String user = options[USER].value; 368 369 System.out.println("Source directories:\n"); 370 for (File f : sourceDirectories) { 371 System.out.println(" " + f.getPath() + "\t(" 372 + PathUtilities.getNormalizedPathString(f) + ")"); 373 } 374 375 // set up the test 376 Factory cldrFactory = SimpleFactory.make(sourceDirectories, factoryFilter) 377 .setSupplementalDirectory(new File(CLDRPaths.SUPPLEMENTAL_DIRECTORY)); 378 CompoundCheckCLDR checkCldr = CheckCLDR.getCheckAll(cldrFactory, checkFilter); 379 if (checkCldr.getFilteredTestList().size() == 0) { 380 throw new IllegalArgumentException("The filter doesn't match any tests."); 381 } 382 System.out.println("filtered tests: " + checkCldr.getFilteredTests()); 383 Factory backCldrFactory = CLDRConfig.getInstance().getMainAndAnnotationsFactory(); 384 english = backCldrFactory.make("en", true); 385 386 CheckCLDR.setDisplayInformation(english); 387 checkCldr.setEnglishFile(english); 388 setExampleGenerator(new ExampleGenerator(english, english, CLDRPaths.SUPPLEMENTAL_DIRECTORY)); 389 PathShower pathShower = new PathShower(); 390 391 // call on the files 392 Set<String> locales = new TreeSet<>(baseFirstCollator); 393 locales.addAll(cldrFactory.getAvailable()); 394 395 List<CheckStatus> result = new ArrayList<>(); 396 Set<PathHeader> paths = new TreeSet<>(); // CLDRFile.ldmlComparator); 397 Map<String, String> m = new TreeMap<>(); 398 Map<String, String> options = new HashMap<>(); 399 FlexibleDateFromCLDR fset = new FlexibleDateFromCLDR(); 400 Set<String> englishPaths = null; 401 402 Set<String> fatalErrors = new TreeSet<>(); 403 404 showHeaderLine(); 405 406 supplementalDataInfo = SupplementalDataInfo.getInstance(CLDRPaths.SUPPLEMENTAL_DIRECTORY); 407 408 LocaleIDParser localeIDParser = new LocaleIDParser(); 409 String lastBaseLanguage = ""; 410 PathHeader.Factory pathHeaderFactory = PathHeader.getFactory(english); 411 412 final Map<String, Level> locale_status = StandardCodes.make().getLocaleToLevel(organization); 413 414 final List<String> specialPurposeLocales = new ArrayList<>(Arrays.asList("en_US_POSIX", "en_ZZ")); 415 for (String localeID : locales) { 416 if (CLDRFile.isSupplementalName(localeID)) continue; 417 if (supplementalDataInfo.getDefaultContentLocales().contains(localeID)) { 418 System.out.println("# Skipping default content locale: " + localeID); 419 continue; 420 } 421 422 // We don't really need to check the POSIX locale, as it is a special purpose locale 423 if (specialPurposeLocales.contains(localeID)) { 424 System.out.println("# Skipping special purpose locale: " + localeID); 425 continue; 426 } 427 428 boolean isLanguageLocale = localeID.equals(localeIDParser.set(localeID).getLanguageScript()); 429 options.clear(); 430 431 if (MyOptions.exemplarError.option.doesOccur()) { 432 options.put(Options.Option.exemplarErrors.toString(), "true"); 433 } 434 435 // if the organization is set, skip any locale that doesn't have a value in Locales.txt 436 Level level = coverageLevel; 437 if (level == null) { 438 level = Level.MODERN; 439 } 440 if (organization != null) { 441 if (locale_status == null) continue; 442 level = locale_status.get(localeID); 443 if (level == null) continue; 444 if (level.compareTo(Level.BASIC) < 0) continue; 445 } else if (!isLanguageLocale) { 446 // otherwise, skip all language locales 447 options.put(Options.Option.CheckCoverage_skip.getKey(), "true"); 448 } 449 450 //if (organization != null) options.put(Options.Option.CoverageLevel_localeType.getKey(), organization.toString()); 451 options.put(Options.Option.phase.getKey(), phase.toString()); 452 453 if (SHOW_LOCALE) System.out.println(); 454 455 CLDRFile file; 456 CLDRFile englishFile = english; 457 CLDRFile parent = null; 458 459 ElapsedTimer timer = new ElapsedTimer(); 460 try { 461 file = cldrFactory.make(localeID, true); 462 if (ErrorFile.voteFactory != null) { 463 ErrorFile.voteFile = ErrorFile.voteFactory.make(localeID, true); 464 } 465 final String parentID = LocaleIDParser.getParent(localeID); 466 if (parentID != null) { 467 parent = cldrFactory.make(parentID, true); 468 } 469 } catch (RuntimeException e) { 470 fatalErrors.add(localeID); 471 System.out.println("FATAL ERROR: " + localeID); 472 e.printStackTrace(System.out); 473 continue; 474 } 475 476 // generate HTML if asked for 477 if (ErrorFile.generated_html_directory != null) { 478 String baseLanguage = localeIDParser.set(localeID).getLanguageScript(); 479 480 if (!baseLanguage.equals(lastBaseLanguage)) { 481 lastBaseLanguage = baseLanguage; 482 ErrorFile.openErrorFile(localeID, baseLanguage); 483 } 484 } 485 486 if (user != null) { 487 file = new CLDRFile.TestUser(file, user, isLanguageLocale); 488 if (parent != null) { 489 parent = new CLDRFile.TestUser(parent, user, isLanguageLocale); 490 } 491 } 492 checkCldr.setCldrFileToCheck(file, new Options(options), result); 493 494 subtotalCount.clear(); 495 496 for (Iterator<CheckStatus> it3 = result.iterator(); it3.hasNext();) { 497 CheckStatus status = it3.next(); 498 String statusString = status.toString(); // com.ibm.icu.impl.Utility.escape( 499 CheckStatus.Type statusType = status.getType(); 500 501 if (errorsOnly) { 502 if (!statusType.equals(CheckStatus.errorType)) continue; 503 } 504 505 if (subtypeFilter != null) { 506 if (!subtypeFilter.contains(status.getSubtype())) { 507 continue; 508 } 509 } 510 511 if (checkOnSubmit) { 512 if (!status.isCheckOnSubmit() || !statusType.equals(CheckStatus.errorType)) continue; 513 } 514 showValue(file, null, localeID, null, null, null, null, statusString, status.getSubtype()); 515 } 516 paths.clear(); 517 518 CoverageInfo covInfo = cldrConf.getCoverageInfo(); 519 for (String path : file.fullIterable()) { 520 if (pathFilter != null && !pathFilter.reset(path).find()) { 521 continue; 522 } 523 if (level != null) { 524 Level currentLevel = covInfo.getCoverageLevel(path, localeID); 525 if (currentLevel.compareTo(level) > 0) { 526 continue; 527 } 528 } 529 final PathHeader pathHeader = pathHeaderFactory.fromPath(path); 530 if (pathHeader.getSectionId() != SectionId.Special) { 531 paths.add(pathHeader); 532 } 533 } 534 535 // also add the English paths 536 // initialize the first time in. 537 if (englishPaths == null) { 538 englishPaths = new HashSet<>(); 539 final CLDRFile displayFile = CheckCLDR.getDisplayInformation(); 540 addPrettyPaths(displayFile, pathFilter, pathHeaderFactory, noaliases, true, englishPaths); 541 addPrettyPaths(displayFile, displayFile.getExtraPaths(), pathFilter, pathHeaderFactory, noaliases, 542 true, englishPaths); 543 englishPaths = Collections.unmodifiableSet(englishPaths); // for robustness 544 } 545 546 UnicodeSet missingExemplars = new UnicodeSet(); 547 UnicodeSet missingCurrencyExemplars = new UnicodeSet(); 548 if (checkFlexibleDates) { 549 fset.set(file); 550 } 551 pathShower.set(localeID); 552 553 // only create if we are going to use 554 ExampleGenerator exampleGenerator = SHOW_EXAMPLES ? new ExampleGenerator(file, englishFile, 555 CLDRPaths.DEFAULT_SUPPLEMENTAL_DIRECTORY) : null; 556 557 int pathCount = 0; 558 Status otherPath = new Status(); 559 int rawMissingCount = 0; 560 int rawProvisionalCount = 0; 561 CLDRFile unresolved = file.getUnresolved(); 562 563 for (PathHeader pathHeader : paths) { 564 pathCount++; 565 String path = pathHeader.getOriginalPath(); 566 String prettyPath = pathHeader.toString().replace('\t', '|').replace(' ', '_'); 567 if (!showAll && !file.isWinningPath(path)) { 568 continue; 569 } 570 final String topValue = unresolved.getStringValue(path); 571 RawStatus rawStatus = RawStatus.present; 572 573 if (topValue == null) { 574 rawStatus = RawStatus.missing; 575 rawMissingCount++; 576 } 577 578 if (!isLanguageLocale && !baileyTest) { 579 final String sourceLocaleID = file.getSourceLocaleID(path, otherPath); 580 if (!localeID.equals(sourceLocaleID)) { 581 continue; 582 } 583 // also skip aliases 584 if (!path.equals(otherPath.pathWhereFound)) { 585 continue; 586 } 587 } 588 if (path.contains("@alt") && path.contains("proposed")) { 589 continue; 590 } 591 String value = file.getStringValue(path); 592 if (baileyTest) { 593 value = CldrUtility.INHERITANCE_MARKER; 594 } 595 596 String fullPath = file.getFullXPath(path); 597 if (topValue != null) { 598 XPathParts fullParts = XPathParts.getFrozenInstance(fullPath); 599 String draftStatus = fullParts.getAttributeValue(-1, "draft"); 600 if (draftStatus != null 601 && !draftStatus.equals("contributed")) { 602 rawProvisionalCount++; 603 rawStatus = RawStatus.provisional; 604 } 605 } 606 if (showMissing && rawStatus != RawStatus.present) { 607 String englishValue = englishFile.getStringValue(path); 608 if (englishValue == null) { 609 englishValue = "n/a"; 610 } 611 System.out.println(getLocaleAndName(localeID) + "\tRaw " + rawStatus 612 + "\t" + pathHeader + "\t" + englishValue + "\t" + path); 613 } 614 615 616 String example = ""; 617 if (SHOW_EXAMPLES) { 618 example = ExampleGenerator.simplify(exampleGenerator.getExampleHtml(path, value)); 619 showExamples(checkCldr, prettyPath, localeID, path, value, fullPath, example); 620 } 621 if (checkFlexibleDates) { 622 fset.checkFlexibles(path, value, fullPath); 623 } 624 int limit = 1; 625 for (int jj = 0; jj < limit; ++jj) { 626 if (jj == 0) { 627 checkCldr.check(path, fullPath, value, new Options(options), result); 628 } else { 629 checkCldr.getExamples(path, fullPath, value, new Options(options), result); 630 } 631 632 boolean showedOne = false; 633 for (Iterator<CheckStatus> it3 = result.iterator(); it3.hasNext();) { 634 CheckStatus status = it3.next(); 635 String statusString = status.toString(); // com.ibm.icu.impl.Utility.escape( 636 CheckStatus.Type statusType = status.getType(); 637 Object[] parameters = status.getParameters(); 638 639 if (parameters != null) { 640 if (parameters.length >= 1 && status.getCause().getClass() == CheckForExemplars.class) { 641 try { 642 UnicodeSet set = new UnicodeSet(parameters[0].toString()); 643 if (status.getMessage().contains("currency")) { 644 missingCurrencyExemplars.addAll(set); 645 } else { 646 missingExemplars.addAll(set); 647 } 648 } catch (RuntimeException e) { 649 } // skip if not parseable as set 650 } 651 } 652 653 if (errorsOnly && !statusType.equals(CheckStatus.errorType)) { 654 continue; 655 } 656 657 if (subtypeFilter != null) { 658 if (!subtypeFilter.contains(status.getSubtype())) { 659 continue; 660 } 661 } 662 if (checkOnSubmit) { 663 if (!status.isCheckOnSubmit() || !statusType.equals(CheckStatus.errorType)) continue; 664 } 665 666 if (statusType.equals(CheckStatus.demoType)) { 667 SimpleDemo d = status.getDemo(); 668 if (d != null && d instanceof FormatDemo) { 669 FormatDemo fd = (FormatDemo) d; 670 m.clear(); 671 if (d.processPost(m)) System.out.println("\tDemo:\t" + fd.getPlainText(m)); 672 } 673 continue; 674 } 675 676 if (parameters != null) { 677 for (int i = 0; i < parameters.length; ++i) { 678 if (showStackTrace && parameters[i] instanceof Throwable) { 679 ((Throwable) parameters[i]).printStackTrace(); 680 } 681 } 682 } 683 684 showValue(file, prettyPath, localeID, example, path, value, fullPath, statusString, 685 status.getSubtype()); 686 showedOne = true; 687 } 688 if (!showedOne && phase != Phase.FINAL_TESTING) { 689 if (!showedOne && showAll) { 690 showValue(file, prettyPath, localeID, example, path, value, fullPath, "ok", Subtype.none); 691 showedOne = true; 692 } 693 } 694 } 695 } 696 697 if (resolveVotesDirectory != null) { 698 LocaleVotingData.resolveErrors(localeID); 699 } 700 701 showSummary(localeID, level, "Items:\t" + pathCount 702 + "\tRaw Missing:\t" + rawMissingCount 703 + "\tRaw Provisional:\t" + rawProvisionalCount); 704 705 if (missingExemplars.size() != 0) { 706 missingExemplars.removeAll(new UnicodeSet("[[:Uppercase:]-[İ]]")); // remove uppercase #4670 707 if (missingExemplars.size() != 0) { 708 Collator col = Collator.getInstance(new ULocale(localeID)); 709 showSummary(localeID, level, "Total missing from general exemplars:\t" + 710 missingExemplars.size() 711 + "\t" + new UnicodeSetPrettyPrinter() 712 .setOrdering(col != null ? col : Collator.getInstance(ULocale.ROOT)) 713 .setSpaceComparator(col != null ? col : Collator.getInstance(ULocale.ROOT) 714 .setStrength2(Collator.PRIMARY)) 715 .setCompressRanges(false) 716 .format(missingExemplars)); 717 } 718 } 719 if (missingCurrencyExemplars.size() != 0) { 720 Collator col = Collator.getInstance(new ULocale(localeID)); 721 showSummary(localeID, level, "Total missing from currency exemplars:\t" 722 + new UnicodeSetPrettyPrinter() 723 .setOrdering(col != null ? col : Collator.getInstance(ULocale.ROOT)) 724 .setSpaceComparator(col != null ? col : Collator.getInstance(ULocale.ROOT) 725 .setStrength2(Collator.PRIMARY)) 726 .setCompressRanges(true) 727 .format(missingCurrencyExemplars)); 728 } 729 for (ErrorType type : subtotalCount.keySet()) { 730 showSummary(localeID, level, "Subtotal " + type + ":\t" + subtotalCount.getCount(type)); 731 } 732 733 if (checkFlexibleDates) { 734 fset.showFlexibles(); 735 } 736 if (SHOW_EXAMPLES) { 737 // ldml/dates/timeZoneNames/zone[@type="America/Argentina/San_Juan"]/exemplarCity 738 for (String zone : StandardCodes.make().getGoodAvailableCodes("tzid")) { 739 String path = "//ldml/dates/timeZoneNames/zone[@type=\"" + zone + "\"]/exemplarCity"; 740 PathHeader pathHeader = pathHeaderFactory.fromPath(path); 741 String prettyPath = pathHeader.toString().replace('\t', '|').replace(' ', '_'); 742 if (pathFilter != null && !pathFilter.reset(path).matches()) { 743 continue; 744 } 745 String fullPath = file.getStringValue(path); 746 if (fullPath != null) { 747 continue; 748 } 749 /* 750 * TODO: fix this code. Calling getExampleHtml with value = null will always return null, 751 * so what's this supposed to accomplish? 752 */ 753 String example = ExampleGenerator.simplify(exampleGenerator.getExampleHtml(path, null /* value */)); 754 showExamples(checkCldr, prettyPath, localeID, path, null, fullPath, example); 755 } 756 } 757 System.out.println("# Elapsed time: " + timer); 758 System.out.flush(); 759 } 760 761 if (ErrorFile.errorFileWriter != null) { 762 ErrorFile.closeErrorFile(); 763 } 764 765 if (ErrorFile.generated_html_directory != null) { 766 ErrorFile.writeErrorCountsText(); 767 ErrorFile.writeErrorFileIndex(); 768 } 769 System.out.println(); 770 for (ErrorType type : totalCount.keySet()) { 771 System.out.println("# Total " + type + ":\t" + totalCount.getCount(type)); 772 } 773 774 System.out.println(); 775 System.out.println("# Total elapsed time: " + totalTimer); 776 if (fatalErrors.size() != 0) { 777 System.out.println("# FATAL ERRORS:"); 778 } 779 long errorCount = totalCount.getCount(ErrorType.error) + fatalErrors.size(); 780 if (errorCount != 0) { 781 System.out.println(); 782 System.out.println("<< FAILURE - Error count is " + errorCount + " . >>"); 783 System.exit(-1); 784 } else { 785 System.out.println(); 786 System.out.println("<< SUCCESS - No errors found. >>"); 787 } 788 if (LogicalGrouping.GET_TYPE_COUNTS) { 789 for (String s : LogicalGrouping.typeCount.keySet()) { 790 System.out.println(s + "=" + LogicalGrouping.typeCount.get(s)); 791 } 792 } 793 checkCldr.handleFinish(); 794 } // end of main() 795 796 static class LocaleVotingData { 797 private int disputedCount = 0; 798 Counter<Organization> missingOrganizationCounter = new Counter<>(true); 799 Counter<Organization> goodOrganizationCounter = new Counter<>(true); 800 Counter<Organization> conflictedOrganizations = new Counter<>(true); 801 Counter<VoteResolver.Status> winningStatusCounter = new Counter<>(true); 802 803 static Map<String, LocaleVotingData> localeToErrors = new HashMap<>(); 804 private static Map<Integer, String> idToPath; 805 resolveErrors(String locale)806 public static void resolveErrors(String locale) { 807 localeToErrors.put(locale, new LocaleVotingData(locale)); 808 } 809 LocaleVotingData(String locale)810 public LocaleVotingData(String locale) { 811 812 Map<Organization, VoteResolver.Level> orgToMaxVote = voterInfoList.getOrganizationToMaxVote(locale); 813 814 Map<Integer, Map<Integer, CandidateInfo>> info = VoteResolver 815 .getBaseToAlternateToInfo(resolveVotesDirectory + locale + ".xml", voterInfoList); 816 817 Map<String, Integer> valueToItem = new HashMap<>(); 818 819 for (int basePath : info.keySet()) { 820 final Map<Integer, CandidateInfo> itemInfo = info.get(basePath); 821 822 // find the last release status and value 823 voteResolver.clear(); 824 valueToItem.clear(); 825 826 for (int item : itemInfo.keySet()) { 827 String itemValue = getValue(item); 828 valueToItem.put(itemValue, item); 829 830 CandidateInfo candidateInfo = itemInfo.get(item); 831 if (candidateInfo.oldStatus != null) { 832 voteResolver.setBaseline(itemValue, candidateInfo.oldStatus); 833 } 834 voteResolver.add(itemValue); 835 for (int voter : candidateInfo.voters) { 836 try { 837 voteResolver.add(itemValue, voter); 838 } catch (UnknownVoterException e) { 839 // skip 840 } 841 } 842 } 843 844 EnumSet<Organization> basePathConflictedOrganizations = voteResolver.getConflictedOrganizations(); 845 conflictedOrganizations.addAll(basePathConflictedOrganizations, 1); 846 847 VoteResolver.Status winningStatus = voteResolver.getWinningStatus(); 848 String winningValue = voteResolver.getWinningValue(); 849 850 winningStatusCounter.add(winningStatus, 1); 851 852 if (winningStatus == VoteResolver.Status.approved) { 853 continue; 854 } 855 856 CandidateInfo candidateInfo = itemInfo.get(valueToItem.get(winningValue)); 857 Map<Organization, VoteResolver.Level> orgToMaxVoteHere = voterInfoList 858 .getOrganizationToMaxVote(candidateInfo.voters); 859 860 // if the winning item is less than contributed, record the organizations that haven't given their 861 // maximum vote to the winning item. 862 if (winningStatus.compareTo(VoteResolver.Status.contributed) < 0) { 863 // showPaths(basePath, itemInfo); 864 for (Organization org : orgToMaxVote.keySet()) { 865 VoteResolver.Level maxVote = orgToMaxVote.get(org); 866 VoteResolver.Level maxVoteHere = orgToMaxVoteHere.get(org); 867 if (maxVoteHere == null || maxVoteHere.compareTo(maxVote) < 0) { 868 missingOrganizationCounter.add(org, 1); 869 } 870 } 871 if (voteResolver.isDisputed()) { 872 disputedCount++; 873 String path = getIdToPath(basePath); 874 ErrorFile.addDataToErrorFile(locale, path, ErrorType.disputed, Subtype.none); 875 } 876 } else { 877 for (Organization org : orgToMaxVote.keySet()) { 878 VoteResolver.Level maxVote = orgToMaxVote.get(org); 879 VoteResolver.Level maxVoteHere = orgToMaxVoteHere.get(org); 880 if (maxVoteHere == null || maxVoteHere.compareTo(maxVote) < 0) { 881 } else { 882 goodOrganizationCounter.add(org, 1); 883 } 884 } 885 } 886 } 887 System.out.println(getLocaleAndName(locale) + "\tEnabled Organizations:\t" + orgToMaxVote); 888 if (disputedCount != 0) { 889 System.out.println(getLocaleAndName(locale) + "\tDisputed Items:\t" + disputedCount); 890 } 891 892 if (missingOrganizationCounter.size() > 0) { 893 System.out.println(getLocaleAndName(locale) + "\tMIA organizations:\t" + missingOrganizationCounter); 894 System.out 895 .println(getLocaleAndName(locale) + "\tConflicted organizations:\t" + conflictedOrganizations); 896 System.out.println(getLocaleAndName(locale) + "\tCool organizations!:\t" + goodOrganizationCounter); 897 } 898 System.out.println(getLocaleAndName(locale) + "\tOptimal Status:\t" + winningStatusCounter); 899 } 900 getIdToPath(int basePath)901 private static String getIdToPath(int basePath) { 902 if (idToPath == null) { 903 idToPath = VoteResolver.getIdToPath(resolveVotesDirectory + "xpathTable.xml"); 904 } 905 return idToPath.get(basePath); 906 } 907 get(String locale)908 public static LocaleVotingData get(String locale) { 909 return localeToErrors.get(locale); 910 } 911 getDisputedCount()912 int getDisputedCount() { 913 return disputedCount; 914 } 915 getConflictedHTML()916 String getConflictedHTML() { 917 String result = conflictedOrganizations.toString(); 918 if (result.length() == 0) { 919 return ""; 920 } 921 result = result.substring(1, result.length() - 1); 922 result = result.replace(", ", "<br>"); 923 return result; 924 } 925 } 926 getValue(int item)927 private static String getValue(int item) { 928 return String.valueOf(item); 929 } 930 931 static Matcher draftStatusMatcher = PatternCache.get("\\[@draft=\"(provisional|unconfirmed)\"]").matcher(""); 932 933 enum ErrorType { 934 ok, error, disputed, warning, core, posix, minimal, basic, moderate, modern, comprehensive, optional, contributed, provisional, unconfirmed, unknown; 935 static EnumSet<ErrorType> unapproved = EnumSet.range(ErrorType.contributed, ErrorType.unconfirmed); 936 static EnumSet<ErrorType> coverage = EnumSet.range(ErrorType.posix, ErrorType.optional); 937 static EnumSet<ErrorType> showInSummary = EnumSet.of( 938 ErrorType.error, ErrorType.warning, ErrorType.posix, ErrorType.minimal, ErrorType.basic); 939 fromStatusString(String statusString)940 static ErrorType fromStatusString(String statusString) { 941 ErrorType shortStatus = statusString.equals("ok") ? ErrorType.ok 942 : statusString.startsWith("Error") ? ErrorType.error 943 : statusString.equals("disputed") ? ErrorType.disputed 944 : statusString.startsWith("Warning") ? ErrorType.warning 945 : statusString.equals("contributed") ? ErrorType.contributed 946 : statusString.equals("provisional") ? ErrorType.provisional 947 : statusString.equals("unconfirmed") ? ErrorType.unconfirmed 948 : ErrorType.unknown; 949 if (shortStatus == ErrorType.unknown) { 950 throw new IllegalArgumentException("Unknown error type: " + statusString); 951 } else if (shortStatus == ErrorType.warning) { 952 if (coverageMatcher.reset(statusString).find()) { 953 shortStatus = ErrorType.valueOf(coverageMatcher.group(1)); 954 } 955 } 956 return shortStatus; 957 } 958 } 959 960 static class ErrorFile { 961 962 private static final boolean SHOW_VOTING_INFO = false; 963 public static CLDRFile voteFile; 964 public static Factory voteFactory; 965 openErrorFile(String localeID, String baseLanguage)966 private static void openErrorFile(String localeID, String baseLanguage) throws IOException { 967 if (ErrorFile.errorFileWriter != null) { 968 ErrorFile.closeErrorFile(); 969 } 970 ErrorFile.errorFileWriter = FileUtilities.openUTF8Writer(ErrorFile.generated_html_directory, baseLanguage + ".html"); 971 ErrorFile.errorFileTable = new TablePrinter(); 972 errorFileCounter.clear(); 973 ErrorFile.errorFileTable.setCaption("Problem Details") 974 .addColumn("Problem").setCellAttributes("align=\"left\" class=\"{0}\"").setSortPriority(0) 975 .setSpanRows(true) 976 .setBreakSpans(true).setRepeatHeader(true).setHeaderCell(true) 977 .addColumn("Subtype").setCellAttributes("align=\"left\" class=\"{1}\"").setSortPriority(1) 978 .setSpanRows(true) 979 .setBreakSpans(true).setRepeatHeader(true).setHeaderCell(true) 980 .addColumn("Locale").setCellAttributes("class=\"{1}\"") 981 .setCellPattern("<a href=\"http://unicode.org/cldr/apps/survey?_={0}\">{0}</a>").setSortPriority(2) 982 .setSpanRows(true).setBreakSpans(true)//.setRepeatDivider(true) 983 .addColumn("Name").setCellAttributes("class=\"{1}\"").setSpanRows(true) 984 .setBreakSpans(true) 985 .addColumn("Section").setCellAttributes("class=\"{1}\"").setSortPriority(3) 986 .setCellPattern("<a href=\"http://unicode.org/cldr/apps/survey?_={3}&x={0}\">{0}</a>") 987 .setSpanRows(true) 988 .addColumn("Count").setCellAttributes("class=\"{1}\" align=\"right\""); 989 990 showIndexHead("", localeID, ErrorFile.errorFileWriter); 991 } 992 993 static TablePrinter errorFileTable = new TablePrinter(); 994 static Counter<Row.R4<String, String, ErrorType, Subtype>> errorFileCounter = new Counter<>( 995 true); 996 addDataToErrorFile(String localeID, String path, ErrorType shortStatus, Subtype subtype)997 private static void addDataToErrorFile(String localeID, String path, ErrorType shortStatus, 998 Subtype subtype) { 999 String section = path == null ? null : XPathToMenu.xpathToMenu(path); 1000 if (section == null) { 1001 section = "general"; 1002 } 1003 errorFileCounter.add( 1004 new Row.R4<>(localeID, section, shortStatus, subtype), 1); 1005 ErrorFile.sectionToProblemsToLocaleToCount.add( 1006 new Row.R4<>(section, shortStatus, subtype, localeID), 1); 1007 } 1008 closeErrorFile()1009 private static void closeErrorFile() { 1010 Set<String> locales = new TreeSet<>(); 1011 for (Row.R4<String, String, ErrorType, Subtype> item : errorFileCounter.keySet()) { 1012 String localeID = item.get0(); 1013 locales.add(localeID); 1014 String section = item.get1(); 1015 ErrorType shortStatus = item.get2(); 1016 Subtype subtype = item.get3(); 1017 errorFileTable.addRow() 1018 .addCell(shortStatus) 1019 .addCell(subtype) 1020 .addCell(localeID) 1021 .addCell(ConsoleCheckCLDR.getLocaleName(localeID)) 1022 .addCell(section) // menuPath == null ? "" : "<a href='" + link + "'>" + menuPath + "</a>" 1023 .addCell(errorFileCounter.getCount(item)) 1024 .finishRow(); 1025 } 1026 1027 if (SHOW_VOTING_INFO) { 1028 TablePrinter data = new TablePrinter().setCaption("Voting Information") 1029 .addColumn("Locale").setHeaderCell(true) 1030 .addColumn("Name").setHeaderCell(true) 1031 .addColumn("Organization") 1032 .addColumn("Missing") 1033 .addColumn("Conflicted") 1034 ; 1035 for (String localeID : locales) { 1036 // now the voting info 1037 LocaleVotingData localeVotingData = LocaleVotingData.localeToErrors.get(localeID); 1038 if (localeVotingData != null) { 1039 // find all the orgs with data 1040 EnumSet<Organization> orgs = EnumSet.noneOf(Organization.class); 1041 orgs.addAll(localeVotingData.missingOrganizationCounter.keySet()); 1042 orgs.addAll(localeVotingData.conflictedOrganizations.keySet()); 1043 orgs.addAll(localeVotingData.goodOrganizationCounter.keySet()); 1044 for (Organization org : orgs) { 1045 data.addRow() 1046 .addCell(ConsoleCheckCLDR.getLinkedLocale(localeID)) 1047 .addCell(ConsoleCheckCLDR.getLocaleName(localeID)) 1048 .addCell(org) 1049 .addCell(localeVotingData.missingOrganizationCounter.getCount(org)) 1050 .addCell(localeVotingData.conflictedOrganizations.getCount(org)) 1051 .finishRow(); 1052 } 1053 } 1054 } 1055 ErrorFile.errorFileWriter.println(data.toTable()); 1056 ErrorFile.errorFileWriter.println("<p></p>"); 1057 } 1058 1059 // generated_html.println("<table border='1' style='border-collapse: collapse' bordercolor='#CCCCFF'>"); 1060 // Locale Group Error Warning Missing Votes: Contributed Missing Votes: Provisional Missing Votes: 1061 // Unconfirmed Missing Coverage: Posix Missing Coverage: Minimal Missing Coverage: Basic Missing Coverage: 1062 // Moderate Missing Coverage: Modern 1063 ErrorFile.errorFileWriter.println(ErrorFile.errorFileTable.toTable()); 1064 ErrorFile.errorFileWriter.println(ShowData.dateFooter()); 1065 ErrorFile.errorFileWriter.println(CldrUtility.ANALYTICS); 1066 ErrorFile.errorFileWriter.println("</body></html>"); 1067 ErrorFile.errorFileWriter.close(); 1068 ErrorFile.errorFileTable = null; 1069 } 1070 1071 // ================ Index File =================== 1072 showErrorFileIndex(PrintWriter generated_html_index)1073 static void showErrorFileIndex(PrintWriter generated_html_index) { 1074 1075 // get organizations 1076 Relation<Organization, String> orgToLocales = getOrgToLocales(); 1077 1078 TablePrinter indexTablePrinter = new TablePrinter().setCaption("Problem Summary") 1079 .setTableAttributes("border='1' style='border-collapse: collapse' bordercolor='blue'") 1080 .addColumn("BASE").setHidden(true)//.setRepeatDivider(true) 1081 .addColumn("Locale").setCellPattern("<a name=\"{0}\" href=\"{1}.html\">{0}</a>") // link to base, anchor 1082 // with full 1083 .addColumn("Name"); 1084 if (SHOW_VOTING_INFO) { 1085 indexTablePrinter.addColumn("Summary") 1086 .addColumn("Missing"); 1087 } 1088 for (Organization org : orgToLocales.keySet()) { 1089 indexTablePrinter.addColumn(org.toString().substring(0, 2)); 1090 } 1091 indexTablePrinter 1092 .addColumn("Disputed").setHeaderAttributes("class='disputed'").setCellAttributes("class='disputed'") 1093 .addColumn("Conflicted").setHeaderAttributes("class='conflicted'") 1094 .setCellAttributes("class='conflicted'"); 1095 1096 for (ConsoleCheckCLDR.ErrorType type : ConsoleCheckCLDR.ErrorType.showInSummary) { 1097 String columnTitle = UCharacter.toTitleCase(type.toString(), null); 1098 final boolean coverage = ConsoleCheckCLDR.ErrorType.coverage.contains(type); 1099 if (coverage) { 1100 columnTitle = "MC: " + columnTitle; 1101 } else if (ConsoleCheckCLDR.ErrorType.unapproved.contains(type)) { 1102 columnTitle = "MV: " + columnTitle; 1103 } 1104 indexTablePrinter.addColumn(columnTitle).setHeaderAttributes("class='" + type + "'") 1105 .setCellAttributes("class='" + type + "'"); 1106 } 1107 1108 // now fill in the data 1109 LanguageTagParser ltp = new LanguageTagParser(); 1110 for (String key : ErrorFile.errorFileIndexData.keySet()) { 1111 Pair<String, Counter<ErrorType>> pair = ErrorFile.errorFileIndexData.get(key); 1112 String htmlOpenedFileLanguage = pair.getFirst(); 1113 Counter<ErrorType> counts = pair.getSecond(); 1114 LocaleVotingData votingData = LocaleVotingData.get(htmlOpenedFileLanguage); 1115 if (counts.getTotal() == 0) { 1116 continue; 1117 } 1118 final String baseLanguage = ltp.set(htmlOpenedFileLanguage).getLanguage(); 1119 indexTablePrinter.addRow() 1120 .addCell(baseLanguage) 1121 .addCell(htmlOpenedFileLanguage) 1122 .addCell(ConsoleCheckCLDR.getLocaleName(htmlOpenedFileLanguage)); 1123 if (SHOW_VOTING_INFO) { 1124 indexTablePrinter.addCell(votingData == null ? "" : votingData.winningStatusCounter.toString()) 1125 .addCell(votingData == null ? "" : votingData.missingOrganizationCounter.toString()); 1126 } 1127 for (Organization org : orgToLocales.keySet()) { 1128 indexTablePrinter.addCell(orgToLocales.getAll(org).contains(htmlOpenedFileLanguage) ? org.toString() 1129 .substring(0, 2) : ""); 1130 } 1131 indexTablePrinter 1132 .addCell(votingData == null ? "" : formatSkippingZero(votingData.getDisputedCount())) 1133 .addCell(votingData == null ? "" : votingData.getConflictedHTML()); 1134 for (ConsoleCheckCLDR.ErrorType type : ConsoleCheckCLDR.ErrorType.showInSummary) { 1135 indexTablePrinter.addCell(formatSkippingZero(counts.getCount(type))); 1136 } 1137 indexTablePrinter.finishRow(); 1138 } 1139 generated_html_index.println(indexTablePrinter.toTable()); 1140 generated_html_index.println(ShowData.dateFooter()); 1141 generated_html_index.println(CldrUtility.ANALYTICS); 1142 generated_html_index.println("</body></html>"); 1143 } 1144 1145 static Relation<Organization, String> orgToLocales; 1146 getOrgToLocales()1147 private static Relation<Organization, String> getOrgToLocales() { 1148 if (orgToLocales == null) { 1149 orgToLocales = Relation.of(new TreeMap<Organization, Set<String>>(), TreeSet.class); 1150 StandardCodes sc = StandardCodes.make(); 1151 for (Organization org : sc.getLocaleCoverageOrganizations()) { 1152 for (String locale : sc.getLocaleCoverageLocales(org)) { 1153 Level x = sc.getLocaleCoverageLevel(org, locale); 1154 if (x.compareTo(Level.BASIC) > 0) { 1155 orgToLocales.put(org, locale); 1156 } 1157 } 1158 } 1159 } 1160 return orgToLocales; 1161 } 1162 showSections()1163 static void showSections() throws IOException { 1164 Relation<Organization, String> orgToLocales = getOrgToLocales(); 1165 TablePrinter indexTablePrinter = new TablePrinter().setCaption("Problem Summary") 1166 .setTableAttributes("border='1' style='border-collapse: collapse' bordercolor='blue'") 1167 .addColumn("Section").setSpanRows(true).setBreakSpans(true)//.setRepeatDivider(true) 1168 .addColumn("Problems").setCellAttributes("style=\"text-align:left\" class=\"{2}\"").setSpanRows(true) 1169 .addColumn("Subtype").setCellAttributes("style=\"text-align:left\" class=\"{2}\"").setSpanRows(true) 1170 .addColumn("Locale").setCellAttributes("class=\"{2}\"") 1171 .addColumn("Code").setCellAttributes("class=\"{2}\"") 1172 .setCellPattern("<a href=\"http://unicode.org/cldr/apps/survey?_={0}&x={1}\">{0}</a>") // TODO: use CLDRConfig.urls() 1173 .addColumn("Count").setCellAttributes("class=\"{2}\""); 1174 for (Organization org : orgToLocales.keySet()) { 1175 indexTablePrinter.addColumn(org.toString().substring(0, 2)); 1176 } 1177 1178 for (Row.R4<String, ErrorType, Subtype, String> sectionAndProblemsAndLocale : ErrorFile.sectionToProblemsToLocaleToCount 1179 .getKeysetSortedByKey()) { 1180 final ErrorType problem = sectionAndProblemsAndLocale.get1(); 1181 final Subtype subtype = sectionAndProblemsAndLocale.get2(); 1182 if (!ConsoleCheckCLDR.ErrorType.showInSummary.contains(problem)) { 1183 continue; 1184 } 1185 final String locale = sectionAndProblemsAndLocale.get3(); 1186 if (problem != ErrorType.error && problem != ErrorType.disputed && !orgToLocales.containsValue(locale)) { 1187 continue; 1188 } 1189 long count = ErrorFile.sectionToProblemsToLocaleToCount.getCount(sectionAndProblemsAndLocale); 1190 final String section = sectionAndProblemsAndLocale.get0(); 1191 indexTablePrinter.addRow() 1192 .addCell(section) 1193 .addCell(problem) 1194 .addCell(subtype) 1195 .addCell(ConsoleCheckCLDR.getLocaleName(locale)) 1196 .addCell(locale) 1197 .addCell(count); 1198 for (Organization org : orgToLocales.keySet()) { 1199 indexTablePrinter.addCell(orgToLocales.getAll(org).contains(locale) ? org.toString().substring(0, 2) : ""); 1200 } 1201 indexTablePrinter.finishRow(); 1202 } 1203 PrintWriter generated_html_index = FileUtilities.openUTF8Writer(ErrorFile.generated_html_directory, "sections.html"); 1204 ConsoleCheckCLDR.ErrorFile.showIndexHead("Error Report Index by Section", "", generated_html_index); 1205 generated_html_index.println(indexTablePrinter.toTable()); 1206 generated_html_index.println(ShowData.dateFooter()); 1207 generated_html_index.println(CldrUtility.ANALYTICS); 1208 generated_html_index.println("</body></html>"); 1209 generated_html_index.close(); 1210 } 1211 formatSkippingZero(long count)1212 static String formatSkippingZero(long count) { 1213 if (count == 0) { 1214 return ""; 1215 } 1216 return String.valueOf(count); 1217 } 1218 showIndexHead(String title, String localeID, PrintWriter generated_html_index)1219 static void showIndexHead(String title, String localeID, PrintWriter generated_html_index) { 1220 final boolean notLocaleSpecific = localeID.length() == 0; 1221 if ((!notLocaleSpecific)) { 1222 title = "Errors in " + ConsoleCheckCLDR.getNameAndLocale(localeID, false); 1223 } 1224 generated_html_index 1225 .println("<html>" + 1226 "<head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" 1227 + CldrUtility.LINE_SEPARATOR 1228 + 1229 "<title>" 1230 + title 1231 + "</title>" 1232 + CldrUtility.LINE_SEPARATOR 1233 + 1234 "<link rel='stylesheet' href='errors.css' type='text/css'>" 1235 + CldrUtility.LINE_SEPARATOR 1236 + 1237 "<base target='_blank'>" 1238 + CldrUtility.LINE_SEPARATOR 1239 + 1240 "</head><body>" 1241 + CldrUtility.LINE_SEPARATOR 1242 + 1243 "<h1>" 1244 + title 1245 + "</h1>" 1246 + CldrUtility.LINE_SEPARATOR 1247 + 1248 "<p>" 1249 + 1250 "<a href='index.html" 1251 + (notLocaleSpecific ? "" : "#" + localeID) 1252 + "'>Index</a>" 1253 + 1254 " | " 1255 + 1256 "<a href='sections.html" 1257 + (notLocaleSpecific ? "" : "#" + localeID) 1258 + "'>Index by Section</a>" 1259 + 1260 " | " 1261 + 1262 "<a href='http://unicode.org/cldr/data/docs/survey/vetting.html'><b style='background-color: yellow;'><i>Help: How to Vet</i></b></a>" 1263 + 1264 "</p>" 1265 + 1266 "<p>The following errors have been detected in the locale" 1267 + 1268 (notLocaleSpecific 1269 ? "s. " + org.unicode.cldr.test.HelpMessages.getChartMessages("error_index_header") 1270 : " " + ConsoleCheckCLDR.getNameAndLocale(localeID, false) + ". " 1271 + ErrorFile.ERROR_CHART_HEADER)); 1272 } 1273 writeErrorFileIndex()1274 private static void writeErrorFileIndex() throws IOException { 1275 PrintWriter generated_html_index = FileUtilities.openUTF8Writer(ErrorFile.generated_html_directory, "index.html"); 1276 ConsoleCheckCLDR.ErrorFile.showIndexHead("Error Report Index", "", generated_html_index); 1277 ConsoleCheckCLDR.ErrorFile.showErrorFileIndex(generated_html_index); 1278 generated_html_index.close(); 1279 showSections(); 1280 } 1281 writeErrorCountsText()1282 private static void writeErrorCountsText() { 1283 // do the plain text file 1284 ErrorFile.generated_html_count.print(ConsoleCheckCLDR.lastHtmlLocaleID + ";\tcounts"); 1285 for (ConsoleCheckCLDR.ErrorType type : ConsoleCheckCLDR.ErrorType.showInSummary) { 1286 ErrorFile.generated_html_count.print(";\t" + type + "=" + ErrorFile.htmlErrorsPerLocale.getCount(type)); 1287 } 1288 ErrorFile.generated_html_count.println(); 1289 ErrorFile.generated_html_count.flush(); 1290 1291 // now store the data for the index 1292 ErrorFile.errorFileIndexData.put(ConsoleCheckCLDR.lastHtmlLocaleID, 1293 new Pair<>(ConsoleCheckCLDR.lastHtmlLocaleID, ErrorFile.htmlErrorsPerLocale)); 1294 ErrorFile.htmlErrorsPerLocale = new Counter<>(); 1295 } 1296 1297 static Counter<ErrorType> htmlErrorsPerLocale = new Counter<>(); // ConsoleCheckCLDR.ErrorCount(); 1298 static PrintWriter generated_html_count = null; 1299 private static TreeMap<String, Pair<String, Counter<ErrorType>>> errorFileIndexData = new TreeMap<>(); 1300 1301 static PrintWriter errorFileWriter = null; 1302 private static final String ERROR_CHART_HEADER = org.unicode.cldr.test.HelpMessages 1303 .getChartMessages("error_locale_header"); 1304 static String generated_html_directory = null; 1305 public static Counter<Row.R4<String, ErrorType, Subtype, String>> sectionToProblemsToLocaleToCount = new Counter<>(); 1306 } 1307 showSummary(String localeID, Level level, String value)1308 private static void showSummary(String localeID, Level level, String value) { 1309 String line = "# " + getLocaleAndName(localeID) + "\tSummary\t" + level + "\t" + value; 1310 System.out.println(line); 1311 } 1312 showExamples(CheckCLDR checkCldr, String prettyPath, String localeID, String path, String value, String fullPath, String example)1313 private static void showExamples(CheckCLDR checkCldr, String prettyPath, String localeID, 1314 String path, String value, String fullPath, String example) { 1315 if (example != null) { 1316 showValue(checkCldr.getCldrFileToCheck(), prettyPath, localeID, example, path, value, fullPath, "ok", 1317 Subtype.none); 1318 } 1319 } 1320 addPrettyPaths(CLDRFile file, Matcher pathFilter, PathHeader.Factory pathHeaderFactory, boolean noaliases, boolean filterDraft, Collection<String> target)1321 private static void addPrettyPaths(CLDRFile file, Matcher pathFilter, PathHeader.Factory pathHeaderFactory, 1322 boolean noaliases, boolean filterDraft, Collection<String> target) { 1323 for (Iterator<String> pit = file.iterator(pathFilter); pit.hasNext();) { 1324 String path = pit.next(); 1325 addPrettyPath(file, pathHeaderFactory, noaliases, filterDraft, target, path); 1326 } 1327 } 1328 addPrettyPaths(CLDRFile file, Collection<String> paths, Matcher pathFilter, PathHeader.Factory pathHeaderFactory, boolean noaliases, boolean filterDraft, Collection<String> target)1329 private static void addPrettyPaths(CLDRFile file, Collection<String> paths, Matcher pathFilter, 1330 PathHeader.Factory pathHeaderFactory, boolean noaliases, boolean filterDraft, Collection<String> target) { 1331 for (String path : paths) { 1332 if (pathFilter != null && !pathFilter.reset(path).matches()) continue; 1333 addPrettyPath(file, pathHeaderFactory, noaliases, filterDraft, target, path); 1334 } 1335 } 1336 addPrettyPath(CLDRFile file, PathHeader.Factory pathHeaderFactory, boolean noaliases, boolean filterDraft, Collection<String> target, String path)1337 private static void addPrettyPath(CLDRFile file, PathHeader.Factory pathHeaderFactory, boolean noaliases, 1338 boolean filterDraft, Collection<String> target, String path) { 1339 if (noaliases && XMLSource.Alias.isAliasPath(path)) { // this is just for console testing, the survey tool 1340 // shouldn't do it. 1341 return; 1342 } 1343 if (filterDraft) { 1344 String newPath = CLDRFile.getNondraftNonaltXPath(path); 1345 if (!newPath.equals(path)) { 1346 String value = file.getStringValue(newPath); 1347 if (value != null) { 1348 return; 1349 } 1350 } 1351 } 1352 String prettyPath = pathHeaderFactory.fromPath(path).toString(); 1353 target.add(prettyPath); 1354 } 1355 setExampleGenerator(ExampleGenerator inputExampleGenerator)1356 private static synchronized void setExampleGenerator(ExampleGenerator inputExampleGenerator) { 1357 englishExampleGenerator = inputExampleGenerator; 1358 } 1359 getExampleGenerator()1360 private static synchronized ExampleGenerator getExampleGenerator() { 1361 return englishExampleGenerator; 1362 } 1363 1364 private static ExampleGenerator englishExampleGenerator; 1365 1366 static Matcher coverageMatcher = PatternCache.get("meet ([a-z]*) coverage").matcher(""); // HACK TODO fix 1367 showHeaderLine()1368 private static void showHeaderLine() { 1369 if (SHOW_LOCALE) { 1370 if (idView) { 1371 System.out 1372 .println("Locale\tID\tDesc.\t〈Eng.Value〉\t【Eng.Ex.】\t〈Loc.Value〉\t【Loc.Ex】\t⁅error/warning type⁆\t❮Error/Warning Msg❯"); 1373 } else { 1374 System.out 1375 .println( 1376 "Locale\tStatus\t▸PPath◂\t〈Eng.Value〉\t【Eng.Ex.】\t〈Loc.Value〉\t«fill-in»\t【Loc.Ex】\t⁅error/warning type⁆\t❮Error/Warning Msg❯\tFull Path\tAliasedSource/Path?"); 1377 } 1378 } 1379 } 1380 1381 private static PathDescription pathDescription = null; 1382 getIdString(String path, String value)1383 private static String getIdString(String path, String value) { 1384 if (pathDescription == null) { 1385 pathDescription = new PathDescription(supplementalDataInfo, english, null, null, 1386 PathDescription.ErrorHandling.CONTINUE); 1387 } 1388 final String description = pathDescription.getDescription(path, value, null, null); 1389 return "\t" + StringId.getId(path) + "" + "\t" + description + ""; 1390 } 1391 showValue(CLDRFile cldrFile, String prettyPath, String localeID, String example, String path, String value, String fullPath, String statusString, Subtype subtype)1392 private static void showValue(CLDRFile cldrFile, String prettyPath, String localeID, String example, 1393 String path, String value, String fullPath, String statusString, Subtype subtype) { 1394 ErrorType shortStatus = ErrorType.fromStatusString(statusString); 1395 subtotalCount.add(shortStatus, 1); 1396 totalCount.add(shortStatus, 1); 1397 if (subtype == null) { 1398 subtype = Subtype.none; 1399 } 1400 final SourceLocation location = fullPath == null ? null : cldrFile.getSourceLocation(fullPath); 1401 1402 if (ErrorFile.errorFileWriter == null) { 1403 example = example == null ? "" : example; 1404 String englishExample = null; 1405 final String englishPathValue = path == null ? null : getEnglishPathValue(path); 1406 if (SHOW_EXAMPLES && path != null) { 1407 englishExample = ExampleGenerator.simplify(getExampleGenerator().getExampleHtml(path, englishPathValue)); 1408 } 1409 englishExample = englishExample == null ? "" : englishExample; 1410 String cleanPrettyPath = path == null ? null : prettyPath; 1411 Status status = new Status(); 1412 String sourceLocaleID = path == null ? null : cldrFile.getSourceLocaleID(path, status); 1413 String fillinValue = path == null ? null : cldrFile.getFillInValue(path); 1414 fillinValue = fillinValue == null ? "" : fillinValue.equals(value) ? "=" : fillinValue; 1415 1416 String pathLink = CLDR_CONFIG.urls().forXpath(localeID, path); 1417 1418 final String otherSource = path == null ? null 1419 : (sourceLocaleID.equals(localeID) ? "" 1420 : "\t" + sourceLocaleID); 1421 final String otherPath = path == null ? null 1422 : (status.pathWhereFound.equals(path) ? "" 1423 : "\t" + status.pathWhereFound); 1424 if (location != null) { 1425 System.err.println(location.toString() + shortStatus); // print full path here 1426 } 1427 String idViewString = idView ? (path == null ? "\tNO_ID" : getIdString(path, value)) : ""; 1428 System.out.println( 1429 getLocaleAndName(localeID) 1430 + (idViewString.isEmpty() ? 1431 // + "\t" + subtotalCount.getCount(shortStatus) 1432 "\t" + shortStatus 1433 + "\t▸" + cleanPrettyPath + "◂" 1434 + "\t〈" + englishPathValue + "〉" 1435 + "\t【" + englishExample + "】" 1436 + "\t〈" + value + "〉" 1437 + "\t«" + fillinValue + "»" 1438 + "\t【" + example + "】" 1439 + "\t⁅" + subtype + "⁆" 1440 + "\t❮" + statusString + "❯" 1441 + "\t" + pathLink 1442 + otherSource 1443 + otherPath 1444 : idViewString 1445 + "\t〈" + englishPathValue + "〉" 1446 + "\t【" + englishExample + "】" 1447 + "\t" + value + "〉" 1448 + "\t【" + example + "】" 1449 + "\t⁅" + subtype + "⁆" 1450 + "\t❮" + statusString + "❯")); 1451 } else if (ErrorFile.errorFileWriter != null) { 1452 if (shortStatus == ErrorType.contributed) { 1453 return; 1454 } 1455 if (shortStatus == ErrorType.posix) { 1456 shortStatus = ErrorType.minimal; 1457 } 1458 if (!localeID.equals(lastHtmlLocaleID)) { 1459 ErrorFile.writeErrorCountsText(); 1460 lastHtmlLocaleID = localeID; 1461 } 1462 addError(shortStatus); 1463 ErrorFile.addDataToErrorFile(localeID, path, shortStatus, subtype); 1464 } 1465 if (CLDR_GITHUB_ANNOTATIONS) { 1466 // Annotate anything that needs annotation 1467 if (shortStatus == ErrorType.error || shortStatus == ErrorType.warning) { 1468 String filePath = null; 1469 if (location != null) { 1470 // Use accurate location 1471 filePath = location.forGitHub(CLDRPaths.BASE_DIRECTORY); // Trim to CLDR_DIR for GitHub 1472 } else { 1473 // Fallback if SourceLocation fails 1474 filePath = "file="+localeXpathToFilePath.computeIfAbsent(Pair.of(localeID, path), locPath -> guessFilePath(locPath)); 1475 } 1476 System.out.println("::" + shortStatus + " " + filePath.trim() + ",title=" + subtype + ":: " + statusString); 1477 } 1478 } 1479 if (PATH_IN_COUNT && ErrorFile.generated_html_count != null) { 1480 ErrorFile.generated_html_count.println(lastHtmlLocaleID + ";\tpath:\t" + path); 1481 } 1482 } 1483 addError(ErrorType shortStatus)1484 private static void addError(ErrorType shortStatus) { 1485 if (ErrorType.showInSummary.contains(shortStatus)) { 1486 ErrorFile.htmlErrorsPerLocale.increment(shortStatus); 1487 } 1488 } 1489 1490 static String lastHtmlLocaleID = ""; 1491 private static VoterInfoList voterInfoList; 1492 private static VoteResolver<String> voteResolver; 1493 private static String resolveVotesDirectory; 1494 private static boolean idView; 1495 private static SupplementalDataInfo supplementalDataInfo; 1496 private static CLDRFile english; 1497 1498 public static class PathShower { 1499 String localeID; 1500 boolean newLocale = true; 1501 String lastPath; 1502 String[] lastSplitPath; 1503 boolean showEnglish; 1504 String splitChar = "/"; 1505 1506 static final String lead = "****************************************"; 1507 set(String localeID)1508 public void set(String localeID) { 1509 this.localeID = localeID; 1510 newLocale = true; 1511 LocaleIDParser localeIDParser = new LocaleIDParser(); 1512 showEnglish = !localeIDParser.set(localeID).getLanguageScript().equals("en"); 1513 lastPath = null; 1514 lastSplitPath = null; 1515 } 1516 getSplitChar()1517 public String getSplitChar() { 1518 return splitChar; 1519 } 1520 setSplitChar(String splitChar)1521 public PathShower setSplitChar(String splitChar) { 1522 this.splitChar = splitChar; 1523 return this; 1524 } 1525 } 1526 getEnglishPathValue(String path)1527 private static String getEnglishPathValue(String path) { 1528 String englishValue = CheckCLDR.getDisplayInformation().getWinningValue(path); 1529 if (englishValue == null) { 1530 String path2 = CLDRFile.getNondraftNonaltXPath(path); 1531 englishValue = CheckCLDR.getDisplayInformation().getWinningValue(path2); 1532 } 1533 return englishValue; 1534 } 1535 1536 /** 1537 * Utility for getting information. 1538 * 1539 * @param locale 1540 * @return 1541 */ getLocaleAndName(String locale)1542 private static String getLocaleAndName(String locale) { 1543 String localizedName = CheckCLDR.getDisplayInformation().getName(locale); 1544 if (localizedName == null || localizedName.equals(locale)) return locale; 1545 return locale + " [" + localizedName + "]"; 1546 } 1547 1548 /** 1549 * Utility for getting information. 1550 * 1551 * @param locale 1552 * @param linkToXml 1553 * TODO 1554 * @return 1555 */ getNameAndLocale(String locale, boolean linkToXml)1556 private static String getNameAndLocale(String locale, boolean linkToXml) { 1557 String localizedName = CheckCLDR.getDisplayInformation().getName(locale); 1558 if (localizedName == null || localizedName.equals(locale)) return locale; 1559 if (linkToXml) { 1560 locale = "<a href='https://github.com/unicode-org/cldr/tree/main/common/main/" + locale + ".xml'>" + locale + "</a>"; 1561 } 1562 return localizedName + " [" + locale + "]"; 1563 } 1564 getLocaleName(String locale)1565 private static String getLocaleName(String locale) { 1566 String localizedName = CheckCLDR.getDisplayInformation().getName(locale); 1567 if (localizedName == null || localizedName.equals(locale)) return locale; 1568 return localizedName; 1569 } 1570 getLinkedLocale(String locale)1571 private static String getLinkedLocale(String locale) { 1572 return "<a href='http://unicode.org/cldr/apps/survey?_=" + locale + "'>" + locale + "</a>"; 1573 } 1574 1575 1576 /** 1577 * Approximate xml path 1578 */ guessFilePath(Pair<String, String> locPath)1579 private static String guessFilePath(Pair<String, String> locPath) { 1580 final File base = new File(CLDRPaths.BASE_DIRECTORY); 1581 final String loc = locPath.getFirst(); 1582 final String path = locPath.getSecond(); 1583 String subdir = "main"; 1584 if (path.startsWith("//ldml/annotations")) { 1585 subdir = "annotations"; 1586 } else if(path.startsWith("//ldml/subdivisions")) { 1587 subdir = "subdivisions"; 1588 } 1589 File inCommon = new File(base, "common"); 1590 File subsub = new File(inCommon, subdir); 1591 if (subsub.isDirectory()) { 1592 File subFile = new File(subsub, loc+".xml"); 1593 if (subFile.canRead()) return subFile.getAbsolutePath().substring(base.getAbsolutePath().length() + 1); 1594 } 1595 1596 File inSeed = new File(base, "seed"); 1597 subsub = new File(inSeed, subdir); 1598 if (subsub.isDirectory()) { 1599 File subFile = new File(subsub, loc+".xml"); 1600 if (subFile.canRead()) return subFile.getAbsolutePath().substring(base.getAbsolutePath().length() + 1); 1601 } 1602 return loc+".xml"; 1603 } 1604 final static ConcurrentHashMap<Pair<String, String>, String> localeXpathToFilePath = new ConcurrentHashMap<>(); 1605 } 1606