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