| /* |
| ******************************************************************************* |
| * Copyright (C) 2003-2012, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| /** |
| * @author Ram Viswanadha |
| */ |
| package org.unicode.cldr.icu; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.util.Calendar; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| import java.util.Vector; |
| |
| import org.unicode.cldr.util.LDMLUtilities; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import com.ibm.icu.lang.UCharacter; |
| import com.ibm.icu.text.Collator; |
| import com.ibm.icu.text.DecimalFormat; |
| import com.ibm.icu.text.Normalizer; |
| import com.ibm.icu.text.RuleBasedCollator; |
| import com.ibm.icu.util.ULocale; |
| |
| public class LDMLComparator { |
| /* |
| * This application will compare different locale data xml files |
| * conforming to localeElements.dtd and produces an xml file file |
| * in the format |
| */ |
| private static final int OPT_DIFF = 0x4000; /* 2exp15 */// PN |
| private static final int OPT_DIFF_REF_COMMON = 0x8000; /* 2exp16 */// PN |
| private static final int OPT_BULK = 0x00010000; // PN |
| private static final int OPT_CASE_SENSITIVE = 0x00020000; // PN |
| private static final int OPT_VETTING = 0x00040000; |
| private static final int OPT_UNKNOWN = 0x00080000; |
| |
| private static final String COMMON = "common"; |
| private static final String ICU = "icu"; |
| private static final String IBM_TOR = "ibm"; |
| private static final String WINDOWS = "windows"; |
| private static final String SUNJDK = "sunjdk"; |
| private static final String IBMJDK = "ibmjdk"; |
| private static final String HPUX = "hp"; |
| private static final String APPLE = "apple"; |
| private static final String SOLARIS = "solaris"; |
| private static final String OPEN_OFFICE = "open_office"; |
| private static final String AIX = "aix"; |
| private static final String LINUX = "linux"; |
| |
| private static final String ALTERNATE_TITLE = "(Original)"; |
| private static final String ALT_COLOR = "#DDDDFD"; |
| // PN added |
| private static final String DIFF = "diff"; |
| private static final String DIFF_REF_COMMON = "diff_ref_common"; |
| private static final String BULK = "bulk"; |
| private static final String CASE_SENSITIVE = "case_sensitive"; |
| private static final String VETTING = "vetting"; |
| private static final String[] PLATFORM_PRINT_ORDER = { |
| COMMON, |
| ICU, |
| WINDOWS, |
| SUNJDK, |
| IBMJDK, |
| IBM_TOR, |
| APPLE, |
| SOLARIS, |
| OPEN_OFFICE, |
| AIX, |
| LINUX, |
| HPUX, |
| }; |
| |
| private static final String USER_OPTIONS[] = { |
| "-" + COMMON, |
| "-" + ICU, |
| "-" + IBM_TOR, |
| "-" + WINDOWS, |
| "-" + SUNJDK, |
| "-" + IBMJDK, |
| "-" + HPUX, |
| "-" + APPLE, |
| "-" + SOLARIS, |
| "-" + OPEN_OFFICE, |
| "-" + AIX, |
| "-" + LINUX, |
| "-s", |
| "-d", |
| "-" + DIFF, // PN added, indicates that only differing elements/attributes to be written to html |
| "-" + DIFF_REF_COMMON, // PN added, same as diff only common is excluded from diff but gets printed to html for |
| // reference purposes |
| "-" + BULK, // do a bulk comparison of folder contents |
| "-" + CASE_SENSITIVE, // do case sensitive matching (by default it's not case sensitive) |
| "-" + VETTING // go into Vetting mode. (show draft, etc) |
| }; |
| |
| public static void main(String[] args) { |
| LDMLComparator comparator = new LDMLComparator(); |
| comparator.processArgs(args); |
| } |
| |
| static Collator getDefaultCollation() { |
| // if (DEFAULT_COLLATION != null) return DEFAULT_COLLATION; |
| RuleBasedCollator temp = (RuleBasedCollator) Collator.getInstance(ULocale.ENGLISH); |
| temp.setStrength(Collator.IDENTICAL); |
| temp.setNumericCollation(true); |
| // DEFAULT_COLLATION = temp; |
| return temp; |
| } |
| |
| Hashtable<String, String> optionTable = new Hashtable<String, String>(); |
| private String destFolder = "."; |
| private String localeStr; |
| private String ourCvsVersion = ""; |
| private Calendar cal = Calendar.getInstance(); |
| private Hashtable<String, String> colorHash = new Hashtable<String, String>(); |
| private String goldFileName; |
| private String goldKey; |
| private int serialNumber = 0; |
| private Map<String, Object> compareMap = new TreeMap<String, Object>(getDefaultCollation()); |
| private Hashtable<String, String> doesNotExist = new Hashtable<String, String>(); |
| private Hashtable<String, String> requested = new Hashtable<String, String>(); |
| private Hashtable<String, String> deprecatedLanguageCodes = new Hashtable<String, String>(); |
| private Hashtable<String, String> deprecatedCountryCodes = new Hashtable<String, String>(); |
| private Set<String> vettingSet = new TreeSet<String>(); |
| private String encoding = "UTF-8"; // default encoding |
| |
| // PN added |
| private Vector<String> m_PlatformVect = new Vector<String>(); // holds names of platforms |
| private Vector<String> m_PlatformFolderVect = new Vector<String>(); // holds names of folders containing locale data |
| // for each platform |
| private int m_iOptions; |
| private Map<String, AccumulatedResults> m_AccumulatedResultsMap = new TreeMap<String, AccumulatedResults>(); |
| private int m_iTotalConflictingElements = 0; |
| private int m_iTotalNonConflictingElements = 0; |
| private Map<String, SummaryData> m_LocaleSummaryDataMap = new TreeMap<String, SummaryData>(); // key = localename, |
| // data = summary info |
| private boolean m_Vetting = false; |
| |
| private int m_totalCount = 0; |
| private int m_diffcount = 0; |
| private String m_Messages = ""; |
| |
| private class CompareElement |
| { |
| String node; |
| String index; |
| String parentNode; |
| Hashtable<String, String> platformData = new Hashtable<String, String>(); |
| String referenceUrl; |
| } |
| |
| // PN added |
| // used for bulk comparisons |
| // holds the locales where the element identified by node,index and parentNode conflict |
| // for at least 2 of the platforms tested |
| // holds the locales where the element identified by node,index and parentNode don't |
| // for at all the platforms tested |
| private class AccumulatedResults |
| { |
| String node; |
| String index; |
| String parentNode; |
| Vector<String> localeVectDiff = new Vector<String>(); // holds locales where a conflict in data was found |
| Vector<String> localeVectSame = new Vector<String>(); // holds locales where a no conflict in data was found |
| } |
| |
| private class SummaryData |
| { |
| String m_szPlatforms; |
| int m_iNumConflictingElements; |
| } |
| |
| LDMLComparator() { |
| // initialize the color hash |
| colorHash.put(COMMON, "#AD989D"); |
| colorHash.put(ICU, "#CCFF00"); |
| colorHash.put(IBM_TOR, "#FF7777"); |
| colorHash.put(WINDOWS, "#98FB98"); |
| colorHash.put(SUNJDK, "#FF6633"); |
| colorHash.put(IBMJDK, "#CCFFFF"); |
| colorHash.put(HPUX, "#FFE4B5"); |
| colorHash.put(APPLE, "#FFBBBB"); |
| colorHash.put(SOLARIS, "#CC9966"); |
| colorHash.put(OPEN_OFFICE, "#FFFF33"); |
| colorHash.put(AIX, "#EB97FE"); |
| colorHash.put(LINUX, "#1191F1"); |
| // TODO - use deprecatedMap instead. |
| // deprecatedLanguageCodes.put("sh", "what ever the new one is"); |
| deprecatedLanguageCodes.put("iw", "he"); |
| deprecatedLanguageCodes.put("in", "id"); |
| deprecatedLanguageCodes.put("ji", "yi"); |
| deprecatedLanguageCodes.put("jw", "jv"); // this does not even exist, JDK thinks jw is javanese!! |
| |
| // country codes |
| deprecatedCountryCodes.put("TP", "TL"); |
| deprecatedCountryCodes.put("ZR", "CD"); |
| } |
| |
| private void processArgs(String[] args) |
| { |
| m_iOptions = identifyOptions(args); |
| if ((args.length < 2) || ((m_iOptions & OPT_UNKNOWN) != 0)) |
| { |
| printUsage(); |
| return; |
| } |
| boolean warning[] = new boolean[1]; |
| warning[0] = false; |
| Enumeration<String> en = optionTable.keys(); |
| |
| try |
| { |
| // check for bulk operation |
| if ((m_iOptions & OPT_BULK) != 0) |
| { |
| doBulkComparison(); |
| } |
| else |
| { |
| localeStr = goldFileName.substring(goldFileName.lastIndexOf(File.separatorChar) + 1, |
| goldFileName.lastIndexOf('.')); |
| |
| String fileName = destFolder + File.separator + localeStr + ".html"; |
| m_totalCount = 0; |
| m_diffcount = 0; |
| if ((m_iOptions & OPT_VETTING) != 0) |
| { |
| m_Vetting = true; |
| addVettable(goldFileName, goldKey); |
| } |
| else |
| { |
| addToCompareMap(goldFileName, goldKey); |
| } |
| for (; en.hasMoreElements();) |
| { |
| String key = (String) en.nextElement(); |
| String compFile = (String) optionTable.get(key); |
| if ((m_iOptions & OPT_VETTING) != 0) { |
| addVettable(goldFileName, goldKey); |
| } else { |
| addToCompareMap(compFile, key); |
| } |
| } |
| if ((m_totalCount == 0) && m_Vetting) { // only optional for vetting. |
| // System.out.println("INFO: no file created (nothing to write..) " + fileName); |
| } else { |
| ourCvsVersion = ""; |
| getCVSVersion(); |
| OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(fileName), encoding); |
| System.out.println("INFO: Writing: " + fileName + "\t(" + m_totalCount + " items)"); |
| PrintWriter writer = new PrintWriter(os); |
| printHTML(writer, localeStr); |
| { |
| ULocale ourLocale = new ULocale(localeStr); |
| String idxFileName = destFolder + File.separator + ourLocale.getDisplayLanguage() + "_" |
| + ourLocale.getDisplayCountry() + "_" + localeStr + ".idx"; |
| OutputStreamWriter is = new OutputStreamWriter(new FileOutputStream(idxFileName), "utf-8"); |
| PrintWriter indexwriter = new PrintWriter(is); |
| indexwriter.println("<tr>"); |
| indexwriter.println(" <td>" + |
| localeStr + |
| "</td>"); |
| indexwriter.println(" <td><a href=\"" + localeStr + ".html" + "\">" + |
| ourLocale.getDisplayName() + "</a></td>"); |
| indexwriter.println(" <td>" + m_totalCount + "</td>"); |
| if (!m_Vetting) { |
| indexwriter.println(" <td>" + m_diffcount + "</td>"); |
| } |
| indexwriter.println(" <td>" + LDMLUtilities.getCVSLink(localeStr, ourCvsVersion) |
| + ourCvsVersion + "</a></td>"); |
| indexwriter.println("</tr>"); |
| is.close(); |
| } |
| // TODO: handle vettingSet; |
| } |
| } |
| } catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| |
| } |
| |
| private void printUsage() { |
| System.err.println("Usage: LDMLComparator [<option>:<gold>] filename1 [option] filename2 ... \n" + |
| " LDMLComparator [-common:<gold>] filename [-icu] filename" + |
| " [-ibmjdk] filename [-windows] filename" + |
| " [-hpux] filename [-solaris] filename" + |
| " [-ibmtor] filename [-apple] filename" + |
| " [-sunjdk] filename [-open_office] filename" + |
| " [-aix] filename [-linux] filename" + |
| " [-diff / -diff_ref_common] [-bulk]" + |
| " [-case_sensitive (only active if -diff of -diff-ref-common option selected)]" |
| ); |
| System.err.println("\nExample 1: \n " + |
| "LDMLComparator -solaris:gold foldername1 -sunjdk foldername2 -common foldername3 -diff-ref-common -bulk\n" |
| + |
| "\t\t will do a bulk comparison of the locales in folder1 and folder2 \n " + |
| "\t\t and print the values of any differing elements plus the \n" + |
| "\t\t corresponding element's value in folder3 to bulk.html \n" + |
| "\t\t as well as a summary to bulk_summary.html \n"); |
| System.err.println("Example 2: \n" + |
| "LDMLComparator -common:gold filename1 -sunjdk filename2 -diff \n" + |
| "\t\t will do a comparison of the locales specified by filename1 and \n" + |
| "\t\t filename2 and print the values of any differing elements \n" + |
| "\t\t to a file called filename1.html in the current directory \n"); |
| } |
| |
| private int identifyOptions(String[] options) |
| { |
| int result = 0; |
| for (int j = 0; j < options.length; j++) |
| { |
| String option = options[j]; |
| boolean isGold = false; |
| if (option.startsWith("-")) |
| { |
| if (option.indexOf(":gold") > 0) |
| { |
| option = option.substring(0, option.indexOf(":")); |
| isGold = true; |
| } |
| boolean optionRecognized = false; |
| for (int i = 0; i < USER_OPTIONS.length; i++) |
| { |
| |
| if (USER_OPTIONS[i].equals(option)) |
| { |
| result |= (int) (1 << i); // calculate option bit value |
| optionRecognized = true; |
| if (USER_OPTIONS[i].equals("-s")) { |
| } |
| else if (USER_OPTIONS[i].equals("-d")) { |
| destFolder = options[++j]; |
| } |
| else if (USER_OPTIONS[i].equals("-" + DIFF)) { |
| |
| } |
| else if (USER_OPTIONS[i].equals("-" + DIFF_REF_COMMON)) { |
| |
| } |
| else if (USER_OPTIONS[i].equals("-" + BULK)) { |
| |
| } |
| else if (USER_OPTIONS[i].equals("-" + VETTING)) { |
| m_Vetting = true; |
| } |
| else if (USER_OPTIONS[i].equals("-" + CASE_SENSITIVE)) { |
| } |
| else |
| { |
| if (!isGold) |
| { |
| optionTable.put(option.substring(1, option.length()), options[++j]); |
| |
| } else |
| { |
| goldFileName = options[++j]; |
| goldKey = option.substring(1, option.length()); |
| } |
| // PN added |
| m_PlatformVect.add(option.substring(1, option.length())); |
| m_PlatformFolderVect.add(options[j]); |
| } |
| break; |
| } |
| } |
| if (!optionRecognized) |
| { |
| result |= OPT_UNKNOWN; |
| } |
| } else { |
| if (m_Vetting == true) { |
| vettingSet.add(option); |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| private void printTableHeader(PrintWriter writer) { |
| |
| writer.print(" <tr>\n" + |
| " <th>N.</th>\n" + |
| " <th>ParentNode</th>\n" + |
| " <th>Name</th>\n" + |
| " <th>ID</th>\n"); |
| |
| for (int i = 0; i < PLATFORM_PRINT_ORDER.length && PLATFORM_PRINT_ORDER[i] != null; i++) { |
| String name = PLATFORM_PRINT_ORDER[i]; |
| String folder; |
| |
| Object obj = requested.get(name); |
| if (obj != null && doesNotExist.get(name) == null) { |
| folder = name + "/main/"; |
| if (name.equals("icu") || name.equals("common") || name.indexOf("jdk") >= 0) { |
| int index = localeStr.indexOf("_"); |
| String parent = ""; |
| if (index > -1) { |
| parent = localeStr.substring(0, index); |
| } |
| writer.print(" <th bgcolor=\"" + |
| (String) colorHash.get(name) + "\">" + |
| name.toUpperCase() + |
| " (<a href=\"../../" + folder + localeStr + ".xml\">" + localeStr + "</a>," + |
| " <a href=\"../../" + folder + parent + ".xml\">" + parent + "</a>," + |
| " <a href=\"../../" + folder + "root.xml\">root</a>)" + |
| "</th>\n"); |
| } else { |
| writer.print(" <th bgcolor=\"" + |
| (String) colorHash.get(name) + "\">" + |
| name.toUpperCase() + |
| " (<a href=\"../../" + folder + localeStr + ".xml\">" + localeStr + "</a>)" + |
| "</th>\n"); |
| } |
| } |
| } |
| if (m_Vetting) { |
| writer.print("<th bgcolor=\"" + ALT_COLOR + "\">" + ALTERNATE_TITLE + "</th>"); |
| } |
| writer.print(" </tr>\n"); |
| } |
| |
| // PN added |
| private void printTableHeaderForDifferences(PrintWriter writer) |
| { |
| |
| writer.print(" <tr>\n" + |
| " <th width=10%>N.</th>\n" + |
| " <th width=10%>ParentNode</th>\n" + |
| " <th width=10%>Name</th>\n" + |
| " <th width=10%>ID</th>\n"); |
| |
| for (int i = 0; i < m_PlatformVect.size(); i++) |
| { |
| String name = (String) m_PlatformVect.elementAt(i); |
| String folder; |
| |
| // Object obj = requested.get(name); |
| // if(obj!=null && doesNotExist.get(name)==null ) |
| // { |
| folder = name + "/xml/"; |
| writer.print(" <th bgcolor=\"" + |
| (String) colorHash.get(name) + "\">" + |
| name.toUpperCase() + |
| " (<a href=\"../" + folder + localeStr + ".xml\">xml</a>)" + |
| "</th>\n"); |
| // not used numPlatforms++; |
| |
| // } |
| } |
| if (m_Vetting) { |
| writer.print("<th>" + ALTERNATE_TITLE + "</th>"); |
| } |
| writer.print(" </tr>\n"); |
| } |
| |
| // PN added |
| // method to print differing elements/attributes only to HTML |
| // returns false if a difference found otherwise true |
| private boolean printDifferentValues(CompareElement element, PrintWriter writer) |
| { |
| boolean isEqual = true; |
| // following don't count |
| if ((element.node.compareTo((String) "generation") == 0) |
| || (element.node.compareTo((String) "version") == 0)) |
| { |
| return isEqual; |
| } |
| |
| String compareTo = null; |
| boolean bFoundFirst = false; |
| for (int i = 0; i < m_PlatformVect.size(); i++) |
| { |
| String value = element.platformData.get(m_PlatformVect.elementAt(i)); |
| if (value == null) |
| continue; |
| // loop until non null value is found, this is the reference for comparison |
| if (bFoundFirst == false) |
| { |
| compareTo = value; |
| bFoundFirst = true; |
| } |
| else |
| { // we have something to compare this element to |
| if (Normalizer.compare(compareTo, value, 0) == 0) |
| { |
| isEqual = true; |
| } |
| else if (Normalizer.compare(compareTo, value, Normalizer.COMPARE_IGNORE_CASE) == 0) |
| { |
| if ((m_iOptions & OPT_CASE_SENSITIVE) == 0) |
| { // it's not a case sensitive search so this is a match |
| isEqual = true; |
| } |
| else |
| { |
| isEqual = false; |
| break; // we have found a difference therefore break out of loop , we will print full row |
| } |
| } |
| else |
| { |
| isEqual = false; |
| break; // we have found a difference therefore break out of loop , we will print full row |
| } |
| } // end if |
| } // end while |
| |
| // if any differences found then print all non null values |
| if (isEqual == false) |
| { |
| writer.print(" <tr>\n"); |
| writer.print(" <td><a NAME=\"" + serialNumber + "\" href=\"#" + serialNumber + "\">" |
| + serialNumber + "</a></td>\n"); |
| writer.print(" <td>" + mapToAbbr(element.parentNode) + "</td>\n"); |
| writer.print(" <td>" + mapToAbbr(element.node) + "</td>\n"); |
| writer.print(" <td>" + element.index + "</td>\n"); |
| |
| for (int i = 0; i < m_PlatformVect.size(); i++) |
| { |
| String val = (String) element.platformData.get(m_PlatformVect.elementAt(i)); |
| if (val != null) |
| { |
| writer.print(" <td>" + val + "</td>\n"); |
| } |
| else |
| { |
| writer.print(" <td> </td>\n"); |
| } |
| } // end while |
| |
| writer.print(" </tr>\n"); |
| serialNumber++; |
| } // endif |
| return isEqual; |
| } |
| |
| // PN added |
| // method to print differing elements/attributes only to HTML excluding Common from diff |
| // only if the other platfroms differ amongst themselves will the Common data be printed |
| // returns false if a difference found otherwise true |
| private boolean printDifferentValuesWithRef(CompareElement element, PrintWriter writer) |
| { |
| boolean isEqual = true; |
| // following don't count |
| if ((element.node.compareTo((String) "generation") == 0) |
| || (element.node.compareTo((String) "version") == 0)) |
| { |
| return isEqual; |
| } |
| |
| String compareTo = null; |
| boolean bFoundFirst = false; |
| for (int i = 0; i < m_PlatformVect.size(); i++) |
| { |
| // excluding Common from diff |
| String platform = (String) m_PlatformVect.elementAt(i); |
| if (platform.compareTo(COMMON) == 0) |
| continue; |
| |
| String value = (String) element.platformData.get(platform); |
| if (value == null) |
| continue; |
| |
| // loop until non null value is found, this is the reference for comparison |
| if (bFoundFirst == false) |
| { |
| compareTo = value; |
| bFoundFirst = true; |
| } |
| else |
| { // we have something to compare this element to |
| if (Normalizer.compare(compareTo, value, 0) == 0) |
| { |
| isEqual = true; |
| } |
| else if (Normalizer.compare(compareTo, value, Normalizer.COMPARE_IGNORE_CASE) == 0) |
| { |
| // case difference on date and time format doesn't matter |
| if ((element.parentNode.compareTo("timeFormat") == 0) |
| || (element.parentNode.compareTo("dateFormat") == 0)) |
| { |
| isEqual = true; |
| } |
| else |
| { |
| if ((m_iOptions & OPT_CASE_SENSITIVE) == 0) |
| { // it's not a case sensitive search so this is a match |
| isEqual = true; |
| } |
| else |
| { |
| isEqual = false; |
| break; // we have found a difference therefore break out of loop , we will print full row |
| } |
| } |
| } |
| else |
| { |
| isEqual = false; |
| break; // we have found a difference therefore break out of loop , we will print full row |
| } |
| } // end if |
| } // end while |
| |
| // if any differences found then print all non null values |
| if (isEqual == false) |
| { |
| writer.print(" <tr>\n"); |
| writer.print(" <td><a NAME=\"" + serialNumber + "\" href=\"#" + serialNumber + "\">" |
| + serialNumber + "</a></td>\n"); |
| writer.print(" <td>" + mapToAbbr(element.parentNode) + "</td>\n"); |
| writer.print(" <td>" + mapToAbbr(element.node) + "</td>\n"); |
| writer.print(" <td>" + element.index + "</td>\n"); |
| |
| for (int i = 0; i < m_PlatformVect.size(); i++) |
| { |
| String val = (String) element.platformData.get(m_PlatformVect.elementAt(i)); |
| if (val != null) |
| { |
| writer.print(" <td>" + val + "</td>\n"); |
| } |
| else |
| { |
| writer.print(" <td> </td>\n"); |
| } |
| } // end while |
| |
| writer.print(" </tr>\n"); |
| serialNumber++; |
| } // endif |
| |
| return isEqual; |
| } |
| |
| private void printValue(CompareElement element, PrintWriter writer) { |
| |
| writer.print(" <tr>\n"); |
| writer.print(" <td><a NAME=\"" + serialNumber + "\" href=\"#" + serialNumber + "\">" |
| + serialNumber + "</a></td>\n"); |
| writer.print(" <td>" + mapToAbbr(element.parentNode) + "</td>\n"); |
| writer.print(" <td>" + mapToAbbr(element.node) + "</td>\n"); |
| writer.print(" <td>" + element.index + "</td>\n"); |
| serialNumber++; |
| |
| for (int i = 0; i < PLATFORM_PRINT_ORDER.length; i++) { |
| String value = (String) element.platformData.get(PLATFORM_PRINT_ORDER[i]); |
| String color = (String) colorHash.get(PLATFORM_PRINT_ORDER[i]); |
| boolean caseDiff = false; |
| boolean isEqual = false; |
| // the locale exists for the given platform but there is no data |
| // so just write non breaking space and continue |
| // else the object contains value to be written .. so write it |
| if (value == null) { |
| if (requested.get(PLATFORM_PRINT_ORDER[i]) != null && doesNotExist.get(PLATFORM_PRINT_ORDER[i]) == null) { |
| writer.print(" <td> </td>\n"); |
| } |
| } else { |
| // pick the correct color |
| for (int j = 0; j < i; j++) { |
| String compareTo = (String) element.platformData.get(PLATFORM_PRINT_ORDER[j]); |
| if (compareTo == null) { |
| continue; |
| } else if (value.equals("")) { |
| color = "#FFFFFF"; |
| break; |
| } else if (element.parentNode.indexOf("decimalFormat") > -1 |
| || element.parentNode.indexOf("currencyFormat") > -1) { |
| if (comparePatterns(compareTo, value)) { |
| color = (String) colorHash.get(PLATFORM_PRINT_ORDER[j]); |
| isEqual = true; |
| break; |
| } |
| } else if (Normalizer.compare(compareTo, value, 0) == 0) { |
| color = (String) colorHash.get(PLATFORM_PRINT_ORDER[j]); |
| isEqual = true; |
| break; |
| } else if (Normalizer.compare(compareTo, value, Normalizer.COMPARE_IGNORE_CASE) == 0) { |
| caseDiff = true; |
| color = (String) colorHash.get(PLATFORM_PRINT_ORDER[j]); |
| break; |
| } |
| } |
| if (isEqual) { |
| value = "="; |
| } else { |
| if (i > 0) { // not the first platform |
| if ((element.node.compareTo((String) "generation") == 0) |
| || (element.node.compareTo((String) "version") == 0)) { |
| // ignored |
| } else { |
| m_diffcount++; |
| } |
| } |
| } |
| if (m_Vetting) { |
| String altText = (String) element.platformData.get("ALT"); |
| writer.print("<td>" + value); |
| String parName = mapToAbbr(element.parentNode); |
| if ((parName.indexOf("_dateFormat") != -1) |
| || (parName.indexOf("_timeFormat") != -1)) |
| { |
| writer.print("<form method=\"POST\" action=\"http://oss.software.ibm.com/cgi-bin/icu/lx/\">" + |
| "<input type=hidden name=\"_\" value=\"" + localeStr + "\"/>" + |
| "<input type=hidden name=\"x\" value=\"" + "dat" + "\"/>" + |
| "<input type=hidden name=\"str\" value=\"" + value + "\"/>" + |
| "<input type=submit value=\"" + "Test" + "\"/>" + |
| "</form>"); |
| } |
| if (/* m_Vetting && */element.referenceUrl != null) { |
| writer.print("<br><div align='right'><a href=\"" + element.referenceUrl |
| + "\"><i>(Ref)</i></a></div>"); |
| } |
| writer.print("</td>"); |
| if (altText != null) { |
| writer.print(" <td bgcolor=" + ALT_COLOR + ">" + altText); |
| writer.print("</td>\n"); |
| } |
| } else { |
| if (caseDiff == true) { |
| writer.print(" <td bgcolor=" + color + ">" + value + "†"); |
| } else { |
| writer.print(" <td bgcolor=" + color + ">" + value); |
| } |
| writer.print("</td>\n"); |
| } |
| } |
| } |
| writer.print(" </tr>\n"); |
| } |
| |
| private String mapToAbbr(String source) { |
| if (source.equals("icu:ruleBasedNumberFormat")) { |
| return "icu:rbnf"; |
| } |
| if (source.equals("icu:ruleBasedNumberFormats")) { |
| return "icu:rbnfs"; |
| } |
| if (source.equals("exemplarCharacters")) { |
| return "exemplarC"; |
| } |
| if (source.equals("localizedPatternChars")) { |
| return "lpc"; |
| } |
| return source; |
| } |
| |
| private void printHTML(PrintWriter writer, String localeStr) { |
| // System.out.println("INFO: Creating the comparison chart "); |
| ULocale locale = new ULocale(localeStr); |
| String displayName = localeStr + " (" + locale.getDisplayName() + ") "; |
| if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| writer.print("<p> Common data shown for reference purposes only</p>\n"); |
| |
| if (!m_Vetting) { |
| writer.print("<html>\n" + |
| " <head>\n" + |
| " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" + |
| " <title>" + localeStr + "</title>\n" + |
| " </head>\n" + |
| " <style>\n" + |
| " <!--\n" + |
| " table { border-spacing: 0; border-collapse: collapse; width: 100%; \n" + |
| " border: 1px solid black }\n" + |
| " td, th { width: 10%; border-spacing: 0; border-collapse: collapse; color: black; \n" + |
| " vertical-align: top; border: 1px solid black }\n" + |
| " -->\n" + |
| " </style>" + |
| " <body bgcolor=\"#FFFFFF\">\n" + |
| " <p><b>" + displayName + |
| "<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_=" + localeStr + "\">Demo</a>, " + |
| "<a href=\"../../comparison_charts.html\">Cover Page</a>, " + |
| "<a href=\"./index.html\">Index</a>, " + |
| "<a href=\"../collation/" + localeStr + ".html\">Collation</a> " + |
| "</b></p>\n" + |
| " <table>\n"); |
| } else { |
| writer.print("<html>\n" + |
| " <head>\n" + |
| " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" + |
| " <title>Draft/Alt: " + localeStr + "</title>\n" + |
| " </head>\n" + |
| " <style>\n" + |
| " <!--\n" + |
| " table { border-spacing: 0; border-collapse: collapse; \n" + |
| " border: 1px solid black }\n" + |
| " td, th { border-spacing: 0; border-collapse: collapse; color: black; \n" + |
| " vertical-align: top; border: 1px solid black }\n" + |
| " -->\n" + |
| " </style>" + |
| " <body bgcolor=\"#FFFFFF\">\n" + |
| " <p><b>" + displayName + |
| "<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_=" + localeStr + "\">Demo</a>, " + |
| "<a href=\"./index.html\">Main and About</a>, " + |
| "</b></p>\n"); |
| if ((ourCvsVersion != null) && (ourCvsVersion.length() > 0)) { |
| writer.println("<h3><tt>" + LDMLUtilities.getCVSLink(localeStr) + localeStr + ".xml</a> version " + |
| LDMLUtilities.getCVSLink(localeStr, ourCvsVersion) + ourCvsVersion + "</a></tt></h3>"); |
| } |
| writer.print(" <table>\n"); |
| } |
| |
| // PN added |
| if (((m_iOptions & OPT_DIFF) != 0) |
| || ((m_iOptions & OPT_DIFF_REF_COMMON) != 0)) |
| { |
| printTableHeaderForDifferences(writer); |
| } |
| else |
| { |
| printTableHeader(writer); |
| } |
| |
| // walk down the compare map and print the data |
| for (Object obj : compareMap.keySet()) { |
| CompareElement element; |
| if (obj != null) { |
| Object value = compareMap.get(obj); |
| if (value instanceof CompareElement) { |
| element = (CompareElement) value; |
| } else { |
| throw new RuntimeException( |
| "The object stored in the compare map is not an instance of CompareElement"); |
| } |
| // PN added |
| if ((m_iOptions & OPT_DIFF) != 0) |
| { |
| printDifferentValues(element, writer); // only print differences |
| } |
| else if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| { |
| printDifferentValuesWithRef(element, writer); |
| } |
| else |
| { |
| printValue(element, writer); |
| } |
| } else { |
| throw new RuntimeException("No objects stored in the compare map!"); |
| } |
| |
| } |
| writer.print(" </table>\n"); |
| |
| if (m_Vetting) { |
| if (m_Messages.length() > 0) { |
| writer.print("<table bgcolor=\"#FFBBBB\" border=3><tr><th>Warnings (please see source LDML)</th></tr>" + |
| "<tr><td>" + m_Messages + "</td></tr></table><p/><p/>\n"); |
| } |
| writer.print("<i>Interim page - subject to change</i> (<a href=\"./index.html\">Help</a>)<br/>"); |
| } |
| |
| writer.print(" <p>Created on: " + cal.getTime() + "</p>\n" + |
| " </body>\n" + |
| "</html>\n"); |
| writer.flush(); |
| |
| writer.flush(); |
| } |
| |
| private Document getFullyResolvedLocale(String localeName, String fileName) { |
| // here we assume that "_" is the delimiter |
| int index = fileName.lastIndexOf(File.separatorChar); |
| String sourceDir = fileName.substring(0, index + 1); |
| String locale = fileName.substring(index + 1, fileName.lastIndexOf(".")); |
| System.out.println("INFO: Creating fully resolved tree for : " + fileName); |
| |
| Document doc = LDMLUtilities.getFullyResolvedLDML(sourceDir, locale, true, true, true, true); |
| /* |
| * debugging code |
| * |
| * try{ |
| * OutputStreamWriter writer = new OutputStreamWriter(new |
| * FileOutputStream(destFolder+File.separator+localeName+"_debug.xml"),encoding); |
| * LDMLUtilities.printDOMTree(doc,new PrintWriter(writer)); |
| * writer.flush(); |
| * }catch( Exception e){ |
| * //throw the exception away .. this is for debugging |
| * } |
| */ |
| return doc; |
| } |
| |
| private boolean addToCompareMap(String fileName, String key) |
| { |
| // parse the test doc only if gold doc was parsed OK |
| Document testDoc = getFullyResolvedLocale(key, fileName); |
| requested.put(key, ""); |
| if (null == testDoc) |
| { |
| doesNotExist.put(key, ""); |
| return false; |
| } |
| return extractMergeData(testDoc, key, false); |
| |
| } |
| |
| private Document getParsedLocale(String localeName, String fileName) { |
| // here we assume that "_" is the delimiter |
| System.out.println("INFO: Parsing " + fileName); |
| Document doc = LDMLUtilities.parse(fileName, true); // ? |
| |
| return doc; |
| } |
| |
| private boolean addVettable(String fileName, String key) |
| { |
| // parse the test doc only if gold doc was parsed OK |
| Document testDoc = getParsedLocale(key, fileName); |
| requested.put(key, ""); |
| if (null == testDoc) |
| { |
| doesNotExist.put(key, ""); |
| return false; |
| } |
| return extractMergeData(testDoc, key, false); |
| |
| } |
| |
| private boolean comparePatterns(String pat1, String pat2) { |
| // TODO: just return for now .. this is useful only |
| // when comparing data from toronto |
| try { |
| double args1 = 10000000000.00; |
| double args2 = -10000000000.00; |
| |
| DecimalFormat fmt = new DecimalFormat(); |
| |
| fmt.applyPattern(pat1); |
| String s1 = fmt.format(args1); |
| String s3 = fmt.format(args2); |
| fmt.applyPattern(pat2); |
| String s2 = fmt.format(args1); |
| String s4 = fmt.format(args2); |
| if (s1.equals(s2) && s3.equals(s4)) { |
| return true; |
| } |
| } catch (Exception e) { |
| // throw away the exception |
| } |
| return false; |
| |
| // return true; |
| } |
| |
| private String trim(String source) { |
| char[] src = source.toCharArray(); |
| char[] dest = new char[src.length]; |
| |
| int start = 0; |
| while (start < (src.length) && (UCharacter.isWhitespace(src[start]))) { |
| start++; |
| } |
| int stop = src.length - 1; |
| while (stop > 0 && (UCharacter.isWhitespace(src[stop]) || (src[stop] == 0xA0))) { |
| stop--; |
| } |
| if (stop != -1 && start != src.length) { |
| System.arraycopy(src, start, dest, 0, (stop - start) + 1); |
| return new String(dest, 0, (stop - start) + 1); |
| } else { |
| return new String(); |
| } |
| |
| } |
| |
| private final void addElement(String childNode, String parentNode, String id, String index, |
| String platformValue, String platformName) { |
| addElement(childNode, parentNode, id, index, platformValue, platformName, null); |
| } |
| |
| private void addElement(String childNode, String parentNode, String id, String index, |
| String platformValue, String platformName, String referenceUrl) { |
| m_totalCount++; |
| Object obj = compareMap.get(id); |
| CompareElement element; |
| if (obj == null) { |
| element = new CompareElement(); |
| // initialize the values |
| element.index = index; |
| element.parentNode = parentNode; |
| element.node = childNode; |
| element.referenceUrl = referenceUrl; |
| // add the element to the compare map |
| compareMap.put(id, element); |
| } else { |
| if (obj instanceof CompareElement) { |
| element = (CompareElement) obj; |
| } else { |
| throw new RuntimeException("The object stored in the compareMap is not a CompareElement object!"); |
| } |
| } |
| |
| if ((!element.index.equals(index)) || |
| (!element.node.equals(childNode)) || |
| (!element.parentNode.equals(parentNode))) { |
| throw new RuntimeException("The retrieved object is not the same as the one trying to be saved, id is " |
| + id); |
| } |
| |
| element.platformData.put(platformName, platformValue); |
| } |
| |
| private boolean childrenAreElements(Node node) { |
| NodeList list = node.getChildNodes(); |
| for (int i = 0; i < list.getLength(); i++) { |
| if (list.item(i).getNodeType() == Node.ELEMENT_NODE) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private String getTag(String childNodeName, String index) { |
| |
| // for months make index a,b,c,d etc |
| if (childNodeName.indexOf("month") > -1) { |
| int i = Integer.parseInt(index); |
| StringBuffer temp = new StringBuffer(); |
| temp.append((char) ('a' + i)); |
| return temp.toString(); |
| } else if (childNodeName.indexOf("day") > -1) { |
| if (index.equals("sun")) { |
| return "a"; |
| } else if (index.equals("mon")) { |
| return "b"; |
| } else if (index.equals("tue")) { |
| return "c"; |
| } else if (index.equals("wed")) { |
| return "d"; |
| } else if (index.equals("thu")) { |
| return "e"; |
| } else if (index.equals("fri")) { |
| return "f"; |
| } else if (index.equals("sat")) { |
| return "g"; |
| } |
| } else { |
| return index; |
| } |
| return ""; |
| } |
| |
| private boolean extractMergeData(Node node, String key, boolean parentDraft) { |
| Node childOfSource; |
| for (childOfSource = node.getFirstChild(); childOfSource != null; childOfSource = childOfSource |
| .getNextSibling()) { |
| if (childOfSource.getNodeType() != Node.ELEMENT_NODE) { |
| continue; |
| } |
| String altText = null; |
| // String altReferenceUrl = null; |
| Node altForChild = null; |
| boolean subDraft = parentDraft; |
| String childOfSourceName = childOfSource.getNodeName(); |
| // Ignore collation and special tags |
| if (childOfSourceName.equals("collations") || childOfSource.equals("special") |
| || childOfSourceName.indexOf(":") > -1) { |
| continue; |
| } |
| |
| if (m_Vetting && LDMLUtilities.isNodeDraft(childOfSource)) { |
| if (!subDraft) { |
| subDraft = true; |
| } |
| } |
| String referenceUrl = null; |
| if (m_Vetting) { |
| referenceUrl = LDMLUtilities.getAttributeValue(childOfSource, LDMLConstants.REFERENCES); |
| if ((referenceUrl != null) && (referenceUrl.length() == 0)) { |
| referenceUrl = null; |
| } |
| } |
| |
| if (m_Vetting) { /* Should this be always checked? */ |
| String alt = LDMLUtilities.getAttributeValue(childOfSource, LDMLConstants.ALT); |
| if (alt != null) { |
| if (alt.equals(LDMLConstants.PROPOSED)) { |
| if (subDraft == false) { |
| throw new IllegalArgumentException("***** ERROR Proposed but not draft? " |
| + childOfSource.toString()); |
| // NOTREACHED |
| } |
| altForChild = LDMLUtilities.getNonAltNodeLike(node, childOfSource); |
| if (altForChild == null) { |
| System.out.println("WARNING: can't find a node like this one: " + childOfSource.toString() |
| + " - consider removing the alt=\"proposed\" attribute."); |
| alt = null; |
| } |
| // altReferenceUrl = LDMLUtilities.getAttributeValue(altForChild, LDMLConstants.REFERENCES); |
| // if((altReferenceUrl!=null)&&(altReferenceUrl.length()==0)) { |
| // altReferenceUrl = null; |
| // } |
| } else if (subDraft) { /* don't care about nondraft */ |
| String type = LDMLUtilities.getAttributeValue(childOfSource, LDMLConstants.TYPE); |
| if (type == null) { |
| type = ""; |
| } |
| m_Messages = m_Messages + " <br> UNKNOWN alt type '" + alt + "' for " + |
| node.getNodeName() + "/" + childOfSourceName + "/" + type; |
| System.err.println("Warning: unknown alt type '" + alt + "' - *IGNORING*. " |
| + childOfSource.toString()); |
| continue; |
| } |
| } |
| } |
| |
| if (childrenAreElements(childOfSource) == false) { |
| NamedNodeMap attr = childOfSource.getAttributes(); |
| Node typeNode = attr.getNamedItem("type"); |
| Node altNode = attr.getNamedItem("alt"); |
| String index = ""; |
| if (typeNode != null) { |
| /* |
| * if(childOfSource.getNodeName().equals("era")&&!key.equals("common")){ |
| * //remap type for comparison purpose |
| * // TODO remove this hack |
| * int j = Integer.parseInt(typeNode.getNodeValue()); |
| * if(j>0){ |
| * j--; |
| * } |
| * typeNode.setNodeValue(Integer.toString(j)); |
| * } |
| */ |
| String temp = typeNode.getNodeValue(); |
| |
| if (!temp.equals("standard")) { |
| index = temp; |
| } |
| |
| } |
| String alt = null; |
| if (altNode != null) { |
| alt = altNode.getNodeValue(); |
| } |
| if (m_Vetting) { // TODO: all? |
| Node keyNode = attr.getNamedItem("key"); |
| if (keyNode != null) { |
| String temp = keyNode.getNodeValue(); |
| index = index + " (" + temp + ")"; |
| } |
| } |
| String nodeValue = ""; |
| Node valueNode = childOfSource.getFirstChild(); |
| if (valueNode != null) { |
| String temp = trim(valueNode.getNodeValue()); |
| if (!temp.equals("standard")) { |
| nodeValue = temp; |
| } |
| } |
| if (altForChild != null) { |
| Node valueNode2 = altForChild.getFirstChild(); |
| if (valueNode2 != null) { |
| String temp = trim(valueNode2.getNodeValue()); |
| if (!temp.equals("standard")) { |
| altText = temp; |
| } else { |
| altText = "??? alt=standard"; |
| } |
| } else { |
| altText = "??? alt has no value"; |
| } |
| } |
| Node parentNode = childOfSource.getParentNode(); |
| String parentNodeName = trim(parentNode.getNodeName()); |
| String childNodeName = trim(childOfSource.getNodeName()); |
| Node grandParentNode = childOfSource.getParentNode().getParentNode(); |
| String grandParentNodeName = grandParentNode.getNodeName(); |
| NamedNodeMap parentAttrib = parentNode.getAttributes(); |
| String type = ""; |
| if (parentAttrib != null) { |
| Node mytypeNode = parentAttrib.getNamedItem("type"); |
| if (mytypeNode != null) { |
| String mytype = mytypeNode.getNodeValue(); |
| if (!mytype.equals("standard")) { |
| if (!parentNodeName.equals("calendar")) { |
| type = mytype; |
| } else { |
| parentNodeName = mytype; |
| } |
| } |
| } |
| |
| } |
| if (grandParentNodeName.equals("eras")) { |
| Node calendar = grandParentNode.getParentNode(); |
| NamedNodeMap gpa = calendar.getAttributes(); |
| Node gptNode = gpa.getNamedItem("type"); |
| if (gptNode != null) { |
| String gptType = gptNode.getNodeValue(); |
| if (!gptType.equals("standard")) { |
| grandParentNodeName = gptType; |
| } |
| } |
| parentNodeName = grandParentNodeName + "\u200b_" + parentNodeName; |
| } |
| if (grandParentNodeName.equals("calendar")) { |
| NamedNodeMap gpa = grandParentNode.getAttributes(); |
| Node gptNode = gpa.getNamedItem("type"); |
| if (gptNode != null) { |
| String gptType = gptNode.getNodeValue(); |
| if (!gptType.equals("standard")) { |
| grandParentNodeName = gptType; |
| } |
| } |
| parentNodeName = grandParentNodeName + "\u200b_" + parentNodeName; |
| } |
| if (grandParentNodeName.equals("monthContext") || grandParentNodeName.equals("dayContext") || |
| grandParentNodeName.equals("dateFormatLength") || grandParentNodeName.equals("timeFormatLength") || |
| grandParentNodeName.equals("dateTimeFormatLength")) { |
| |
| Node calendar = grandParentNode.getParentNode().getParentNode(); |
| NamedNodeMap ggpa = calendar.getAttributes(); |
| Node ggptNode = ggpa.getNamedItem("type"); |
| if (ggptNode != null) { |
| String ggptType = ggptNode.getNodeValue(); |
| if (!ggptType.equals("standard")) { |
| grandParentNodeName = ggptType; |
| parentNodeName = ggptType + "\u200b_" + parentNodeName; |
| } |
| } |
| NamedNodeMap gpa = grandParentNode.getAttributes(); |
| Node gptNode = gpa.getNamedItem("type"); |
| if (gptNode != null) { |
| String gptType = gptNode.getNodeValue(); |
| if (!gptType.equals("standard")) { |
| parentNodeName = parentNodeName + "\u200b_" + gptType; |
| } |
| } |
| NamedNodeMap pa = parentNode.getAttributes(); |
| Node ptNode = pa.getNamedItem("type"); |
| if (ptNode != null) { |
| String ptType = ptNode.getNodeValue(); |
| if (!ptType.equals("standard")) { |
| parentNodeName = parentNodeName + "\u200b_" + ptType; |
| } |
| } |
| |
| } |
| if (childNodeName.equals("pattern") || grandParentNodeName.equals("zone")) { |
| if (parentNodeName.indexOf("date") == -1 && parentNodeName.indexOf("time") == -1) { |
| NamedNodeMap at = grandParentNode.getAttributes(); |
| Node mytypeNode = at.getNamedItem("type"); |
| if (mytypeNode != null) { |
| String mytype = mytypeNode.getNodeValue(); |
| if (!mytype.equals("standard")) { |
| if (type.equals("")) { |
| type = mytype; |
| } else { |
| type = type + "\u200b_" + mytype; |
| } |
| |
| } |
| } |
| } |
| } |
| if (grandParentNodeName.equals("special") || parentNodeName.equals("special") |
| || childNodeName.equals("special") |
| || grandParentNodeName.indexOf(":") > 0) { |
| continue; |
| } |
| if (!nodeValue.equals("") && |
| !childOfSource.getNodeName().equals("version")) { |
| |
| // for country codes and language codes |
| // replace the deprecated codes with the latest ones |
| if (childNodeName.equals("language")) { |
| String temp = (String) deprecatedLanguageCodes.get(index); |
| if (temp != null) { |
| index = temp; |
| } |
| } else if (childNodeName.equals("territory")) { |
| String temp = (String) deprecatedCountryCodes.get(index); |
| if (temp != null) { |
| index = temp; |
| } |
| if (index != null && alt != null) { |
| index = index + "_" + alt; |
| } |
| } |
| String id = ""; |
| if (!type.equals("")) { |
| id = parentNodeName + "_" + childNodeName + "_" + type + "_" + getTag(childNodeName, index) |
| + "_" + grandParentNodeName; |
| } else { |
| id = parentNodeName + "_" + childNodeName + "_" + getTag(childNodeName, index) + "_" |
| + grandParentNodeName; |
| } |
| if (!index.equals("")) { |
| if (!index.equals(nodeValue) && !index.equals("Fallback")) { |
| if (!m_Vetting || subDraft) { |
| addElement(childNodeName, parentNodeName, id, index, nodeValue, key, referenceUrl); |
| if (altText != null) { |
| addElement(childNodeName, parentNodeName, id, index, altText, "ALT", null /* altReferenceUrl */); |
| } |
| } |
| } |
| } else { |
| if (!type.equals(nodeValue) && !type.equals("Fallback")) { |
| if (!m_Vetting || subDraft) { |
| addElement(childNodeName, parentNodeName, id, type, nodeValue, key, referenceUrl); |
| if (altText != null) { |
| addElement(childNodeName, parentNodeName, id, index, altText, "ALT", null /* altReferenceUrl */); |
| } |
| } |
| } |
| } |
| } |
| if (attr.getLength() > 0 && typeNode == null) { // TODO: make this a fcn |
| // add an element for each attribute different for each attribute |
| if (!m_Vetting || subDraft) { |
| for (int i = 0; i < attr.getLength(); i++) { |
| Node item = attr.item(i); |
| String attrName = item.getNodeName(); |
| if (attrName.equals("type")) { |
| continue; |
| } |
| if (attrName.equals("alt")) { |
| continue; |
| } |
| if (attrName.equals("draft")) { |
| continue; |
| } |
| if (grandParentNodeName.equals("zone")) { |
| parentNodeName = grandParentNodeName + "\u200b_" + parentNodeName; |
| } |
| String id = grandParentNodeName + "_" + parentNodeName + "_" + childNodeName + "_" + type |
| + "_" + attrName; |
| String subNodeValue = item.getNodeValue(); |
| if (altForChild != null) { |
| System.err.println(parentNodeName + "/" + childNodeName + " alt?? : " + altText); |
| throw new IllegalArgumentException("UNKNOWN ALT SUBTAG + " + parentNodeName + "/" |
| + childNodeName + " alt?? : " + altText + " not " + subNodeValue); |
| } |
| if (!index.equals("")) { |
| addElement(childNodeName, parentNodeName, id, index, subNodeValue, key); |
| } else if (!type.equals("")) { |
| addElement(childNodeName, parentNodeName, id, type, subNodeValue, key); |
| } else { |
| if (!attrName.equals("draft")) { |
| addElement(childNodeName, parentNodeName, id, attrName, subNodeValue, key); |
| } |
| } |
| } |
| } |
| } |
| } else { |
| // the element has more children .. recurse to pick them all |
| extractMergeData(childOfSource, key, subDraft); |
| } |
| } |
| return true; |
| } |
| |
| // ***************************************************************************************************** |
| // method writes the differences between xml files all to one HTML file |
| // added by PN |
| // ***************************************************************************************************** |
| private void doBulkComparison() |
| { |
| // get the output file name |
| String fileName = destFolder + "/" + "Bulk.html"; |
| System.out.println("INFO: Creating file named: " + fileName); |
| String fileName_summary = destFolder + "/" + "Bulk_summary.html"; |
| System.out.println("INFO: Creating file named: " + fileName_summary); |
| |
| try |
| { |
| OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(fileName), encoding); |
| OutputStreamWriter os_summary = new OutputStreamWriter(new FileOutputStream(fileName_summary), encoding); |
| |
| // write the beginning of HTML page |
| PrintWriter writer = new PrintWriter(os); |
| PrintWriter writer_summary = new PrintWriter(os_summary); |
| printHTMLStart(writer); |
| printInfo(writer); |
| printHTMLStart(writer_summary); |
| |
| // not all platforms have files for all locales so first build a locale superset |
| // loop thru locale files from each folder, each folder contains a certain number of locales |
| // build a HashSet superset |
| File localeDir = null; |
| String[] fileList; |
| Set<String> localeTreeSet = new TreeSet<String>(); // use TreeSet for locales in alphabetical order |
| for (int i = 0; i < m_PlatformFolderVect.size(); i++) |
| { |
| localeDir = new File((String) m_PlatformFolderVect.elementAt(i)); |
| fileList = localeDir.list(); |
| for (int j = 0; j < fileList.length; j++) |
| { |
| if (fileList[j].endsWith(".xml")) |
| { |
| // need to exclude root.xml and supplementalData.xml |
| if ((fileList[j].compareTo("root.xml") == 0) |
| || (fileList[j].compareTo("supplementalData.xml") == 0)) |
| continue; |
| |
| // exclude common if -diff_ref_common option chosen by user |
| // as common will only be shown as a reference if there are differences between locales for |
| // other platforms |
| if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| { |
| String platform = (String) m_PlatformVect.elementAt(i); |
| if (platform.compareTo(COMMON) == 0) |
| continue; |
| } |
| |
| // entries are only added to TreeSets if not already there |
| localeTreeSet.add(fileList[j]); |
| // System.out.println (j + " adding " + fileList[j] + " to super set for platform " + (String) |
| // m_PlatformFolderVect.elementAt(i) ); |
| } |
| } |
| } |
| |
| // System.out.println(" size of locale set = " + localeTreeSet.size()); |
| // System.out.println(" number of platforms = " + m_PlatformFolderVect.size() + "(" + m_PlatformVect.size() |
| // + ")"); |
| |
| // loop thru all locales |
| Object[] localeArray = localeTreeSet.toArray(); |
| int i = 0; |
| for (i = 0; i < localeArray.length; i++) |
| { |
| String platforms_with_this_locale = ""; |
| |
| String localeFile = (String) localeArray[i]; // locale file name without path |
| // class member localeStr used for writing to html |
| localeStr = localeFile.substring(0, localeFile.indexOf('.')); |
| System.out.println("INFO: locale : " + localeStr); |
| |
| // add entry to CompareMap for any platforms having an xml file for the locale in question |
| for (int j = 0; j < m_PlatformFolderVect.size(); j++) |
| { |
| localeDir = new File((String) m_PlatformFolderVect.elementAt(j)); |
| fileList = localeDir.list(); |
| for (int k = 0; k < fileList.length; k++) |
| { |
| if (fileList[k].compareTo(localeFile) == 0) // test for 2 matching xml filenames |
| { |
| String key = (String) m_PlatformVect.elementAt(j); // should use hashtable to link |
| // m_PlatformVect and |
| // m_PlatformFolderVect |
| String xmlFileName = localeDir + "/" + localeArray[i]; |
| // System.out.println(i + " " + j + " " + k + " adding " + xmlFileName + |
| // " to compareMap at key " + key); |
| addToCompareMap(xmlFileName, key); |
| |
| if (!(((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| && (key.compareTo(COMMON) == 0))) |
| { |
| platforms_with_this_locale += key; |
| platforms_with_this_locale += ", "; |
| } |
| } |
| } |
| } |
| // System.out.println("size of compareMap " + compareMap.size()); |
| |
| // print locale info and table header for this locale |
| printHTMLLocaleStart(writer, i, platforms_with_this_locale); |
| printTableHeaderForDifferences(writer); |
| |
| // now do the comparison for a specific locale |
| walkCompareMap(writer, localeStr, platforms_with_this_locale); |
| |
| // clear the compareMap before starting next locale |
| compareMap.clear(); |
| |
| // finish html table |
| printHTMLLocaleEnd(writer); |
| |
| } // end outer for loop on locales |
| |
| // print summary data to html summary file |
| printLocaleSummaryToHTML(writer_summary); |
| printAccumulatedResultsToHTML(writer_summary); |
| |
| printHTMLEnd(writer, i); |
| printHTMLEnd(writer_summary, i); |
| } catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| System.out.println("INFO: Finished writing file named: " + fileName); |
| System.out.println("INFO: Finished writing file named: " + fileName_summary); |
| } |
| |
| // added by PN |
| private void printHTMLStart(PrintWriter writer) |
| { |
| // System.out.println("INFO: Creating the comparison chart "); |
| |
| writer.print("<html>\n" + |
| " <head>\n" + |
| " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" + |
| " </head>\n" + |
| " <style>\n" + |
| " <!--\n" + |
| " table { border-spacing: 0; border-collapse: collapse; width:100%; \n" + |
| " border: 1px solid black }\n" + |
| " td, th { border-spacing: 0; border-collapse: collapse; color: black; \n" + |
| " vertical-align: top; border: 1px solid black }\n" + |
| " -->\n" + |
| " </style>" + |
| " <body bgcolor=\"#FFFFFF\"> \n" + |
| " <p><b>LOCALE DATA AUDIT</b></p>"); |
| |
| writer.print(" <p>Created on: " + cal.getTime() + "</p>\n"); |
| } |
| |
| private void printInfo(PrintWriter writer) |
| { |
| if (((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| || ((m_iOptions & OPT_DIFF) != 0)) |
| { |
| writer |
| .print(" <p>locale elements where there is a difference between at least two platforms are shown. \n" |
| + |
| "If a locale element is the same across all platforms it is not shown </p>"); |
| } |
| |
| if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| writer |
| .print("<p> Common data is shown for reference purposes only and is not part of the comparison</p>\n"); |
| |
| } |
| |
| // added by PN |
| private void printHTMLEnd(PrintWriter writer, int iTotalNumLocales) |
| { |
| writer.print("<p> </p>"); |
| writer.print("<p> </p>"); |
| writer.print(" <p><b>SUMMARY : </b></p>"); |
| String platforms = ""; |
| for (int i = 0; i < m_PlatformVect.size(); i++) |
| { |
| if (((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| && (m_PlatformVect.elementAt(i).equals(COMMON))) |
| { |
| continue; |
| } |
| platforms += m_PlatformVect.elementAt(i); |
| platforms += ", "; |
| } |
| |
| writer.print(" <p><b>Platforms compared : " + platforms + "</b></p>"); |
| writer |
| .print(" <p><b>Total Number of locales audited : " |
| + iTotalNumLocales |
| + "</b></p>" |
| + |
| " <p><b>Total Number of conflicting locale data across all locales : " |
| + serialNumber |
| + "</b></p>" |
| + |
| " <p><b>Number of locale elements where a conflict was found for at least one locale : " |
| + m_iTotalConflictingElements |
| + "</b></p>" |
| + |
| " <p><b>Number of locale elements where no conflicts were found for any locale having this element : " |
| + m_iTotalNonConflictingElements + "</b></p>" + |
| " </body>\n" + |
| "</html>\n"); |
| writer.flush(); |
| |
| writer.flush(); |
| } |
| |
| // added by PN |
| private void printHTMLLocaleStart(PrintWriter writer, int iLocaleCounter, String platforms_with_this_locale) |
| { |
| ULocale locale = new ULocale(localeStr); |
| String displayLang = locale.getDisplayLanguage(); |
| String dispCountry = locale.getDisplayCountry(); |
| String dispVariant = locale.getDisplayVariant(); |
| String displayName = localeStr + " (" + displayLang + "_" + dispCountry; |
| if (dispVariant.length() > 0) |
| { |
| displayName += "_" + dispVariant + ") "; |
| } else |
| { |
| displayName += ") "; |
| } |
| |
| writer.print( |
| " <p><b>" + iLocaleCounter + " " + displayName + |
| // "<a href=\"http://oss.software.ibm.com/cgi-bin/icu/lx/en/?_="+localeStr+"\">Demo</a>, "+ |
| // "<a href=\"../comparison_charts.html\">Cover Page</a>, "+ |
| // "<a href=\"./index.html\">Index</a>, "+ |
| // "<a href=\"../collation_diff/"+localeStr+"_collation.html\">Collation</a> "+ |
| "</b>" + |
| "<b> platforms with this locale : " + platforms_with_this_locale + "</b></p>\n" + |
| " <table>\n"); |
| } |
| |
| // added by PN |
| private void printHTMLLocaleEnd(PrintWriter writer) |
| { |
| writer.print(" </table>\n"); |
| } |
| |
| // added by PN |
| private void walkCompareMap(PrintWriter writer, String locale, String platforms) |
| { |
| SummaryData summData = new SummaryData(); |
| |
| // walk down the compare map and print the data |
| Iterator<String> iter = compareMap.keySet().iterator(); |
| while (iter.hasNext()) |
| { |
| Object obj = iter.next(); |
| CompareElement element; |
| if (obj != null) |
| { |
| Object value = compareMap.get(obj); |
| if (value instanceof CompareElement) |
| { |
| element = (CompareElement) value; |
| } else |
| { |
| throw new RuntimeException( |
| "The object stored in the compare map is not an instance of CompareElement"); |
| } |
| |
| boolean bIsEqual = true; |
| if ((m_iOptions & OPT_DIFF) != 0) |
| { |
| bIsEqual = printDifferentValues(element, writer); |
| AddToAccumulatedResultsMap((String) obj, element, localeStr, bIsEqual); |
| } |
| else if ((m_iOptions & OPT_DIFF_REF_COMMON) != 0) |
| { |
| bIsEqual = printDifferentValuesWithRef(element, writer); |
| AddToAccumulatedResultsMap((String) obj, element, localeStr, bIsEqual); |
| } |
| else |
| { |
| printValue(element, writer); |
| } |
| |
| if (bIsEqual == false) |
| summData.m_iNumConflictingElements++; |
| |
| } else |
| { |
| throw new RuntimeException("No objects stored in the compare map!"); |
| } |
| } |
| summData.m_szPlatforms = platforms; |
| m_LocaleSummaryDataMap.put(locale, summData); |
| |
| } |
| |
| // PN added |
| private void AddToAccumulatedResultsMap(String id, CompareElement element, String locale, boolean bIsEqual) |
| { |
| if (element == null) |
| return; |
| |
| AccumulatedResults ad = m_AccumulatedResultsMap.get(id); |
| if (ad == null) |
| { |
| // System.out.println("id = " + id); |
| |
| // add a new entry, there's none there with this key |
| ad = new AccumulatedResults(); |
| ad.index = element.index; |
| ad.node = element.node; |
| ad.parentNode = element.parentNode; |
| if (bIsEqual == false) |
| ad.localeVectDiff.add(locale); |
| else |
| ad.localeVectSame.add(locale); |
| m_AccumulatedResultsMap.put(id, ad); |
| } |
| else |
| { |
| if ((!ad.index.equals(element.index)) || |
| (!ad.node.equals(element.node)) || |
| (!ad.parentNode.equals(element.parentNode))) // || |
| // (!ad.type.equals(element.type))) type can be null so don't ceck its value |
| { |
| throw new RuntimeException( |
| "The retrieved AccumulatedResults is not the same as the one trying to be saved - " + id); |
| } |
| else |
| { |
| if (bIsEqual == false) |
| ad.localeVectDiff.add(locale); |
| else |
| ad.localeVectSame.add(locale); |
| } |
| } |
| } |
| |
| private void printAccumulatedResultsToHTML(PrintWriter writer) |
| { |
| writer.print("<p> </p>"); |
| writer.print("<p> </p>"); |
| writer |
| .print("<p><b>Table below shows the number of locales where conflicts did and didn't occur on a per locale element basis"); |
| writer |
| .print(" (For brevity, locale elements where no conflicts were detected for any locale are not shown) </b></p>"); |
| writer.print("<p></p>"); |
| writer.print(" <table width=\"700\">\n"); |
| writer.print(" <tr>\n" + |
| " <th width=5%>N.</th>\n" + |
| " <th width=10%>ParentNode</th>\n" + |
| " <th width=10%>Name</th>\n" + |
| " <th width=10%>ID</th>\n" + |
| " <th width=10%># of non-conflicting locales</th>" + |
| " <th width=10%># of conflicting locales</th>" + |
| " <th width=45%>Locales where conflicts were found</th>" + |
| " </tr>\n"); |
| |
| // walk down the cm_AccumulateDifferenceMap and print the data |
| Iterator<String> iter = m_AccumulatedResultsMap.keySet().iterator(); |
| // System.out.println ("size = " + m_AccumulateDifferenceMap.size()); |
| |
| int iCounter = 0; |
| while (iter.hasNext()) |
| { |
| Object obj = iter.next(); |
| AccumulatedResults ad; |
| if (obj != null) |
| { |
| Object value = m_AccumulatedResultsMap.get(obj); |
| if (value instanceof AccumulatedResults) |
| { |
| ad = (AccumulatedResults) value; |
| } else |
| { |
| throw new RuntimeException( |
| "The object stored in the AccumulateDifferencesMap is not an instance of AccumulateDifferences"); |
| } |
| |
| // only print locale elements where differences occurred |
| if (ad.localeVectDiff.size() > 0) |
| { |
| m_iTotalConflictingElements++; |
| writer.print(" <tr>\n"); |
| writer.print(" <td>" + (iCounter++) + "</td>\n"); |
| writer.print(" <td>" + ad.parentNode + "</td>\n"); |
| writer.print(" <td>" + ad.node + "</td>\n"); |
| writer.print(" <td>" + ad.index + "</td>\n"); |
| writer.print(" <td>" + ad.localeVectSame.size() + "</td>\n"); |
| writer.print(" <td>" + ad.localeVectDiff.size() + "</td>\n"); |
| String locales = ""; |
| for (int i = 0; i < ad.localeVectDiff.size(); i++) |
| { |
| locales += ad.localeVectDiff.elementAt(i); |
| locales += ", "; |
| } |
| writer.print(" <td>" + locales + "</td>\n"); |
| writer.print(" </tr>\n"); |
| } |
| else |
| { |
| m_iTotalNonConflictingElements++; |
| } |
| |
| } else |
| { |
| throw new RuntimeException("No objects stored in the AccumulateDifferencesMap!"); |
| } |
| } |
| |
| writer.print(" </table>\n"); |
| |
| } |
| |
| private void printLocaleSummaryToHTML(PrintWriter writer) |
| { |
| writer.print("<p> </p>"); |
| writer.print("<p> </p>"); |
| writer.print("<p><b>Table below shows the number of conflicting elements on a per locale basis\n</b></p>"); |
| writer.print("<p></p>"); |
| writer.print(" <table width=\"700\">\n"); |
| writer.print(" <tr>\n" + |
| " <th width=5%>N.</th>\n" + |
| " <th width=20%>Locale</th>\n" + |
| " <th width=40%>Platforms With This Locale</th>\n" + |
| " <th width=35%># of elements where a conflict was found</th>\n" + |
| " </tr>\n"); |
| |
| // walk down the cm_AccumulateDifferenceMap and print the data |
| Iterator<String> iter = m_LocaleSummaryDataMap.keySet().iterator(); |
| int iCounter = 0; |
| while (iter.hasNext()) |
| { |
| Object obj = iter.next(); |
| SummaryData summData; |
| if (obj != null) |
| { |
| Object value = m_LocaleSummaryDataMap.get(obj); |
| if (value instanceof SummaryData) |
| { |
| summData = (SummaryData) value; |
| } else |
| { |
| throw new RuntimeException( |
| "The object stored in the AccumulateDifferencesMap is not an instance of AccumulateDifferences"); |
| } |
| |
| writer.print(" <tr>\n"); |
| writer.print(" <td>" + (iCounter++) + "</td>\n"); |
| writer.print(" <td>" + (String) obj + "</td>\n"); |
| writer.print(" <td>" + summData.m_szPlatforms + "</td>\n"); |
| writer.print(" <td>" + summData.m_iNumConflictingElements + "</td>\n"); |
| writer.print(" </tr>\n"); |
| } else |
| { |
| throw new RuntimeException("No objects stored in the AccumulateDifferencesMap!"); |
| } |
| } |
| |
| writer.print(" </table>\n"); |
| } |
| |
| private void getCVSVersion() |
| { |
| ourCvsVersion = LDMLUtilities.loadFileRevision(goldFileName); |
| } |
| |
| } // end of class definition/declaration |