1 /* 2 ******************************************************************************* 3 * Copyright (C) 2003-2012, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7 /** 8 * @author Ram Viswanadha 9 */ 10 package org.unicode.cldr.icu; 11 12 import java.io.File; 13 import java.io.FileOutputStream; 14 import java.io.OutputStreamWriter; 15 import java.io.PrintWriter; 16 import java.util.Calendar; 17 import java.util.Enumeration; 18 import java.util.Hashtable; 19 import java.util.Iterator; 20 import java.util.Map; 21 import java.util.Set; 22 import java.util.TreeMap; 23 import java.util.TreeSet; 24 import java.util.Vector; 25 26 import org.unicode.cldr.util.LDMLUtilities; 27 import org.w3c.dom.Document; 28 import org.w3c.dom.NamedNodeMap; 29 import org.w3c.dom.Node; 30 import org.w3c.dom.NodeList; 31 32 import com.ibm.icu.lang.UCharacter; 33 import com.ibm.icu.text.Collator; 34 import com.ibm.icu.text.DecimalFormat; 35 import com.ibm.icu.text.Normalizer; 36 import com.ibm.icu.text.RuleBasedCollator; 37 import com.ibm.icu.util.ULocale; 38 39 public class LDMLComparator { 40 /* 41 * This application will compare different locale data xml files 42 * conforming to localeElements.dtd and produces an xml file file 43 * in the format 44 */ 45 private static final int OPT_DIFF = 0x4000; /* 2exp15 */// PN 46 private static final int OPT_DIFF_REF_COMMON = 0x8000; /* 2exp16 */// PN 47 private static final int OPT_BULK = 0x00010000; // PN 48 private static final int OPT_CASE_SENSITIVE = 0x00020000; // PN 49 private static final int OPT_VETTING = 0x00040000; 50 private static final int OPT_UNKNOWN = 0x00080000; 51 52 private static final String COMMON = "common"; 53 private static final String ICU = "icu"; 54 private static final String IBM_TOR = "ibm"; 55 private static final String WINDOWS = "windows"; 56 private static final String SUNJDK = "sunjdk"; 57 private static final String IBMJDK = "ibmjdk"; 58 private static final String HPUX = "hp"; 59 private static final String APPLE = "apple"; 60 private static final String SOLARIS = "solaris"; 61 private static final String OPEN_OFFICE = "open_office"; 62 private static final String AIX = "aix"; 63 private static final String LINUX = "linux"; 64 65 private static final String ALTERNATE_TITLE = "(Original)"; 66 private static final String ALT_COLOR = "#DDDDFD"; 67 // PN added 68 private static final String DIFF = "diff"; 69 private static final String DIFF_REF_COMMON = "diff_ref_common"; 70 private static final String BULK = "bulk"; 71 private static final String CASE_SENSITIVE = "case_sensitive"; 72 private static final String VETTING = "vetting"; 73 private static final String[] PLATFORM_PRINT_ORDER = { 74 COMMON, 75 ICU, 76 WINDOWS, 77 SUNJDK, 78 IBMJDK, 79 IBM_TOR, 80 APPLE, 81 SOLARIS, 82 OPEN_OFFICE, 83 AIX, 84 LINUX, 85 HPUX, 86 }; 87 88 private static final String USER_OPTIONS[] = { 89 "-" + COMMON, 90 "-" + ICU, 91 "-" + IBM_TOR, 92 "-" + WINDOWS, 93 "-" + SUNJDK, 94 "-" + IBMJDK, 95 "-" + HPUX, 96 "-" + APPLE, 97 "-" + SOLARIS, 98 "-" + OPEN_OFFICE, 99 "-" + AIX, 100 "-" + LINUX, 101 "-s", 102 "-d", 103 "-" + DIFF, // PN added, indicates that only differing elements/attributes to be written to html 104 "-" + DIFF_REF_COMMON, // PN added, same as diff only common is excluded from diff but gets printed to html for 105 // reference purposes 106 "-" + BULK, // do a bulk comparison of folder contents 107 "-" + CASE_SENSITIVE, // do case sensitive matching (by default it's not case sensitive) 108 "-" + VETTING // go into Vetting mode. (show draft, etc) 109 }; 110 main(String[] args)111 public static void main(String[] args) { 112 LDMLComparator comparator = new LDMLComparator(); 113 comparator.processArgs(args); 114 } 115 getDefaultCollation()116 static Collator getDefaultCollation() { 117 // if (DEFAULT_COLLATION != null) return DEFAULT_COLLATION; 118 RuleBasedCollator temp = (RuleBasedCollator) Collator.getInstance(ULocale.ENGLISH); 119 temp.setStrength(Collator.IDENTICAL); 120 temp.setNumericCollation(true); 121 // DEFAULT_COLLATION = temp; 122 return temp; 123 } 124 125 Hashtable<String, String> optionTable = new Hashtable<String, String>(); 126 private String destFolder = "."; 127 private String localeStr; 128 private String ourCvsVersion = ""; 129 private Calendar cal = Calendar.getInstance(); 130 private Hashtable<String, String> colorHash = new Hashtable<String, String>(); 131 private String goldFileName; 132 private String goldKey; 133 private int serialNumber = 0; 134 private Map<String, Object> compareMap = new TreeMap<String, Object>(getDefaultCollation()); 135 private Hashtable<String, String> doesNotExist = new Hashtable<String, String>(); 136 private Hashtable<String, String> requested = new Hashtable<String, String>(); 137 private Hashtable<String, String> deprecatedLanguageCodes = new Hashtable<String, String>(); 138 private Hashtable<String, String> deprecatedCountryCodes = new Hashtable<String, String>(); 139 private Set<String> vettingSet = new TreeSet<String>(); 140 private String encoding = "UTF-8"; // default encoding 141 142 // PN added 143 private Vector<String> m_PlatformVect = new Vector<String>(); // holds names of platforms 144 private Vector<String> m_PlatformFolderVect = new Vector<String>(); // holds names of folders containing locale data 145 // for each platform 146 private int m_iOptions; 147 private Map<String, AccumulatedResults> m_AccumulatedResultsMap = new TreeMap<String, AccumulatedResults>(); 148 private int m_iTotalConflictingElements = 0; 149 private int m_iTotalNonConflictingElements = 0; 150 private Map<String, SummaryData> m_LocaleSummaryDataMap = new TreeMap<String, SummaryData>(); // key = localename, 151 // data = summary info 152 private boolean m_Vetting = false; 153 154 private int m_totalCount = 0; 155 private int m_diffcount = 0; 156 private String m_Messages = ""; 157 158 private class CompareElement { 159 String node; 160 String index; 161 String parentNode; 162 Hashtable<String, String> platformData = new Hashtable<String, String>(); 163 String referenceUrl; 164 } 165 166 // PN added 167 // used for bulk comparisons 168 // holds the locales where the element identified by node,index and parentNode conflict 169 // for at least 2 of the platforms tested 170 // holds the locales where the element identified by node,index and parentNode don't 171 // for at all the platforms tested 172 private class AccumulatedResults { 173 String node; 174 String index; 175 String parentNode; 176 Vector<String> localeVectDiff = new Vector<String>(); // holds locales where a conflict in data was found 177 Vector<String> localeVectSame = new Vector<String>(); // holds locales where a no conflict in data was found 178 } 179 180 private class SummaryData { 181 String m_szPlatforms; 182 int m_iNumConflictingElements; 183 } 184 LDMLComparator()185 LDMLComparator() { 186 // initialize the color hash 187 colorHash.put(COMMON, "#AD989D"); 188 colorHash.put(ICU, "#CCFF00"); 189 colorHash.put(IBM_TOR, "#FF7777"); 190 colorHash.put(WINDOWS, "#98FB98"); 191 colorHash.put(SUNJDK, "#FF6633"); 192 colorHash.put(IBMJDK, "#CCFFFF"); 193 colorHash.put(HPUX, "#FFE4B5"); 194 colorHash.put(APPLE, "#FFBBBB"); 195 colorHash.put(SOLARIS, "#CC9966"); 196 colorHash.put(OPEN_OFFICE, "#FFFF33"); 197 colorHash.put(AIX, "#EB97FE"); 198 colorHash.put(LINUX, "#1191F1"); 199 // TODO - use deprecatedMap instead. 200 // deprecatedLanguageCodes.put("sh", "what ever the new one is"); 201 deprecatedLanguageCodes.put("iw", "he"); 202 deprecatedLanguageCodes.put("in", "id"); 203 deprecatedLanguageCodes.put("ji", "yi"); 204 deprecatedLanguageCodes.put("jw", "jv"); // this does not even exist, JDK thinks jw is javanese!! 205 206 // country codes 207 deprecatedCountryCodes.put("TP", "TL"); 208 deprecatedCountryCodes.put("ZR", "CD"); 209 } 210 processArgs(String[] args)211 private void processArgs(String[] args) { 212 m_iOptions = identifyOptions(args); 213 if ((args.length < 2) || ((m_iOptions & OPT_UNKNOWN) != 0)) { 214 printUsage(); 215 return; 216 } 217 boolean warning[] = new boolean[1]; 218 warning[0] = false; 219 Enumeration<String> en = optionTable.keys(); 220 221 try { 222 // check for bulk operation 223 if ((m_iOptions & OPT_BULK) != 0) { 224 doBulkComparison(); 225 } else { 226 localeStr = goldFileName.substring(goldFileName.lastIndexOf(File.separatorChar) + 1, 227 goldFileName.lastIndexOf('.')); 228 229 String fileName = destFolder + File.separator + localeStr + ".html"; 230 m_totalCount = 0; 231 m_diffcount = 0; 232 if ((m_iOptions & OPT_VETTING) != 0) { 233 m_Vetting = true; 234 addVettable(goldFileName, goldKey); 235 } else { 236 addToCompareMap(goldFileName, goldKey); 237 } 238 for (; en.hasMoreElements();) { 239 String key = (String) en.nextElement(); 240 String compFile = (String) optionTable.get(key); 241 if ((m_iOptions & OPT_VETTING) != 0) { 242 addVettable(goldFileName, goldKey); 243 } else { 244 addToCompareMap(compFile, key); 245 } 246 } 247 if ((m_totalCount == 0) && m_Vetting) { // only optional for vetting. 248 // System.out.println("INFO: no file created (nothing to write..) " + fileName); 249 } else { 250 ourCvsVersion = ""; 251 getCVSVersion(); 252 OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(fileName), encoding); 253 System.out.println("INFO: Writing: " + fileName + "\t(" + m_totalCount + " items)"); 254 PrintWriter writer = new PrintWriter(os); 255 printHTML(writer, localeStr); 256 { 257 ULocale ourLocale = new ULocale(localeStr); 258 String idxFileName = destFolder + File.separator + ourLocale.getDisplayLanguage() + "_" 259 + ourLocale.getDisplayCountry() + "_" + localeStr + ".idx"; 260 OutputStreamWriter is = new OutputStreamWriter(new FileOutputStream(idxFileName), "utf-8"); 261 PrintWriter indexwriter = new PrintWriter(is); 262 indexwriter.println("<tr>"); 263 indexwriter.println(" <td>" + 264 localeStr + 265 "</td>"); 266 indexwriter.println(" <td><a href=\"" + localeStr + ".html" + "\">" + 267 ourLocale.getDisplayName() + "</a></td>"); 268 indexwriter.println(" <td>" + m_totalCount + "</td>"); 269 if (!m_Vetting) { 270 indexwriter.println(" <td>" + m_diffcount + "</td>"); 271 } 272 indexwriter.println(" <td>" + LDMLUtilities.getCVSLink(localeStr, ourCvsVersion) 273 + ourCvsVersion + "</a></td>"); 274 indexwriter.println("</tr>"); 275 is.close(); 276 } 277 // TODO: handle vettingSet; 278 } 279 } 280 } catch (Exception e) { 281 e.printStackTrace(); 282 } 283 284 } 285 printUsage()286 private void printUsage() { 287 System.err.println("Usage: LDMLComparator [<option>:<gold>] filename1 [option] filename2 ... \n" + 288 " LDMLComparator [-common:<gold>] filename [-icu] filename" + 289 " [-ibmjdk] filename [-windows] filename" + 290 " [-hpux] filename [-solaris] filename" + 291 " [-ibmtor] filename [-apple] filename" + 292 " [-sunjdk] filename [-open_office] filename" + 293 " [-aix] filename [-linux] filename" + 294 " [-diff / -diff_ref_common] [-bulk]" + 295 " [-case_sensitive (only active if -diff of -diff-ref-common option selected)]"); 296 System.err.println("\nExample 1: \n " + 297 "LDMLComparator -solaris:gold foldername1 -sunjdk foldername2 -common foldername3 -diff-ref-common -bulk\n" 298 + 299 "\t\t will do a bulk comparison of the locales in folder1 and folder2 \n " + 300 "\t\t and print the values of any differing elements plus the \n" + 301 "\t\t corresponding element's value in folder3 to bulk.html \n" + 302 "\t\t as well as a summary to bulk_summary.html \n"); 303 System.err.println("Example 2: \n" + 304 "LDMLComparator -common:gold filename1 -sunjdk filename2 -diff \n" + 305 "\t\t will do a comparison of the locales specified by filename1 and \n" + 306 "\t\t filename2 and print the values of any differing elements \n" + 307 "\t\t to a file called filename1.html in the current directory \n"); 308 } 309 identifyOptions(String[] options)310 private int identifyOptions(String[] options) { 311 int result = 0; 312 for (int j = 0; j < options.length; j++) { 313 String option = options[j]; 314 boolean isGold = false; 315 if (option.startsWith("-")) { 316 if (option.indexOf(":gold") > 0) { 317 option = option.substring(0, option.indexOf(":")); 318 isGold = true; 319 } 320 boolean optionRecognized = false; 321 for (int i = 0; i < USER_OPTIONS.length; i++) { 322 323 if (USER_OPTIONS[i].equals(option)) { 324 result |= (int) (1 << i); // calculate option bit value 325 optionRecognized = true; 326 if (USER_OPTIONS[i].equals("-s")) { 327 } else if (USER_OPTIONS[i].equals("-d")) { 328 destFolder = options[++j]; 329 } else if (USER_OPTIONS[i].equals("-" + DIFF)) { 330 331 } else if (USER_OPTIONS[i].equals("-" + DIFF_REF_COMMON)) { 332 333 } else if (USER_OPTIONS[i].equals("-" + BULK)) { 334 335 } else if (USER_OPTIONS[i].equals("-" + VETTING)) { 336 m_Vetting = true; 337 } else if (USER_OPTIONS[i].equals("-" + CASE_SENSITIVE)) { 338 } else { 339 if (!isGold) { 340 optionTable.put(option.substring(1, option.length()), options[++j]); 341 342 } else { 343 goldFileName = options[++j]; 344 goldKey = option.substring(1, option.length()); 345 } 346 // PN added 347 m_PlatformVect.add(option.substring(1, option.length())); 348 m_PlatformFolderVect.add(options[j]); 349 } 350 break; 351 } 352 } 353 if (!optionRecognized) { 354 result |= OPT_UNKNOWN; 355 } 356 } else { 357 if (m_Vetting == true) { 358 vettingSet.add(option); 359 } 360 } 361 } 362 363 return result; 364 } 365 printTableHeader(PrintWriter writer)366 private void printTableHeader(PrintWriter writer) { 367 368 writer.print(" <tr>\n" + 369 " <th>N.</th>\n" + 370 " <th>ParentNode</th>\n" + 371 " <th>Name</th>\n" + 372 " <th>ID</th>\n"); 373 374 for (int i = 0; i < PLATFORM_PRINT_ORDER.length && PLATFORM_PRINT_ORDER[i] != null; i++) { 375 String name = PLATFORM_PRINT_ORDER[i]; 376 String folder; 377 378 Object obj = requested.get(name); 379 if (obj != null && doesNotExist.get(name) == null) { 380 folder = name + "/main/"; 381 if (name.equals("icu") || name.equals("common") || name.indexOf("jdk") >= 0) { 382 int index = localeStr.indexOf("_"); 383 String parent = ""; 384 if (index > -1) { 385 parent = localeStr.substring(0, index); 386 } 387 writer.print(" <th bgcolor=\"" + 388 (String) colorHash.get(name) + "\">" + 389 name.toUpperCase() + 390 " (<a href=\"../../" + folder + localeStr + ".xml\">" + localeStr + "</a>," + 391 " <a href=\"../../" + folder + parent + ".xml\">" + parent + "</a>," + 392 " <a href=\"../../" + folder + "root.xml\">root</a>)" + 393 "</th>\n"); 394 } else { 395 writer.print(" <th bgcolor=\"" + 396 (String) colorHash.get(name) + "\">" + 397 name.toUpperCase() + 398 " (<a href=\"../../" + folder + localeStr + ".xml\">" + localeStr + "</a>)" + 399 "</th>\n"); 400 } 401 } 402 } 403 if (m_Vetting) { 404 writer.print("<th bgcolor=\"" + ALT_COLOR + "\">" + ALTERNATE_TITLE + "</th>"); 405 } 406 writer.print(" </tr>\n"); 407 } 408 409 // PN added printTableHeaderForDifferences(PrintWriter writer)410 private void printTableHeaderForDifferences(PrintWriter writer) { 411 412 writer.print(" <tr>\n" + 413 " <th width=10%>N.</th>\n" + 414 " <th width=10%>ParentNode</th>\n" + 415 " <th width=10%>Name</th>\n" + 416 " <th width=10%>ID</th>\n"); 417 418 for (int i = 0; i < m_PlatformVect.size(); i++) { 419 String name = (String) m_PlatformVect.elementAt(i); 420 String folder; 421 422 // Object obj = requested.get(name); 423 // if(obj!=null && doesNotExist.get(name)==null ) 424 // { 425 folder = name + "/xml/"; 426 writer.print(" <th bgcolor=\"" + 427 (String) colorHash.get(name) + "\">" + 428 name.toUpperCase() + 429 " (<a href=\"../" + folder + localeStr + ".xml\">xml</a>)" + 430 "</th>\n"); 431 // not used numPlatforms++; 432 433 // } 434 } 435 if (m_Vetting) { 436 writer.print("<th>" + ALTERNATE_TITLE + "</th>"); 437 } 438 writer.print(" </tr>\n"); 439 } 440 441 // PN added 442 // method to print differing elements/attributes only to HTML 443 // returns false if a difference found otherwise true printDifferentValues(CompareElement element, PrintWriter writer)444 private boolean printDifferentValues(CompareElement element, PrintWriter writer) { 445 boolean isEqual = true; 446 // following don't count 447 if ((element.node.compareTo((String) "generation") == 0) 448 || (element.node.compareTo((String) "version") == 0)) { 449 return isEqual; 450 } 451 452 String compareTo = null; 453 boolean bFoundFirst = false; 454 for (int i = 0; i < m_PlatformVect.size(); i++) { 455 String value = element.platformData.get(m_PlatformVect.elementAt(i)); 456 if (value == null) 457 continue; 458 // loop until non null value is found, this is the reference for comparison 459 if (bFoundFirst == false) { 460 compareTo = value; 461 bFoundFirst = true; 462 } else { // we have something to compare this element to 463 if (Normalizer.compare(compareTo, value, 0) == 0) { 464 isEqual = true; 465 } else if (Normalizer.compare(compareTo, value, Normalizer.COMPARE_IGNORE_CASE) == 0) { 466 if ((m_iOptions & OPT_CASE_SENSITIVE) == 0) { // it's not a case sensitive search so this is a match 467 isEqual = true; 468 } else { 469 isEqual = false; 470 break; // we have found a difference therefore break out of loop , we will print full row 471 } 472 } else { 473 isEqual = false; 474 break; // we have found a difference therefore break out of loop , we will print full row 475 } 476 } // end if 477 } // end while 478 479 // if any differences found then print all non null values 480 if (isEqual == false) { 481 writer.print(" <tr>\n"); 482 writer.print(" <td><a NAME=\"" + serialNumber + "\" href=\"#" + serialNumber + "\">" 483 + serialNumber + "</a></td>\n"); 484 writer.print(" <td>" + mapToAbbr(element.parentNode) + "</td>\n"); 485 writer.print(" <td>" + mapToAbbr(element.node) + "</td>\n"); 486 writer.print(" <td>" + element.index + "</td>\n"); 487 488 for (int i = 0; i < m_PlatformVect.size(); i++) { 489 String val = (String) element.platformData.get(m_PlatformVect.elementAt(i)); 490 if (val != null) { 491 writer.print(" <td>" + val + "</td>\n"); 492 } else { 493 writer.print(" <td> </td>\n"); 494 } 495 } // end while 496 497 writer.print(" </tr>\n"); 498 serialNumber++; 499 } // endif 500 return isEqual; 501 } 502 503 // PN added 504 // method to print differing elements/attributes only to HTML excluding Common from diff 505 // only if the other platfroms differ amongst themselves will the Common data be printed 506 // returns false if a difference found otherwise true printDifferentValuesWithRef(CompareElement element, PrintWriter writer)507 private boolean printDifferentValuesWithRef(CompareElement element, PrintWriter writer) { 508 boolean isEqual = true; 509 // following don't count 510 if ((element.node.compareTo((String) "generation") == 0) 511 || (element.node.compareTo((String) "version") == 0)) { 512 return isEqual; 513 } 514 515 String compareTo = null; 516 boolean bFoundFirst = false; 517 for (int i = 0; i < m_PlatformVect.size(); i++) { 518 // excluding Common from diff 519 String platform = (String) m_PlatformVect.elementAt(i); 520 if (platform.compareTo(COMMON) == 0) 521 continue; 522 523 String value = (String) element.platformData.get(platform); 524 if (value == null) 525 continue; 526 527 // loop until non null value is found, this is the reference for comparison 528 if (bFoundFirst == false) { 529 compareTo = value; 530 bFoundFirst = true; 531 } else { // we have something to compare this element to 532 if (Normalizer.compare(compareTo, value, 0) == 0) { 533 isEqual = true; 534 } else if (Normalizer.compare(compareTo, value, Normalizer.COMPARE_IGNORE_CASE) == 0) { 535 // case difference on date and time format doesn't matter 536 if ((element.parentNode.compareTo("timeFormat") == 0) 537 || (element.parentNode.compareTo("dateFormat") == 0)) { 538 isEqual = true; 539 } else { 540 if ((m_iOptions & OPT_CASE_SENSITIVE) == 0) { // it's not a case sensitive search so this is a match 541 isEqual = true; 542 } else { 543 isEqual = false; 544 break; // we have found a difference therefore break out of loop , we will print full row 545 } 546 } 547 } else { 548 isEqual = false; 549 break; // we have found a difference therefore break out of loop , we will print full row 550 } 551 } // end if 552 } // end while 553 554 // if any differences found then print all non null values 555 if (isEqual == false) { 556 writer.print(" <tr>\n"); 557 writer.print(" <td><a NAME=\"" + serialNumber + "\" href=\"#" + serialNumber + "\">" 558 + serialNumber + "</a></td>\n"); 559 writer.print(" <td>" + mapToAbbr(element.parentNode) + "</td>\n"); 560 writer.print(" <td>" + mapToAbbr(element.node) + "</td>\n"); 561 writer.print(" <td>" + element.index + "</td>\n"); 562 563 for (int i = 0; i < m_PlatformVect.size(); i++) { 564 String val = (String) element.platformData.get(m_PlatformVect.elementAt(i)); 565 if (val != null) { 566 writer.print(" <td>" + val + "</td>\n"); 567 } else { 568 writer.print(" <td> </td>\n"); 569 } 570 } // end while 571 572 writer.print(" </tr>\n"); 573 serialNumber++; 574 } // endif 575 576 return isEqual; 577 } 578 printValue(CompareElement element, PrintWriter writer)579 private void printValue(CompareElement element, PrintWriter writer) { 580 581 writer.print(" <tr>\n"); 582 writer.print(" <td><a NAME=\"" + serialNumber + "\" href=\"#" + serialNumber + "\">" 583 + serialNumber + "</a></td>\n"); 584 writer.print(" <td>" + mapToAbbr(element.parentNode) + "</td>\n"); 585 writer.print(" <td>" + mapToAbbr(element.node) + "</td>\n"); 586 writer.print(" <td>" + element.index + "</td>\n"); 587 serialNumber++; 588 589 for (int i = 0; i < PLATFORM_PRINT_ORDER.length; i++) { 590 String value = (String) element.platformData.get(PLATFORM_PRINT_ORDER[i]); 591 String color = (String) colorHash.get(PLATFORM_PRINT_ORDER[i]); 592 boolean caseDiff = false; 593 boolean isEqual = false; 594 // the locale exists for the given platform but there is no data 595 // so just write non breaking space and continue 596 // else the object contains value to be written .. so write it 597 if (value == null) { 598 if (requested.get(PLATFORM_PRINT_ORDER[i]) != null && doesNotExist.get(PLATFORM_PRINT_ORDER[i]) == null) { 599 writer.print(" <td> </td>\n"); 600 } 601 } else { 602 // pick the correct color 603 for (int j = 0; j < i; j++) { 604 String compareTo = (String) element.platformData.get(PLATFORM_PRINT_ORDER[j]); 605 if (compareTo == null) { 606 continue; 607 } else if (value.equals("")) { 608 color = "#FFFFFF"; 609 break; 610 } else if (element.parentNode.indexOf("decimalFormat") > -1 611 || element.parentNode.indexOf("currencyFormat") > -1) { 612 if (comparePatterns(compareTo, value)) { 613 color = (String) colorHash.get(PLATFORM_PRINT_ORDER[j]); 614 isEqual = true; 615 break; 616 } 617 } else if (Normalizer.compare(compareTo, value, 0) == 0) { 618 color = (String) colorHash.get(PLATFORM_PRINT_ORDER[j]); 619 isEqual = true; 620 break; 621 } else if (Normalizer.compare(compareTo, value, Normalizer.COMPARE_IGNORE_CASE) == 0) { 622 caseDiff = true; 623 color = (String) colorHash.get(PLATFORM_PRINT_ORDER[j]); 624 break; 625 } 626 } 627 if (isEqual) { 628 value = "="; 629 } else { 630 if (i > 0) { // not the first platform 631 if ((element.node.compareTo((String) "generation") == 0) 632 || (element.node.compareTo((String) "version") == 0)) { 633 // ignored 634 } else { 635 m_diffcount++; 636 } 637 } 638 } 639 if (m_Vetting) { 640 String altText = (String) element.platformData.get("ALT"); 641 writer.print("<td>" + value); 642 String parName = mapToAbbr(element.parentNode); 643 if ((parName.indexOf("_dateFormat") != -1) 644 || (parName.indexOf("_timeFormat") != -1)) { 645 writer.print("<form method=\"POST\" action=\"http://oss.software.ibm.com/cgi-bin/icu/lx/\">" + 646 "<input type=hidden name=\"_\" value=\"" + localeStr + "\"/>" + 647 "<input type=hidden name=\"x\" value=\"" + "dat" + "\"/>" + 648 "<input type=hidden name=\"str\" value=\"" + value + "\"/>" + 649 "<input type=submit value=\"" + "Test" + "\"/>" + 650 "</form>"); 651 } 652 if (/* m_Vetting && */element.referenceUrl != null) { 653 writer.print("<br><div align='right'><a href=\"" + element.referenceUrl 654 + "\"><i>(Ref)</i></a></div>"); 655 } 656 writer.print("</td>"); 657 if (altText != null) { 658 writer.print(" <td bgcolor=" + ALT_COLOR + ">" + altText); 659 writer.print("</td>\n"); 660 } 661 } else { 662 if (caseDiff == true) { 663 writer.print(" <td bgcolor=" + color + ">" + value + "†"); 664 } else { 665 writer.print(" <td bgcolor=" + color + ">" + value); 666 } 667 writer.print("</td>\n"); 668 } 669 } 670 } 671 writer.print(" </tr>\n"); 672 } 673 mapToAbbr(String source)674 private String mapToAbbr(String source) { 675 if (source.equals("icu:ruleBasedNumberFormat")) { 676 return "icu:rbnf"; 677 } 678 if (source.equals("icu:ruleBasedNumberFormats")) { 679 return "icu:rbnfs"; 680 } 681 if (source.equals("exemplarCharacters")) { 682 return "exemplarC"; 683 } 684 if (source.equals("localizedPatternChars")) { 685 return "lpc"; 686 } 687 return source; 688 } 689 printHTML(PrintWriter writer, String localeStr)690 private void printHTML(PrintWriter writer, String localeStr) { 691 // System.out.println("INFO: Creating the comparison chart "); 692 ULocale locale = new ULocale(localeStr); 693 String displayName = localeStr + " (" + locale.getDisplayName() + ") "; 694 if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) 695 writer.print("<p> Common data shown for reference purposes only</p>\n"); 696 697 if (!m_Vetting) { 698 writer.print("<html>\n" + 699 " <head>\n" + 700 " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" + 701 " <title>" + localeStr + "</title>\n" + 702 " </head>\n" + 703 " <style>\n" + 704 " <!--\n" + 705 " table { border-spacing: 0; border-collapse: collapse; width: 100%; \n" + 706 " border: 1px solid black }\n" + 707 " td, th { width: 10%; border-spacing: 0; border-collapse: collapse; color: black; \n" + 708 " vertical-align: top; border: 1px solid black }\n" + 709 " -->\n" + 710 " </style>" + 711 " <body bgcolor=\"#FFFFFF\">\n" + 712 " <p><b>" + displayName + 713 "<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_=" + localeStr + "\">Demo</a>, " + 714 "<a href=\"../../comparison_charts.html\">Cover Page</a>, " + 715 "<a href=\"./index.html\">Index</a>, " + 716 "<a href=\"../collation/" + localeStr + ".html\">Collation</a> " + 717 "</b></p>\n" + 718 " <table>\n"); 719 } else { 720 writer.print("<html>\n" + 721 " <head>\n" + 722 " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" + 723 " <title>Draft/Alt: " + localeStr + "</title>\n" + 724 " </head>\n" + 725 " <style>\n" + 726 " <!--\n" + 727 " table { border-spacing: 0; border-collapse: collapse; \n" + 728 " border: 1px solid black }\n" + 729 " td, th { border-spacing: 0; border-collapse: collapse; color: black; \n" + 730 " vertical-align: top; border: 1px solid black }\n" + 731 " -->\n" + 732 " </style>" + 733 " <body bgcolor=\"#FFFFFF\">\n" + 734 " <p><b>" + displayName + 735 "<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_=" + localeStr + "\">Demo</a>, " + 736 "<a href=\"./index.html\">Main and About</a>, " + 737 "</b></p>\n"); 738 if ((ourCvsVersion != null) && (ourCvsVersion.length() > 0)) { 739 writer.println("<h3><tt>" + LDMLUtilities.getCVSLink(localeStr) + localeStr + ".xml</a> version " + 740 LDMLUtilities.getCVSLink(localeStr, ourCvsVersion) + ourCvsVersion + "</a></tt></h3>"); 741 } 742 writer.print(" <table>\n"); 743 } 744 745 // PN added 746 if (((m_iOptions & OPT_DIFF) != 0) 747 || ((m_iOptions & OPT_DIFF_REF_COMMON) != 0)) { 748 printTableHeaderForDifferences(writer); 749 } else { 750 printTableHeader(writer); 751 } 752 753 // walk down the compare map and print the data 754 for (Object obj : compareMap.keySet()) { 755 CompareElement element; 756 if (obj != null) { 757 Object value = compareMap.get(obj); 758 if (value instanceof CompareElement) { 759 element = (CompareElement) value; 760 } else { 761 throw new RuntimeException( 762 "The object stored in the compare map is not an instance of CompareElement"); 763 } 764 // PN added 765 if ((m_iOptions & OPT_DIFF) != 0) { 766 printDifferentValues(element, writer); // only print differences 767 } else if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) { 768 printDifferentValuesWithRef(element, writer); 769 } else { 770 printValue(element, writer); 771 } 772 } else { 773 throw new RuntimeException("No objects stored in the compare map!"); 774 } 775 776 } 777 writer.print(" </table>\n"); 778 779 if (m_Vetting) { 780 if (m_Messages.length() > 0) { 781 writer.print("<table bgcolor=\"#FFBBBB\" border=3><tr><th>Warnings (please see source LDML)</th></tr>" + 782 "<tr><td>" + m_Messages + "</td></tr></table><p/><p/>\n"); 783 } 784 writer.print("<i>Interim page - subject to change</i> (<a href=\"./index.html\">Help</a>)<br/>"); 785 } 786 787 writer.print(" <p>Created on: " + cal.getTime() + "</p>\n" + 788 " </body>\n" + 789 "</html>\n"); 790 writer.flush(); 791 792 writer.flush(); 793 } 794 getFullyResolvedLocale(String localeName, String fileName)795 private Document getFullyResolvedLocale(String localeName, String fileName) { 796 // here we assume that "_" is the delimiter 797 int index = fileName.lastIndexOf(File.separatorChar); 798 String sourceDir = fileName.substring(0, index + 1); 799 String locale = fileName.substring(index + 1, fileName.lastIndexOf(".")); 800 System.out.println("INFO: Creating fully resolved tree for : " + fileName); 801 802 Document doc = LDMLUtilities.getFullyResolvedLDML(sourceDir, locale, true, true, true, true); 803 /* 804 * debugging code 805 * 806 * try{ 807 * OutputStreamWriter writer = new OutputStreamWriter(new 808 * FileOutputStream(destFolder+File.separator+localeName+"_debug.xml"),encoding); 809 * LDMLUtilities.printDOMTree(doc,new PrintWriter(writer)); 810 * writer.flush(); 811 * }catch( Exception e){ 812 * //throw the exception away .. this is for debugging 813 * } 814 */ 815 return doc; 816 } 817 addToCompareMap(String fileName, String key)818 private boolean addToCompareMap(String fileName, String key) { 819 // parse the test doc only if gold doc was parsed OK 820 Document testDoc = getFullyResolvedLocale(key, fileName); 821 requested.put(key, ""); 822 if (null == testDoc) { 823 doesNotExist.put(key, ""); 824 return false; 825 } 826 return extractMergeData(testDoc, key, false); 827 828 } 829 getParsedLocale(String localeName, String fileName)830 private Document getParsedLocale(String localeName, String fileName) { 831 // here we assume that "_" is the delimiter 832 System.out.println("INFO: Parsing " + fileName); 833 Document doc = LDMLUtilities.parse(fileName, true); // ? 834 835 return doc; 836 } 837 addVettable(String fileName, String key)838 private boolean addVettable(String fileName, String key) { 839 // parse the test doc only if gold doc was parsed OK 840 Document testDoc = getParsedLocale(key, fileName); 841 requested.put(key, ""); 842 if (null == testDoc) { 843 doesNotExist.put(key, ""); 844 return false; 845 } 846 return extractMergeData(testDoc, key, false); 847 848 } 849 comparePatterns(String pat1, String pat2)850 private boolean comparePatterns(String pat1, String pat2) { 851 // TODO: just return for now .. this is useful only 852 // when comparing data from toronto 853 try { 854 double args1 = 10000000000.00; 855 double args2 = -10000000000.00; 856 857 DecimalFormat fmt = new DecimalFormat(); 858 859 fmt.applyPattern(pat1); 860 String s1 = fmt.format(args1); 861 String s3 = fmt.format(args2); 862 fmt.applyPattern(pat2); 863 String s2 = fmt.format(args1); 864 String s4 = fmt.format(args2); 865 if (s1.equals(s2) && s3.equals(s4)) { 866 return true; 867 } 868 } catch (Exception e) { 869 // throw away the exception 870 } 871 return false; 872 873 // return true; 874 } 875 trim(String source)876 private String trim(String source) { 877 char[] src = source.toCharArray(); 878 char[] dest = new char[src.length]; 879 880 int start = 0; 881 while (start < (src.length) && (UCharacter.isWhitespace(src[start]))) { 882 start++; 883 } 884 int stop = src.length - 1; 885 while (stop > 0 && (UCharacter.isWhitespace(src[stop]) || (src[stop] == 0xA0))) { 886 stop--; 887 } 888 if (stop != -1 && start != src.length) { 889 System.arraycopy(src, start, dest, 0, (stop - start) + 1); 890 return new String(dest, 0, (stop - start) + 1); 891 } else { 892 return new String(); 893 } 894 895 } 896 addElement(String childNode, String parentNode, String id, String index, String platformValue, String platformName)897 private final void addElement(String childNode, String parentNode, String id, String index, 898 String platformValue, String platformName) { 899 addElement(childNode, parentNode, id, index, platformValue, platformName, null); 900 } 901 addElement(String childNode, String parentNode, String id, String index, String platformValue, String platformName, String referenceUrl)902 private void addElement(String childNode, String parentNode, String id, String index, 903 String platformValue, String platformName, String referenceUrl) { 904 m_totalCount++; 905 Object obj = compareMap.get(id); 906 CompareElement element; 907 if (obj == null) { 908 element = new CompareElement(); 909 // initialize the values 910 element.index = index; 911 element.parentNode = parentNode; 912 element.node = childNode; 913 element.referenceUrl = referenceUrl; 914 // add the element to the compare map 915 compareMap.put(id, element); 916 } else { 917 if (obj instanceof CompareElement) { 918 element = (CompareElement) obj; 919 } else { 920 throw new RuntimeException("The object stored in the compareMap is not a CompareElement object!"); 921 } 922 } 923 924 if ((!element.index.equals(index)) || 925 (!element.node.equals(childNode)) || 926 (!element.parentNode.equals(parentNode))) { 927 throw new RuntimeException("The retrieved object is not the same as the one trying to be saved, id is " 928 + id); 929 } 930 931 element.platformData.put(platformName, platformValue); 932 } 933 childrenAreElements(Node node)934 private boolean childrenAreElements(Node node) { 935 NodeList list = node.getChildNodes(); 936 for (int i = 0; i < list.getLength(); i++) { 937 if (list.item(i).getNodeType() == Node.ELEMENT_NODE) { 938 return true; 939 } 940 } 941 return false; 942 } 943 getTag(String childNodeName, String index)944 private String getTag(String childNodeName, String index) { 945 946 // for months make index a,b,c,d etc 947 if (childNodeName.indexOf("month") > -1) { 948 int i = Integer.parseInt(index); 949 StringBuffer temp = new StringBuffer(); 950 temp.append((char) ('a' + i)); 951 return temp.toString(); 952 } else if (childNodeName.indexOf("day") > -1) { 953 if (index.equals("sun")) { 954 return "a"; 955 } else if (index.equals("mon")) { 956 return "b"; 957 } else if (index.equals("tue")) { 958 return "c"; 959 } else if (index.equals("wed")) { 960 return "d"; 961 } else if (index.equals("thu")) { 962 return "e"; 963 } else if (index.equals("fri")) { 964 return "f"; 965 } else if (index.equals("sat")) { 966 return "g"; 967 } 968 } else { 969 return index; 970 } 971 return ""; 972 } 973 extractMergeData(Node node, String key, boolean parentDraft)974 private boolean extractMergeData(Node node, String key, boolean parentDraft) { 975 Node childOfSource; 976 for (childOfSource = node.getFirstChild(); childOfSource != null; childOfSource = childOfSource 977 .getNextSibling()) { 978 if (childOfSource.getNodeType() != Node.ELEMENT_NODE) { 979 continue; 980 } 981 String altText = null; 982 // String altReferenceUrl = null; 983 Node altForChild = null; 984 boolean subDraft = parentDraft; 985 String childOfSourceName = childOfSource.getNodeName(); 986 // Ignore collation and special tags 987 if (childOfSourceName.equals("collations") || childOfSource.equals("special") 988 || childOfSourceName.indexOf(":") > -1) { 989 continue; 990 } 991 992 if (m_Vetting && LDMLUtilities.isNodeDraft(childOfSource)) { 993 if (!subDraft) { 994 subDraft = true; 995 } 996 } 997 String referenceUrl = null; 998 if (m_Vetting) { 999 referenceUrl = LDMLUtilities.getAttributeValue(childOfSource, LDMLConstants.REFERENCES); 1000 if ((referenceUrl != null) && (referenceUrl.length() == 0)) { 1001 referenceUrl = null; 1002 } 1003 } 1004 1005 if (m_Vetting) { /* Should this be always checked? */ 1006 String alt = LDMLUtilities.getAttributeValue(childOfSource, LDMLConstants.ALT); 1007 if (alt != null) { 1008 if (alt.equals(LDMLConstants.PROPOSED)) { 1009 if (subDraft == false) { 1010 throw new IllegalArgumentException("***** ERROR Proposed but not draft? " 1011 + childOfSource.toString()); 1012 // NOTREACHED 1013 } 1014 altForChild = LDMLUtilities.getNonAltNodeLike(node, childOfSource); 1015 if (altForChild == null) { 1016 System.out.println("WARNING: can't find a node like this one: " + childOfSource.toString() 1017 + " - consider removing the alt=\"proposed\" attribute."); 1018 alt = null; 1019 } 1020 // altReferenceUrl = LDMLUtilities.getAttributeValue(altForChild, LDMLConstants.REFERENCES); 1021 // if((altReferenceUrl!=null)&&(altReferenceUrl.length()==0)) { 1022 // altReferenceUrl = null; 1023 // } 1024 } else if (subDraft) { /* don't care about nondraft */ 1025 String type = LDMLUtilities.getAttributeValue(childOfSource, LDMLConstants.TYPE); 1026 if (type == null) { 1027 type = ""; 1028 } 1029 m_Messages = m_Messages + " <br> UNKNOWN alt type '" + alt + "' for " + 1030 node.getNodeName() + "/" + childOfSourceName + "/" + type; 1031 System.err.println("Warning: unknown alt type '" + alt + "' - *IGNORING*. " 1032 + childOfSource.toString()); 1033 continue; 1034 } 1035 } 1036 } 1037 1038 if (childrenAreElements(childOfSource) == false) { 1039 NamedNodeMap attr = childOfSource.getAttributes(); 1040 Node typeNode = attr.getNamedItem("type"); 1041 Node altNode = attr.getNamedItem("alt"); 1042 String index = ""; 1043 if (typeNode != null) { 1044 /* 1045 * if(childOfSource.getNodeName().equals("era")&&!key.equals("common")){ 1046 * //remap type for comparison purpose 1047 * // TODO remove this hack 1048 * int j = Integer.parseInt(typeNode.getNodeValue()); 1049 * if(j>0){ 1050 * j--; 1051 * } 1052 * typeNode.setNodeValue(Integer.toString(j)); 1053 * } 1054 */ 1055 String temp = typeNode.getNodeValue(); 1056 1057 if (!temp.equals("standard")) { 1058 index = temp; 1059 } 1060 1061 } 1062 String alt = null; 1063 if (altNode != null) { 1064 alt = altNode.getNodeValue(); 1065 } 1066 if (m_Vetting) { // TODO: all? 1067 Node keyNode = attr.getNamedItem("key"); 1068 if (keyNode != null) { 1069 String temp = keyNode.getNodeValue(); 1070 index = index + " (" + temp + ")"; 1071 } 1072 } 1073 String nodeValue = ""; 1074 Node valueNode = childOfSource.getFirstChild(); 1075 if (valueNode != null) { 1076 String temp = trim(valueNode.getNodeValue()); 1077 if (!temp.equals("standard")) { 1078 nodeValue = temp; 1079 } 1080 } 1081 if (altForChild != null) { 1082 Node valueNode2 = altForChild.getFirstChild(); 1083 if (valueNode2 != null) { 1084 String temp = trim(valueNode2.getNodeValue()); 1085 if (!temp.equals("standard")) { 1086 altText = temp; 1087 } else { 1088 altText = "??? alt=standard"; 1089 } 1090 } else { 1091 altText = "??? alt has no value"; 1092 } 1093 } 1094 Node parentNode = childOfSource.getParentNode(); 1095 String parentNodeName = trim(parentNode.getNodeName()); 1096 String childNodeName = trim(childOfSource.getNodeName()); 1097 Node grandParentNode = childOfSource.getParentNode().getParentNode(); 1098 String grandParentNodeName = grandParentNode.getNodeName(); 1099 NamedNodeMap parentAttrib = parentNode.getAttributes(); 1100 String type = ""; 1101 if (parentAttrib != null) { 1102 Node mytypeNode = parentAttrib.getNamedItem("type"); 1103 if (mytypeNode != null) { 1104 String mytype = mytypeNode.getNodeValue(); 1105 if (!mytype.equals("standard")) { 1106 if (!parentNodeName.equals("calendar")) { 1107 type = mytype; 1108 } else { 1109 parentNodeName = mytype; 1110 } 1111 } 1112 } 1113 1114 } 1115 if (grandParentNodeName.equals("eras")) { 1116 Node calendar = grandParentNode.getParentNode(); 1117 NamedNodeMap gpa = calendar.getAttributes(); 1118 Node gptNode = gpa.getNamedItem("type"); 1119 if (gptNode != null) { 1120 String gptType = gptNode.getNodeValue(); 1121 if (!gptType.equals("standard")) { 1122 grandParentNodeName = gptType; 1123 } 1124 } 1125 parentNodeName = grandParentNodeName + "\u200b_" + parentNodeName; 1126 } 1127 if (grandParentNodeName.equals("calendar")) { 1128 NamedNodeMap gpa = grandParentNode.getAttributes(); 1129 Node gptNode = gpa.getNamedItem("type"); 1130 if (gptNode != null) { 1131 String gptType = gptNode.getNodeValue(); 1132 if (!gptType.equals("standard")) { 1133 grandParentNodeName = gptType; 1134 } 1135 } 1136 parentNodeName = grandParentNodeName + "\u200b_" + parentNodeName; 1137 } 1138 if (grandParentNodeName.equals("monthContext") || grandParentNodeName.equals("dayContext") || 1139 grandParentNodeName.equals("dateFormatLength") || grandParentNodeName.equals("timeFormatLength") || 1140 grandParentNodeName.equals("dateTimeFormatLength")) { 1141 1142 Node calendar = grandParentNode.getParentNode().getParentNode(); 1143 NamedNodeMap ggpa = calendar.getAttributes(); 1144 Node ggptNode = ggpa.getNamedItem("type"); 1145 if (ggptNode != null) { 1146 String ggptType = ggptNode.getNodeValue(); 1147 if (!ggptType.equals("standard")) { 1148 grandParentNodeName = ggptType; 1149 parentNodeName = ggptType + "\u200b_" + parentNodeName; 1150 } 1151 } 1152 NamedNodeMap gpa = grandParentNode.getAttributes(); 1153 Node gptNode = gpa.getNamedItem("type"); 1154 if (gptNode != null) { 1155 String gptType = gptNode.getNodeValue(); 1156 if (!gptType.equals("standard")) { 1157 parentNodeName = parentNodeName + "\u200b_" + gptType; 1158 } 1159 } 1160 NamedNodeMap pa = parentNode.getAttributes(); 1161 Node ptNode = pa.getNamedItem("type"); 1162 if (ptNode != null) { 1163 String ptType = ptNode.getNodeValue(); 1164 if (!ptType.equals("standard")) { 1165 parentNodeName = parentNodeName + "\u200b_" + ptType; 1166 } 1167 } 1168 1169 } 1170 if (childNodeName.equals("pattern") || grandParentNodeName.equals("zone")) { 1171 if (parentNodeName.indexOf("date") == -1 && parentNodeName.indexOf("time") == -1) { 1172 NamedNodeMap at = grandParentNode.getAttributes(); 1173 Node mytypeNode = at.getNamedItem("type"); 1174 if (mytypeNode != null) { 1175 String mytype = mytypeNode.getNodeValue(); 1176 if (!mytype.equals("standard")) { 1177 if (type.equals("")) { 1178 type = mytype; 1179 } else { 1180 type = type + "\u200b_" + mytype; 1181 } 1182 1183 } 1184 } 1185 } 1186 } 1187 if (grandParentNodeName.equals("special") || parentNodeName.equals("special") 1188 || childNodeName.equals("special") 1189 || grandParentNodeName.indexOf(":") > 0) { 1190 continue; 1191 } 1192 if (!nodeValue.equals("") && 1193 !childOfSource.getNodeName().equals("version")) { 1194 1195 // for country codes and language codes 1196 // replace the deprecated codes with the latest ones 1197 if (childNodeName.equals("language")) { 1198 String temp = (String) deprecatedLanguageCodes.get(index); 1199 if (temp != null) { 1200 index = temp; 1201 } 1202 } else if (childNodeName.equals("territory")) { 1203 String temp = (String) deprecatedCountryCodes.get(index); 1204 if (temp != null) { 1205 index = temp; 1206 } 1207 if (index != null && alt != null) { 1208 index = index + "_" + alt; 1209 } 1210 } 1211 String id = ""; 1212 if (!type.equals("")) { 1213 id = parentNodeName + "_" + childNodeName + "_" + type + "_" + getTag(childNodeName, index) 1214 + "_" + grandParentNodeName; 1215 } else { 1216 id = parentNodeName + "_" + childNodeName + "_" + getTag(childNodeName, index) + "_" 1217 + grandParentNodeName; 1218 } 1219 if (!index.equals("")) { 1220 if (!index.equals(nodeValue) && !index.equals("Fallback")) { 1221 if (!m_Vetting || subDraft) { 1222 addElement(childNodeName, parentNodeName, id, index, nodeValue, key, referenceUrl); 1223 if (altText != null) { 1224 addElement(childNodeName, parentNodeName, id, index, altText, "ALT", null /* altReferenceUrl */); 1225 } 1226 } 1227 } 1228 } else { 1229 if (!type.equals(nodeValue) && !type.equals("Fallback")) { 1230 if (!m_Vetting || subDraft) { 1231 addElement(childNodeName, parentNodeName, id, type, nodeValue, key, referenceUrl); 1232 if (altText != null) { 1233 addElement(childNodeName, parentNodeName, id, index, altText, "ALT", null /* altReferenceUrl */); 1234 } 1235 } 1236 } 1237 } 1238 } 1239 if (attr.getLength() > 0 && typeNode == null) { // TODO: make this a fcn 1240 // add an element for each attribute different for each attribute 1241 if (!m_Vetting || subDraft) { 1242 for (int i = 0; i < attr.getLength(); i++) { 1243 Node item = attr.item(i); 1244 String attrName = item.getNodeName(); 1245 if (attrName.equals("type")) { 1246 continue; 1247 } 1248 if (attrName.equals("alt")) { 1249 continue; 1250 } 1251 if (attrName.equals("draft")) { 1252 continue; 1253 } 1254 if (grandParentNodeName.equals("zone")) { 1255 parentNodeName = grandParentNodeName + "\u200b_" + parentNodeName; 1256 } 1257 String id = grandParentNodeName + "_" + parentNodeName + "_" + childNodeName + "_" + type 1258 + "_" + attrName; 1259 String subNodeValue = item.getNodeValue(); 1260 if (altForChild != null) { 1261 System.err.println(parentNodeName + "/" + childNodeName + " alt?? : " + altText); 1262 throw new IllegalArgumentException("UNKNOWN ALT SUBTAG + " + parentNodeName + "/" 1263 + childNodeName + " alt?? : " + altText + " not " + subNodeValue); 1264 } 1265 if (!index.equals("")) { 1266 addElement(childNodeName, parentNodeName, id, index, subNodeValue, key); 1267 } else if (!type.equals("")) { 1268 addElement(childNodeName, parentNodeName, id, type, subNodeValue, key); 1269 } else { 1270 if (!attrName.equals("draft")) { 1271 addElement(childNodeName, parentNodeName, id, attrName, subNodeValue, key); 1272 } 1273 } 1274 } 1275 } 1276 } 1277 } else { 1278 // the element has more children .. recurse to pick them all 1279 extractMergeData(childOfSource, key, subDraft); 1280 } 1281 } 1282 return true; 1283 } 1284 1285 // ***************************************************************************************************** 1286 // method writes the differences between xml files all to one HTML file 1287 // added by PN 1288 // ***************************************************************************************************** doBulkComparison()1289 private void doBulkComparison() { 1290 // get the output file name 1291 String fileName = destFolder + "/" + "Bulk.html"; 1292 System.out.println("INFO: Creating file named: " + fileName); 1293 String fileName_summary = destFolder + "/" + "Bulk_summary.html"; 1294 System.out.println("INFO: Creating file named: " + fileName_summary); 1295 1296 try { 1297 OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(fileName), encoding); 1298 OutputStreamWriter os_summary = new OutputStreamWriter(new FileOutputStream(fileName_summary), encoding); 1299 1300 // write the beginning of HTML page 1301 PrintWriter writer = new PrintWriter(os); 1302 PrintWriter writer_summary = new PrintWriter(os_summary); 1303 printHTMLStart(writer); 1304 printInfo(writer); 1305 printHTMLStart(writer_summary); 1306 1307 // not all platforms have files for all locales so first build a locale superset 1308 // loop thru locale files from each folder, each folder contains a certain number of locales 1309 // build a HashSet superset 1310 File localeDir = null; 1311 String[] fileList; 1312 Set<String> localeTreeSet = new TreeSet<String>(); // use TreeSet for locales in alphabetical order 1313 for (int i = 0; i < m_PlatformFolderVect.size(); i++) { 1314 localeDir = new File((String) m_PlatformFolderVect.elementAt(i)); 1315 fileList = localeDir.list(); 1316 for (int j = 0; j < fileList.length; j++) { 1317 if (fileList[j].endsWith(".xml")) { 1318 // need to exclude root.xml and supplementalData.xml 1319 if ((fileList[j].compareTo("root.xml") == 0) 1320 || (fileList[j].compareTo("supplementalData.xml") == 0)) 1321 continue; 1322 1323 // exclude common if -diff_ref_common option chosen by user 1324 // as common will only be shown as a reference if there are differences between locales for 1325 // other platforms 1326 if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) { 1327 String platform = (String) m_PlatformVect.elementAt(i); 1328 if (platform.compareTo(COMMON) == 0) 1329 continue; 1330 } 1331 1332 // entries are only added to TreeSets if not already there 1333 localeTreeSet.add(fileList[j]); 1334 // System.out.println (j + " adding " + fileList[j] + " to super set for platform " + (String) 1335 // m_PlatformFolderVect.elementAt(i) ); 1336 } 1337 } 1338 } 1339 1340 // System.out.println(" size of locale set = " + localeTreeSet.size()); 1341 // System.out.println(" number of platforms = " + m_PlatformFolderVect.size() + "(" + m_PlatformVect.size() 1342 // + ")"); 1343 1344 // loop thru all locales 1345 Object[] localeArray = localeTreeSet.toArray(); 1346 int i = 0; 1347 for (i = 0; i < localeArray.length; i++) { 1348 String platforms_with_this_locale = ""; 1349 1350 String localeFile = (String) localeArray[i]; // locale file name without path 1351 // class member localeStr used for writing to html 1352 localeStr = localeFile.substring(0, localeFile.indexOf('.')); 1353 System.out.println("INFO: locale : " + localeStr); 1354 1355 // add entry to CompareMap for any platforms having an xml file for the locale in question 1356 for (int j = 0; j < m_PlatformFolderVect.size(); j++) { 1357 localeDir = new File((String) m_PlatformFolderVect.elementAt(j)); 1358 fileList = localeDir.list(); 1359 for (int k = 0; k < fileList.length; k++) { 1360 if (fileList[k].compareTo(localeFile) == 0) // test for 2 matching xml filenames 1361 { 1362 String key = (String) m_PlatformVect.elementAt(j); // should use hashtable to link 1363 // m_PlatformVect and 1364 // m_PlatformFolderVect 1365 String xmlFileName = localeDir + "/" + localeArray[i]; 1366 // System.out.println(i + " " + j + " " + k + " adding " + xmlFileName + 1367 // " to compareMap at key " + key); 1368 addToCompareMap(xmlFileName, key); 1369 1370 if (!(((m_iOptions & OPT_DIFF_REF_COMMON) != 0) 1371 && (key.compareTo(COMMON) == 0))) { 1372 platforms_with_this_locale += key; 1373 platforms_with_this_locale += ", "; 1374 } 1375 } 1376 } 1377 } 1378 // System.out.println("size of compareMap " + compareMap.size()); 1379 1380 // print locale info and table header for this locale 1381 printHTMLLocaleStart(writer, i, platforms_with_this_locale); 1382 printTableHeaderForDifferences(writer); 1383 1384 // now do the comparison for a specific locale 1385 walkCompareMap(writer, localeStr, platforms_with_this_locale); 1386 1387 // clear the compareMap before starting next locale 1388 compareMap.clear(); 1389 1390 // finish html table 1391 printHTMLLocaleEnd(writer); 1392 1393 } // end outer for loop on locales 1394 1395 // print summary data to html summary file 1396 printLocaleSummaryToHTML(writer_summary); 1397 printAccumulatedResultsToHTML(writer_summary); 1398 1399 printHTMLEnd(writer, i); 1400 printHTMLEnd(writer_summary, i); 1401 } catch (Exception e) { 1402 e.printStackTrace(); 1403 } 1404 System.out.println("INFO: Finished writing file named: " + fileName); 1405 System.out.println("INFO: Finished writing file named: " + fileName_summary); 1406 } 1407 1408 // added by PN printHTMLStart(PrintWriter writer)1409 private void printHTMLStart(PrintWriter writer) { 1410 // System.out.println("INFO: Creating the comparison chart "); 1411 1412 writer.print("<html>\n" + 1413 " <head>\n" + 1414 " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" + 1415 " </head>\n" + 1416 " <style>\n" + 1417 " <!--\n" + 1418 " table { border-spacing: 0; border-collapse: collapse; width:100%; \n" + 1419 " border: 1px solid black }\n" + 1420 " td, th { border-spacing: 0; border-collapse: collapse; color: black; \n" + 1421 " vertical-align: top; border: 1px solid black }\n" + 1422 " -->\n" + 1423 " </style>" + 1424 " <body bgcolor=\"#FFFFFF\"> \n" + 1425 " <p><b>LOCALE DATA AUDIT</b></p>"); 1426 1427 writer.print(" <p>Created on: " + cal.getTime() + "</p>\n"); 1428 } 1429 printInfo(PrintWriter writer)1430 private void printInfo(PrintWriter writer) { 1431 if (((m_iOptions & OPT_DIFF_REF_COMMON) != 0) 1432 || ((m_iOptions & OPT_DIFF) != 0)) { 1433 writer 1434 .print(" <p>locale elements where there is a difference between at least two platforms are shown. \n" 1435 + 1436 "If a locale element is the same across all platforms it is not shown </p>"); 1437 } 1438 1439 if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) 1440 writer 1441 .print("<p> Common data is shown for reference purposes only and is not part of the comparison</p>\n"); 1442 1443 } 1444 1445 // added by PN printHTMLEnd(PrintWriter writer, int iTotalNumLocales)1446 private void printHTMLEnd(PrintWriter writer, int iTotalNumLocales) { 1447 writer.print("<p> </p>"); 1448 writer.print("<p> </p>"); 1449 writer.print(" <p><b>SUMMARY : </b></p>"); 1450 String platforms = ""; 1451 for (int i = 0; i < m_PlatformVect.size(); i++) { 1452 if (((m_iOptions & OPT_DIFF_REF_COMMON) != 0) 1453 && (m_PlatformVect.elementAt(i).equals(COMMON))) { 1454 continue; 1455 } 1456 platforms += m_PlatformVect.elementAt(i); 1457 platforms += ", "; 1458 } 1459 1460 writer.print(" <p><b>Platforms compared : " + platforms + "</b></p>"); 1461 writer 1462 .print(" <p><b>Total Number of locales audited : " 1463 + iTotalNumLocales 1464 + "</b></p>" 1465 + 1466 " <p><b>Total Number of conflicting locale data across all locales : " 1467 + serialNumber 1468 + "</b></p>" 1469 + 1470 " <p><b>Number of locale elements where a conflict was found for at least one locale : " 1471 + m_iTotalConflictingElements 1472 + "</b></p>" 1473 + 1474 " <p><b>Number of locale elements where no conflicts were found for any locale having this element : " 1475 + m_iTotalNonConflictingElements + "</b></p>" + 1476 " </body>\n" + 1477 "</html>\n"); 1478 writer.flush(); 1479 1480 writer.flush(); 1481 } 1482 1483 // added by PN printHTMLLocaleStart(PrintWriter writer, int iLocaleCounter, String platforms_with_this_locale)1484 private void printHTMLLocaleStart(PrintWriter writer, int iLocaleCounter, String platforms_with_this_locale) { 1485 ULocale locale = new ULocale(localeStr); 1486 String displayLang = locale.getDisplayLanguage(); 1487 String dispCountry = locale.getDisplayCountry(); 1488 String dispVariant = locale.getDisplayVariant(); 1489 String displayName = localeStr + " (" + displayLang + "_" + dispCountry; 1490 if (dispVariant.length() > 0) { 1491 displayName += "_" + dispVariant + ") "; 1492 } else { 1493 displayName += ") "; 1494 } 1495 1496 writer.print( 1497 " <p><b>" + iLocaleCounter + " " + displayName + 1498 // "<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_="+localeStr+"\">Demo</a>, "+ 1499 // "<a href=\"../comparison_charts.html\">Cover Page</a>, "+ 1500 // "<a href=\"./index.html\">Index</a>, "+ 1501 // "<a href=\"../collation_diff/"+localeStr+"_collation.html\">Collation</a> "+ 1502 "</b>" + 1503 "<b> platforms with this locale : " + platforms_with_this_locale + "</b></p>\n" + 1504 " <table>\n"); 1505 } 1506 1507 // added by PN printHTMLLocaleEnd(PrintWriter writer)1508 private void printHTMLLocaleEnd(PrintWriter writer) { 1509 writer.print(" </table>\n"); 1510 } 1511 1512 // added by PN walkCompareMap(PrintWriter writer, String locale, String platforms)1513 private void walkCompareMap(PrintWriter writer, String locale, String platforms) { 1514 SummaryData summData = new SummaryData(); 1515 1516 // walk down the compare map and print the data 1517 Iterator<String> iter = compareMap.keySet().iterator(); 1518 while (iter.hasNext()) { 1519 Object obj = iter.next(); 1520 CompareElement element; 1521 if (obj != null) { 1522 Object value = compareMap.get(obj); 1523 if (value instanceof CompareElement) { 1524 element = (CompareElement) value; 1525 } else { 1526 throw new RuntimeException( 1527 "The object stored in the compare map is not an instance of CompareElement"); 1528 } 1529 1530 boolean bIsEqual = true; 1531 if ((m_iOptions & OPT_DIFF) != 0) { 1532 bIsEqual = printDifferentValues(element, writer); 1533 AddToAccumulatedResultsMap((String) obj, element, localeStr, bIsEqual); 1534 } else if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) { 1535 bIsEqual = printDifferentValuesWithRef(element, writer); 1536 AddToAccumulatedResultsMap((String) obj, element, localeStr, bIsEqual); 1537 } else { 1538 printValue(element, writer); 1539 } 1540 1541 if (bIsEqual == false) 1542 summData.m_iNumConflictingElements++; 1543 1544 } else { 1545 throw new RuntimeException("No objects stored in the compare map!"); 1546 } 1547 } 1548 summData.m_szPlatforms = platforms; 1549 m_LocaleSummaryDataMap.put(locale, summData); 1550 1551 } 1552 1553 // PN added AddToAccumulatedResultsMap(String id, CompareElement element, String locale, boolean bIsEqual)1554 private void AddToAccumulatedResultsMap(String id, CompareElement element, String locale, boolean bIsEqual) { 1555 if (element == null) 1556 return; 1557 1558 AccumulatedResults ad = m_AccumulatedResultsMap.get(id); 1559 if (ad == null) { 1560 // System.out.println("id = " + id); 1561 1562 // add a new entry, there's none there with this key 1563 ad = new AccumulatedResults(); 1564 ad.index = element.index; 1565 ad.node = element.node; 1566 ad.parentNode = element.parentNode; 1567 if (bIsEqual == false) 1568 ad.localeVectDiff.add(locale); 1569 else 1570 ad.localeVectSame.add(locale); 1571 m_AccumulatedResultsMap.put(id, ad); 1572 } else { 1573 if ((!ad.index.equals(element.index)) || 1574 (!ad.node.equals(element.node)) || 1575 (!ad.parentNode.equals(element.parentNode))) // || 1576 // (!ad.type.equals(element.type))) type can be null so don't ceck its value 1577 { 1578 throw new RuntimeException( 1579 "The retrieved AccumulatedResults is not the same as the one trying to be saved - " + id); 1580 } else { 1581 if (bIsEqual == false) 1582 ad.localeVectDiff.add(locale); 1583 else 1584 ad.localeVectSame.add(locale); 1585 } 1586 } 1587 } 1588 printAccumulatedResultsToHTML(PrintWriter writer)1589 private void printAccumulatedResultsToHTML(PrintWriter writer) { 1590 writer.print("<p> </p>"); 1591 writer.print("<p> </p>"); 1592 writer 1593 .print("<p><b>Table below shows the number of locales where conflicts did and didn't occur on a per locale element basis"); 1594 writer 1595 .print(" (For brevity, locale elements where no conflicts were detected for any locale are not shown) </b></p>"); 1596 writer.print("<p></p>"); 1597 writer.print(" <table width=\"700\">\n"); 1598 writer.print(" <tr>\n" + 1599 " <th width=5%>N.</th>\n" + 1600 " <th width=10%>ParentNode</th>\n" + 1601 " <th width=10%>Name</th>\n" + 1602 " <th width=10%>ID</th>\n" + 1603 " <th width=10%># of non-conflicting locales</th>" + 1604 " <th width=10%># of conflicting locales</th>" + 1605 " <th width=45%>Locales where conflicts were found</th>" + 1606 " </tr>\n"); 1607 1608 // walk down the cm_AccumulateDifferenceMap and print the data 1609 Iterator<String> iter = m_AccumulatedResultsMap.keySet().iterator(); 1610 // System.out.println ("size = " + m_AccumulateDifferenceMap.size()); 1611 1612 int iCounter = 0; 1613 while (iter.hasNext()) { 1614 Object obj = iter.next(); 1615 AccumulatedResults ad; 1616 if (obj != null) { 1617 Object value = m_AccumulatedResultsMap.get(obj); 1618 if (value instanceof AccumulatedResults) { 1619 ad = (AccumulatedResults) value; 1620 } else { 1621 throw new RuntimeException( 1622 "The object stored in the AccumulateDifferencesMap is not an instance of AccumulateDifferences"); 1623 } 1624 1625 // only print locale elements where differences occurred 1626 if (ad.localeVectDiff.size() > 0) { 1627 m_iTotalConflictingElements++; 1628 writer.print(" <tr>\n"); 1629 writer.print(" <td>" + (iCounter++) + "</td>\n"); 1630 writer.print(" <td>" + ad.parentNode + "</td>\n"); 1631 writer.print(" <td>" + ad.node + "</td>\n"); 1632 writer.print(" <td>" + ad.index + "</td>\n"); 1633 writer.print(" <td>" + ad.localeVectSame.size() + "</td>\n"); 1634 writer.print(" <td>" + ad.localeVectDiff.size() + "</td>\n"); 1635 String locales = ""; 1636 for (int i = 0; i < ad.localeVectDiff.size(); i++) { 1637 locales += ad.localeVectDiff.elementAt(i); 1638 locales += ", "; 1639 } 1640 writer.print(" <td>" + locales + "</td>\n"); 1641 writer.print(" </tr>\n"); 1642 } else { 1643 m_iTotalNonConflictingElements++; 1644 } 1645 1646 } else { 1647 throw new RuntimeException("No objects stored in the AccumulateDifferencesMap!"); 1648 } 1649 } 1650 1651 writer.print(" </table>\n"); 1652 1653 } 1654 printLocaleSummaryToHTML(PrintWriter writer)1655 private void printLocaleSummaryToHTML(PrintWriter writer) { 1656 writer.print("<p> </p>"); 1657 writer.print("<p> </p>"); 1658 writer.print("<p><b>Table below shows the number of conflicting elements on a per locale basis\n</b></p>"); 1659 writer.print("<p></p>"); 1660 writer.print(" <table width=\"700\">\n"); 1661 writer.print(" <tr>\n" + 1662 " <th width=5%>N.</th>\n" + 1663 " <th width=20%>Locale</th>\n" + 1664 " <th width=40%>Platforms With This Locale</th>\n" + 1665 " <th width=35%># of elements where a conflict was found</th>\n" + 1666 " </tr>\n"); 1667 1668 // walk down the cm_AccumulateDifferenceMap and print the data 1669 Iterator<String> iter = m_LocaleSummaryDataMap.keySet().iterator(); 1670 int iCounter = 0; 1671 while (iter.hasNext()) { 1672 Object obj = iter.next(); 1673 SummaryData summData; 1674 if (obj != null) { 1675 Object value = m_LocaleSummaryDataMap.get(obj); 1676 if (value instanceof SummaryData) { 1677 summData = (SummaryData) value; 1678 } else { 1679 throw new RuntimeException( 1680 "The object stored in the AccumulateDifferencesMap is not an instance of AccumulateDifferences"); 1681 } 1682 1683 writer.print(" <tr>\n"); 1684 writer.print(" <td>" + (iCounter++) + "</td>\n"); 1685 writer.print(" <td>" + (String) obj + "</td>\n"); 1686 writer.print(" <td>" + summData.m_szPlatforms + "</td>\n"); 1687 writer.print(" <td>" + summData.m_iNumConflictingElements + "</td>\n"); 1688 writer.print(" </tr>\n"); 1689 } else { 1690 throw new RuntimeException("No objects stored in the AccumulateDifferencesMap!"); 1691 } 1692 } 1693 1694 writer.print(" </table>\n"); 1695 } 1696 getCVSVersion()1697 private void getCVSVersion() { 1698 ourCvsVersion = LDMLUtilities.loadFileRevision(goldFileName); 1699 } 1700 1701 } // end of class definition/declaration 1702