• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>&nbsp;</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>&nbsp;</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>&nbsp;</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 + "&#x2020;");
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>&nbsp;</p>");
1448         writer.print("<p>&nbsp;</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 + "&nbsp;&nbsp;&nbsp;" + 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>&nbsp;&nbsp;&nbsp; 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>&nbsp;</p>");
1591         writer.print("<p>&nbsp;</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("&nbsp;&nbsp; (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>&nbsp;</p>");
1657         writer.print("<p>&nbsp;</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