1 package org.unicode.cldr.tool; 2 3 import com.google.common.base.Objects; 4 import com.google.common.collect.Sets; 5 import com.ibm.icu.util.Output; 6 import java.util.Map; 7 import java.util.Set; 8 import java.util.TreeSet; 9 import java.util.regex.Matcher; 10 import java.util.regex.Pattern; 11 import org.unicode.cldr.tool.Option.Options; 12 import org.unicode.cldr.tool.Option.Params; 13 import org.unicode.cldr.util.CLDRConfig; 14 import org.unicode.cldr.util.CLDRFile; 15 import org.unicode.cldr.util.CLDRPaths; 16 import org.unicode.cldr.util.Factory; 17 import org.unicode.cldr.util.SupplementalDataInfo; 18 import org.unicode.cldr.util.XPathParts; 19 20 public class CompareResolved { 21 private static final CLDRConfig CLDR_CONFIG = CLDRConfig.getInstance(); 22 private static final SupplementalDataInfo SUPPLEMENTAL_DATA_INFO = 23 CLDR_CONFIG.getSupplementalDataInfo(); 24 25 private enum MyOptions { 26 source( 27 new Params() 28 .setHelp("Set the source directory name. Only these files will be compared") 29 .setDefault(CLDRPaths.ARCHIVE_DIRECTORY + "cldr-42.0/common/main") 30 .setMatch(".*")), 31 compare( 32 new Params() 33 .setHelp("Set the comparison directory name.") 34 .setMatch(".*") 35 .setDefault(CLDRPaths.MAIN_DIRECTORY)), 36 fileFilter(new Params().setHelp("Filter files in source dir.").setMatch(".*")), 37 pathFilter(new Params().setHelp("Filter paths in each source file.").setMatch(".*")), 38 verbose(new Params().setMatch(null)), 39 ; 40 41 // BOILERPLATE TO COPY 42 final Option option; 43 MyOptions(Params params)44 private MyOptions(Params params) { 45 option = new Option(this, params); 46 } 47 48 private static Options myOptions = new Options(); 49 50 static { 51 for (MyOptions option : MyOptions.values()) { myOptions.add(option, option.option)52 myOptions.add(option, option.option); 53 } 54 } 55 parse(String[] args)56 private static Set<String> parse(String[] args) { 57 return myOptions.parse(MyOptions.values()[0], args, true); 58 } 59 } 60 main(String[] args)61 public static void main(String[] args) { 62 63 // get options 64 65 MyOptions.parse(args); 66 String sourceDir = MyOptions.source.option.getValue(); 67 String compareDir = MyOptions.compare.option.getValue(); 68 69 Matcher fileMatcher = null; 70 String pattern = MyOptions.fileFilter.option.getValue(); 71 if (pattern != null) { 72 fileMatcher = Pattern.compile(pattern).matcher(""); 73 } 74 Matcher pathMatcher = null; 75 pattern = MyOptions.pathFilter.option.getValue(); 76 if (pattern != null) { 77 pathMatcher = Pattern.compile(pattern).matcher(""); 78 } 79 80 boolean verbose = MyOptions.verbose.option.doesOccur(); 81 82 // set up factories 83 84 Factory sourceFactory = Factory.make(sourceDir, ".*"); 85 Factory compareFactory; 86 try { 87 compareFactory = Factory.make(compareDir, ".*"); 88 } catch (Exception e1) { 89 System.out.println(e1); 90 return; 91 } 92 93 System.out.println("## Comparing\t\tSource (S) dir\tCompare (C) dir"); 94 System.out.println("## Comparing\t\t" + sourceDir + "\t" + compareDir); 95 96 // don't currently use these, but might filter on these in the future 97 Output<String> sourcePathFound = new Output<>(); 98 Output<String> sourceLocaleFound = new Output<>(); 99 Output<String> comparePathFound = new Output<>(); 100 Output<String> compareLocaleFound = new Output<>(); 101 102 int filterCountAllLocales = 0; 103 int diffCountAllLocales = 0; 104 105 // cycle over locales 106 System.out.println( 107 "## Locale\tRequested Path\tResolved Value (S)\tResolved Value (C)\tFound Locale (S)\tFound Locale (C)\tFound Path (S)\tFound Path (C)"); 108 for (String localeID : sourceFactory.getAvailable()) { 109 if (fileMatcher != null && !fileMatcher.reset(localeID).find()) { 110 continue; 111 } 112 113 // create the CLDRFiles 114 115 CLDRFile sourceFile = sourceFactory.make(localeID, true); // resolved 116 CLDRFile compareFile; 117 try { 118 compareFile = compareFactory.make(localeID, true); // resolved 119 } catch (Exception e) { 120 System.out.println(localeID + " not available in " + compareDir); 121 continue; 122 } 123 124 // get the union of paths 125 126 Set<String> sortedPaths = new TreeSet<>(); // could sort by PathHeader also 127 sortedPaths.addAll(Sets.newTreeSet(sourceFile)); 128 sortedPaths.addAll(Sets.newTreeSet(compareFile)); 129 130 // cycle over the union of paths 131 int filterCount = 0; 132 int diffCount = 0; 133 134 for (String path : sortedPaths) { 135 if (pathMatcher != null && !pathMatcher.reset(path).find()) { 136 continue; 137 } 138 ++filterCount; 139 String sourceValue = 140 sourceFile.getStringValueWithBailey( 141 path, sourcePathFound, sourceLocaleFound); 142 String compareValue = 143 compareFile.getStringValueWithBailey( 144 path, comparePathFound, compareLocaleFound); 145 146 if (Objects.equal(sourceValue, compareValue)) { 147 continue; 148 } 149 150 final boolean verticalDiff = 151 !Objects.equal(sourceLocaleFound.value, compareLocaleFound.value); 152 final boolean horizontalDiff = 153 !Objects.equal(sourcePathFound.value, comparePathFound.value); 154 155 // // inheritance filters, if not null, follow it. 156 // if (onlyVertical != null) { 157 // if (verticalDiff != (onlyVertical == true)) { 158 // continue; 159 // } 160 // } 161 // if (onlyHorizontal != null) { 162 // if (horizontalDiff != (onlyHorizontal == true)) { 163 // continue; 164 // } 165 // } 166 167 // fell through, so record diff 168 169 ++diffCount; 170 System.out.println( 171 localeID 172 + "\t" 173 + path // 174 + "\t" 175 + sourceValue 176 + "\t" 177 + compareValue // 178 + "\t" 179 + sourceLocaleFound.value 180 + "\t" 181 + compareLocaleFound.value 182 + "\t" 183 + abbreviate(sourcePathFound.value, path) 184 + "\t" 185 + abbreviate(comparePathFound.value, path)); 186 } 187 if (verbose || diffCount != 0) { 188 System.out.println( 189 "# " 190 + localeID 191 + "\tfilteredCount:\t" 192 + filterCount 193 + "\tdiffCount:\t" 194 + diffCount); 195 } 196 filterCountAllLocales += filterCount; 197 diffCountAllLocales += diffCount; 198 } 199 if (verbose || diffCountAllLocales != 0) { 200 System.out.println( 201 "# " 202 + "ALL LOCALES" 203 + "\t#filteredCount:\t" 204 + filterCountAllLocales 205 + ", diffCountAllLocales: " 206 + diffCountAllLocales); 207 } 208 System.out.println("DONE"); 209 } 210 211 /* 212 * Abbreviate the pathToAbbreviate, replacing leading and trailing identical elements/attributes by … 213 */ abbreviate(String pathToAbbreviate, String referencePath)214 private static String abbreviate(String pathToAbbreviate, String referencePath) { 215 if (pathToAbbreviate.equals(referencePath)) { 216 return "…"; 217 } 218 XPathParts compare = XPathParts.getFrozenInstance(pathToAbbreviate); 219 XPathParts source = XPathParts.getFrozenInstance(referencePath); 220 final int cSize = compare.size(); 221 final int sSize = source.size(); 222 int min = Math.min(cSize, sSize); 223 224 int initialSame = 0; 225 for (; initialSame < min; ++initialSame) { 226 String cElement = compare.getElement(initialSame); 227 String sElement = source.getElement(initialSame); 228 Map<String, String> cAttributes = compare.getAttributes(initialSame); 229 Map<String, String> sAttributes = source.getAttributes(initialSame); 230 if (!cElement.equals(sElement) || !cAttributes.equals(sAttributes)) { 231 break; 232 } 233 } 234 // at this point elements less than initialSame are identical 235 236 int trailingSame = cSize; 237 int cDelta = -1; 238 int sDelta = sSize - cSize - 1; 239 for (; trailingSame > initialSame; --trailingSame) { 240 String cElement = compare.getElement(trailingSame + cDelta); 241 String sElement = source.getElement(trailingSame + sDelta); 242 Map<String, String> cAttributes = compare.getAttributes(trailingSame + cDelta); 243 Map<String, String> sAttributes = source.getAttributes(trailingSame + sDelta); 244 if (!cElement.equals(sElement) || !cAttributes.equals(sAttributes)) { 245 break; 246 } 247 } 248 // at this point elements at or after trailingSame are identical 249 return "…" 250 + compare.toString(initialSame, trailingSame) 251 + (trailingSame == cSize ? "" : "…"); 252 } 253 } 254