1 package org.unicode.cldr.tool; 2 3 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.Multimap; 5 import com.google.common.collect.TreeMultimap; 6 import com.ibm.icu.util.Output; 7 import java.io.File; 8 import java.util.Collections; 9 import java.util.Map; 10 import java.util.Map.Entry; 11 import java.util.Objects; 12 import java.util.Set; 13 import java.util.TreeMap; 14 import java.util.regex.Matcher; 15 import java.util.regex.Pattern; 16 import org.unicode.cldr.util.CLDRConfig; 17 import org.unicode.cldr.util.CLDRFile; 18 import org.unicode.cldr.util.CLDRFile.Status; 19 import org.unicode.cldr.util.CLDRPaths; 20 import org.unicode.cldr.util.CldrUtility; 21 import org.unicode.cldr.util.Factory; 22 import org.unicode.cldr.util.LanguageTagParser; 23 import org.unicode.cldr.util.Level; 24 import org.unicode.cldr.util.Organization; 25 import org.unicode.cldr.util.PathHeader; 26 import org.unicode.cldr.util.PatternCache; 27 import org.unicode.cldr.util.StandardCodes; 28 import org.unicode.cldr.util.XMLSource; 29 30 public class GetChanges { 31 static CLDRConfig testInfo = ToolConfig.getToolInstance(); 32 static CLDRFile english = testInfo.getEnglish(); 33 static boolean verbose = true; 34 main(String[] args)35 public static void main(String[] args) { 36 System.out.println( 37 "#Dir\tState\tTrunk Value\tmodify_config.txt Locale\tAction\tlabel\tPath Value\tlabel\tNew Value"); 38 Matcher localeFilter = Pattern.compile(".*").matcher(""); 39 File vxml = new File(CLDRPaths.AUX_DIRECTORY, "voting/" + "35" + "/vxml2"); 40 for (File vxmlDir : vxml.listFiles()) { 41 if (!vxmlDir.isDirectory()) { 42 continue; 43 } 44 // System.out.println("#Dir=\t" + vxmlDir); 45 // common, ... 46 File[] commonSeedFiles = vxmlDir.listFiles(); 47 if (commonSeedFiles == null) { 48 System.out.println("##No files in: " + vxmlDir); 49 continue; 50 } 51 for (File commonSeed : commonSeedFiles) { 52 if (!commonSeed.isDirectory() || "dtd".equals(commonSeed.getName())) { 53 continue; 54 } 55 // System.out.println("#Dir=\t" + commonSeed); 56 String subDir = vxmlDir.getName() + "/" + commonSeed.getName(); 57 String l2 = CLDRPaths.BASE_DIRECTORY + subDir; 58 // main, annotations 59 Factory factoryVxml = Factory.make(commonSeed.toString(), ".*"); 60 Factory factoryTrunk = Factory.make(l2, ".*"); 61 62 for (String locale : factoryVxml.getAvailable()) { 63 if (!localeFilter.reset(locale).matches()) { 64 continue; 65 } 66 if (locale.equals("root")) { 67 continue; 68 } 69 CLDRFile vxmlFile; 70 try { 71 vxmlFile = factoryVxml.make(locale, true); 72 } catch (Exception e1) { 73 System.out.println( 74 "##Error: dir=\t" 75 + commonSeed 76 + "\t locale=\t" 77 + locale 78 + "\tmsg=\t" 79 + e1.getMessage()); 80 continue; 81 } 82 CLDRFile trunkFile = null; 83 try { 84 trunkFile = factoryTrunk.make(locale, true); 85 } catch (Exception e) { 86 } 87 compare(subDir, vxmlFile, trunkFile); 88 } 89 } 90 } 91 } 92 93 public static final Set<String> ROOT_OR_CODE_FALLBACK = 94 ImmutableSet.of(XMLSource.CODE_FALLBACK_ID, XMLSource.ROOT_ID); 95 compare(String dir, CLDRFile vxmlFileResolved, CLDRFile trunkFileResolved)96 private static void compare(String dir, CLDRFile vxmlFileResolved, CLDRFile trunkFileResolved) { 97 String localeID = vxmlFileResolved.getLocaleID(); 98 if (localeID.equals("ccp")) { 99 int debug = 0; 100 } 101 CLDRFile vxmlFileUnresolved = vxmlFileResolved.getUnresolved(); 102 // System.out.println("#Dir: " + dir + ";\tLocale: " + localeID); 103 Output<String> localeWhereFound = new Output<>(); 104 Output<String> pathWhereFound = new Output<>(); 105 Status status = new Status(); 106 107 int countNew = 0; 108 int countChanged = 0; 109 for (String path : vxmlFileUnresolved) { 110 if (path.contains("/identity")) { 111 continue; 112 } 113 if (path.contains("ccp")) { 114 int debug = 0; 115 } 116 117 // get trunk value. If not accessible or ROOT_OR_CODE_FALLBACK, then set to null 118 119 String trunkValue = null; 120 if (trunkFileResolved != null) { 121 trunkValue = trunkFileResolved.getStringValue(path); 122 String foundId = trunkFileResolved.getSourceLocaleID(path, status); 123 if (ROOT_OR_CODE_FALLBACK.contains(foundId)) { 124 trunkValue = null; 125 } 126 } 127 String vxmlValue = vxmlFileResolved.getStringValue(path); 128 129 // quick test; will repeat 130 131 if (Objects.equals(vxmlValue, trunkValue)) { 132 continue; 133 } 134 135 // If vxmlValue is INHERITANCE_MARKER, then get bailey 136 // if ROOT_OR_CODE_FALLBACK location, then we skip 137 138 if (vxmlValue.equals(CldrUtility.INHERITANCE_MARKER)) { 139 vxmlValue = vxmlFileResolved.getBaileyValue(path, pathWhereFound, localeWhereFound); 140 if (ROOT_OR_CODE_FALLBACK.contains(localeWhereFound.value)) { 141 continue; 142 } 143 // if (!path.equals(pathWhereFound.value)) { 144 // continue; 145 // } 146 } 147 148 if (Objects.equals(vxmlValue, trunkValue)) { 149 continue; 150 } 151 if (trunkValue == null) { 152 ++countNew; 153 if (verbose) { 154 System.out.println( 155 dir 156 + ";\tnew\t" 157 + "\tlocale=" 158 + localeID 159 + ";" 160 + "\taction=add;" 161 + "\tpath=\t" 162 + path 163 + "\tnew_value=\t" 164 + vxmlValue); 165 } 166 } else { 167 // we do a lot of processing on the annotations, so most likely are just changes 168 // introduced by that. 169 // So ignore for now 170 if (path.startsWith("//ldml/annotations")) { 171 continue; 172 } 173 ++countChanged; 174 if (verbose) { 175 System.out.println( 176 dir 177 + ";\ttrunk=\t" 178 + trunkValue 179 + "\tlocale=" 180 + localeID 181 + ";" 182 + "\taction=add;" 183 + "\tpath=\t" 184 + path 185 + "\tnew_value=\t" 186 + vxmlValue); 187 } 188 } 189 // if (countNew != 0 || countChanged != 0) { 190 // System.out.println("#Dir=\t" + dir + "\tLocale=\t" + localeID + 191 // "\tCountNew=\t" + countNew + "\tCountChanged=\t" + countChanged); 192 // } 193 } 194 } 195 196 static class Data { 197 final String valueLastRelease; 198 final String valueSnapshot; 199 final String valueTrunk; 200 Data(String valueLastRelease, String valueSnapshot, String valueTrunk)201 public Data(String valueLastRelease, String valueSnapshot, String valueTrunk) { 202 super(); 203 this.valueLastRelease = valueLastRelease; 204 this.valueSnapshot = valueSnapshot; 205 this.valueTrunk = valueTrunk; 206 } 207 208 @Override toString()209 public String toString() { 210 return "«" 211 + valueLastRelease 212 + "»" 213 + (!CldrUtility.equals(valueTrunk, valueLastRelease) ? "‡" : "") 214 + "\t" 215 + "«" 216 + valueSnapshot 217 + "»" 218 + (CldrUtility.equals(valueTrunk, valueSnapshot) ? "†" : ""); 219 } 220 } 221 old()222 private void old() { 223 boolean onlyMissing = true; 224 String release = "33.1"; 225 226 String subdir = "annotations"; // "main"; 227 Factory lastReleaseFactory = 228 Factory.make(CLDRPaths.LAST_RELEASE_DIRECTORY + "common/" + subdir, ".*"); 229 Factory trunkFactory = testInfo.getAnnotationsFactory(); // CldrFactory(); 230 Factory snapshotFactory = 231 Factory.make( 232 CLDRPaths.AUX_DIRECTORY + "voting/" + release + "/vxml/common/" + subdir, 233 ".*"); 234 PathHeader.Factory phf = PathHeader.getFactory(english); 235 236 int totalCount = 0; 237 int localeCount = 0; 238 239 Output<String> localeWhereFound = new Output<>(); 240 Output<String> pathWhereFound = new Output<>(); 241 242 CLDRFile englishCldrFile = trunkFactory.make("en", false); 243 final Set<String> paths = ImmutableSet.copyOf(englishCldrFile.iterator()); 244 System.out.println("english paths: " + paths.size()); 245 246 Multimap<String, PathHeader> missing = TreeMultimap.create(); 247 248 Set<String> locales = 249 StandardCodes.make() 250 .getLocaleCoverageLocales( 251 Organization.cldr, Collections.singleton(Level.MODERN)); 252 253 LanguageTagParser ltp = new LanguageTagParser(); 254 for (String locale : locales) { 255 if (!ltp.set(locale).getRegion().isEmpty() || locale.equals("sr_Latn")) { 256 continue; // skip region locales, they'll inherit 257 } 258 // if (!locale.equals("sr_Latn")) { 259 // continue; 260 // } 261 System.out.println(locale); 262 263 CLDRFile snapshot; 264 try { 265 snapshot = snapshotFactory.make(locale, false); 266 } catch (Exception e) { 267 System.out.println("##Skipping " + locale + ", no data in annotations/"); 268 continue; 269 } 270 271 CLDRFile lastRelease = null; 272 try { 273 lastRelease = lastReleaseFactory.make(locale, false); 274 } catch (Exception e) { 275 } 276 277 CLDRFile trunk = null; 278 try { 279 trunk = trunkFactory.make(locale, false); 280 } catch (Exception e) { 281 } 282 283 Map<PathHeader, Data> results = new TreeMap<>(); 284 285 for (String xpath : paths) { 286 if (xpath.contains("fallbackRegionFormat") 287 || xpath.contains("exemplar") 288 || xpath.contains("/identity")) { 289 continue; 290 } 291 String newPath = fixOldPath(xpath); 292 String valueSnapshot = snapshot.getStringValue(newPath); 293 PathHeader ph = null; 294 295 if (valueSnapshot == null) { 296 ph = phf.fromPath(newPath); 297 missing.put(locale, ph); 298 } 299 String valueLastRelease = 300 lastRelease == null ? null : lastRelease.getStringValue(xpath); 301 if (valueSnapshot == null) { 302 ph = phf.fromPath(newPath); 303 missing.put(locale, ph); 304 } 305 306 if (onlyMissing) { 307 continue; 308 } 309 if (valueSnapshot != null && Objects.equals(valueLastRelease, valueSnapshot)) { 310 continue; 311 } 312 String valueTrunk = trunk == null ? null : trunk.getStringValue(newPath); 313 // if (valueSnapshot == null && valueTrunk == null) { // committee 314 // deletion 315 // continue; 316 // } 317 // skip inherited 318 String baileyValue = 319 snapshot.getBaileyValue(xpath, pathWhereFound, localeWhereFound); 320 if (!"root".equals(localeWhereFound.value) 321 && !"code-fallback".equals(localeWhereFound.value) 322 && CldrUtility.equals(valueSnapshot, baileyValue)) { 323 continue; 324 } 325 ph = ph != null ? ph : phf.fromPath(newPath); 326 results.put(ph, new Data(valueLastRelease, valueSnapshot, valueTrunk)); 327 } 328 if (results.isEmpty()) { 329 continue; 330 } 331 int itemCount = 0; 332 localeCount++; 333 for (Entry<PathHeader, Data> entry : results.entrySet()) { 334 PathHeader ph = entry.getKey(); 335 String englishValue = englishCldrFile.getStringValue(ph.getOriginalPath()); 336 System.out.println( 337 localeCount 338 + "\t" 339 + ++itemCount 340 + "\t" 341 + locale 342 + "\t" 343 + english.getName(locale) 344 + "\t" 345 + ph 346 + "\t«" 347 + englishValue 348 + "»\t" 349 + entry.getValue()); 350 } 351 totalCount += itemCount; 352 } 353 System.out.println("##Total:\t" + totalCount); 354 for (Entry<String, PathHeader> entry : missing.entries()) { 355 System.out.println(entry.getKey() + "\t" + entry.getValue()); 356 } 357 } 358 359 static Pattern OLD_PATH = 360 PatternCache.get( 361 "//ldml/units/unit\\[@type=\"([^\"]*)\"]/unitPattern\\[@count=\"([^\"]*)\"](\\[@alt=\"([^\"]*)\"])?"); 362 static Matcher OLD_PATH_MATCHER = OLD_PATH.matcher(""); 363 fixOldPath(String xpath)364 private static String fixOldPath(String xpath) { 365 // //ldml/units/unit[@type="day-future"]/unitPattern[@count="one"] 366 // to 367 // //ldml/units/unitLength[@type="long"]/unit[@type="duration-day-future"]/unitPattern[@count="one"] 368 369 if (OLD_PATH_MATCHER.reset(xpath).matches()) { 370 String type = OLD_PATH_MATCHER.group(4); 371 return "//ldml/units/unitLength[@type=\"" 372 + (type == null ? "long" : type) 373 + "\"]/unit[@type=\"duration-" 374 + OLD_PATH_MATCHER.group(1) 375 + "\"]/unitPattern[@count=\"" 376 + OLD_PATH_MATCHER.group(2) 377 + "\"]"; 378 } 379 return xpath; 380 } 381 } 382