xref: /aosp_15_r20/external/cldr/tools/cldr-code/src/main/java/org/unicode/cldr/tool/CountItems.java (revision 912701f9769bb47905792267661f0baf2b85bed5)
1 /*
2  ******************************************************************************
3  * Copyright (C) 2004-2013, International Business Machines Corporation and   *
4  * others. All Rights Reserved.                                               *
5  ******************************************************************************
6  */
7 package org.unicode.cldr.tool;
8 
9 import com.google.common.base.Joiner;
10 import com.google.common.collect.ImmutableMap;
11 import com.ibm.icu.dev.util.UnicodeMap;
12 import com.ibm.icu.dev.util.UnicodeMapIterator;
13 import com.ibm.icu.impl.Relation;
14 import com.ibm.icu.impl.Row;
15 import com.ibm.icu.impl.Row.R2;
16 import com.ibm.icu.impl.Row.R3;
17 import com.ibm.icu.text.Collator;
18 import com.ibm.icu.text.NumberFormat;
19 import com.ibm.icu.text.RuleBasedCollator;
20 import com.ibm.icu.text.Transform;
21 import com.ibm.icu.text.UnicodeSet;
22 import com.ibm.icu.util.ULocale;
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Comparator;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Set;
39 import java.util.TreeMap;
40 import java.util.TreeSet;
41 import java.util.regex.Matcher;
42 import java.util.regex.Pattern;
43 import org.unicode.cldr.draft.FileUtilities;
44 import org.unicode.cldr.util.CLDRConfig;
45 import org.unicode.cldr.util.CLDRFile;
46 import org.unicode.cldr.util.CLDRPaths;
47 import org.unicode.cldr.util.CldrUtility;
48 import org.unicode.cldr.util.Factory;
49 import org.unicode.cldr.util.Iso639Data;
50 import org.unicode.cldr.util.IsoCurrencyParser;
51 import org.unicode.cldr.util.IsoCurrencyParser.Data;
52 import org.unicode.cldr.util.IsoRegionData;
53 import org.unicode.cldr.util.Level;
54 import org.unicode.cldr.util.Log;
55 import org.unicode.cldr.util.Organization;
56 import org.unicode.cldr.util.Pair;
57 import org.unicode.cldr.util.PatternCache;
58 import org.unicode.cldr.util.StandardCodes;
59 import org.unicode.cldr.util.SupplementalDataInfo;
60 import org.unicode.cldr.util.Tabber;
61 import org.unicode.cldr.util.TimezoneFormatter;
62 import org.unicode.cldr.util.UnicodeSetPrettyPrinter;
63 import org.unicode.cldr.util.XPathParts;
64 import org.unicode.cldr.util.props.ICUPropertyFactory;
65 
66 /** Simple program to count the amount of data in CLDR. Internal Use. */
67 public class CountItems {
68 
69     private static final Collator ROOT_PRIMARY_COLLATOR =
70             Collator.getInstance(ULocale.ROOT).setStrength2(Collator.PRIMARY);
71 
72     static final String needsTranslationString =
73             "America/Buenos_Aires " // America/Rio_Branco
74                     + " America/Manaus America/Belem "
75                     + " America/Campo_Grande America/Sao_Paulo "
76                     + " Australia/Perth Australia/Darwin Australia/Brisbane Australia/Adelaide Australia/Sydney Australia/Hobart "
77                     + " America/Vancouver America/Edmonton America/Regina America/Winnipeg America/Toronto America/Halifax America/St_Johns "
78                     + " Asia/Jakarta "
79                     + " America/Tijuana America/Hermosillo America/Chihuahua America/Mexico_City "
80                     + " Europe/Moscow Europe/Kaliningrad Europe/Moscow Asia/Yekaterinburg Asia/Novosibirsk Asia/Yakutsk Asia/Vladivostok"
81                     + " Pacific/Honolulu America/Indiana/Indianapolis America/Anchorage "
82                     + " America/Los_Angeles America/Phoenix America/Denver America/Chicago America/Indianapolis"
83                     + " America/New_York";
84 
85     static final ImmutableMap<String, String> country_map =
86             ImmutableMap.<String, String>builder()
87                     .put("AQ", "http://www.worldtimezone.com/time-antarctica24.php")
88                     .put("AR", "http://www.worldtimezone.com/time-south-america24.php")
89                     .put("AU", "http://www.worldtimezone.com/time-australia24.php")
90                     .put("BR", "http://www.worldtimezone.com/time-south-america24.php")
91                     .put("CA", "http://www.worldtimezone.com/time-canada24.php")
92                     .put("CD", "http://www.worldtimezone.com/time-africa24.php")
93                     .put("CL", "http://www.worldtimezone.com/time-south-america24.php")
94                     .put("CN", "http://www.worldtimezone.com/time-cis24.php")
95                     .put("EC", "http://www.worldtimezone.com/time-south-america24.php")
96                     .put("ES", "http://www.worldtimezone.com/time-europe24.php")
97                     .put("FM", "http://www.worldtimezone.com/time-oceania24.php")
98                     .put("GL", "http://www.worldtimezone.com/index24.php")
99                     .put("ID", "http://www.worldtimezone.com/time-asia24.php")
100                     .put("KI", "http://www.worldtimezone.com/time-oceania24.php")
101                     .put("KZ", "http://www.worldtimezone.com/time-cis24.php")
102                     .put("MH", "http://www.worldtimezone.com/time-oceania24.php")
103                     .put("MN", "http://www.worldtimezone.com/time-cis24.php")
104                     .put("MX", "http://www.worldtimezone.com/index24.php")
105                     .put("MY", "http://www.worldtimezone.com/time-asia24.php")
106                     .put("NZ", "http://www.worldtimezone.com/time-oceania24.php")
107                     .put("PF", "http://www.worldtimezone.com/time-oceania24.php")
108                     .put("PT", "http://www.worldtimezone.com/time-europe24.php")
109                     .put("RU", "http://www.worldtimezone.com/time-russia24.php")
110                     .put("SJ", "http://www.worldtimezone.com/index24.php")
111                     .put("UA", "http://www.worldtimezone.com/time-cis24.php")
112                     .put("UM", "http://www.worldtimezone.com/time-oceania24.php")
113                     .put("US", "http://www.worldtimezone.com/time-usa24.php")
114                     .put("UZ", "http://www.worldtimezone.com/time-cis24.php")
115                     .build();
116 
117     /**
118      * Count the data.
119      *
120      * @throws IOException
121      */
main(String[] args)122     public static void main(String[] args) throws Exception {
123         double deltaTime = System.currentTimeMillis();
124         try {
125             String methodName = System.getProperty("method");
126             if (methodName != null) {
127                 CldrUtility.callMethod(methodName, CountItems.class);
128             } else {
129                 ShowZoneEquivalences.getZoneEquivalences();
130             }
131         } finally {
132             deltaTime = System.currentTimeMillis() - deltaTime;
133             System.out.println("Elapsed: " + deltaTime / 1000.0 + " seconds");
134             System.out.println("Done");
135         }
136     }
137 
subheader(PrintWriter out, Tabber tabber)138     static void subheader(PrintWriter out, Tabber tabber) {
139         // out.println("<tr><td colspan='6' class='gap'>&nbsp;</td></tr>");
140         out.println(
141                 tabber.process(
142                         "Cnty"
143                                 + "\t"
144                                 + "Grp"
145                                 + "\t"
146                                 + "ZoneID"
147                                 + "\t"
148                                 + "Formatted ID"
149                                 + "\t"
150                                 + "MaxOffset"
151                                 + "\t"
152                                 + "MinOffset"));
153     }
154 
155     /** */
getPatternBlocks()156     private static void getPatternBlocks() {
157         UnicodeSet patterns = new UnicodeSet("[:pattern_syntax:]");
158         UnicodeSet unassigned = new UnicodeSet("[:unassigned:]");
159         UnicodeSet punassigned = new UnicodeSet(patterns).retainAll(unassigned);
160         UnicodeMap<String> blocks = ICUPropertyFactory.make().getProperty("block").getUnicodeMap();
161         blocks.setMissing("<Reserved-Block>");
162         // blocks.composeWith(new UnicodeMap().putAll(new
163         // UnicodeSet(patterns).retainAll(unassigned),"<reserved>"),
164         // new UnicodeMap.Composer() {
165         // public Object compose(int codePoint, Object a, Object b) {
166         // if (a == null) {
167         // return b;
168         // }
169         // if (b == null) {
170         // return a;
171         // }
172         // return a.toString() + " " + b.toString();
173         // }});
174         for (UnicodeMapIterator<String> it = new UnicodeMapIterator<>(blocks); it.nextRange(); ) {
175             UnicodeSet range = new UnicodeSet(it.codepoint, it.codepointEnd);
176             boolean hasPat = range.containsSome(patterns);
177             String prefix =
178                     !hasPat
179                             ? "Not-Syntax"
180                             : !range.containsSome(unassigned)
181                                     ? "Closed"
182                                     : !range.containsSome(punassigned) ? "Closed2" : "Open";
183 
184             boolean show = (prefix.equals("Open") || prefix.equals("Closed2"));
185 
186             if (show) System.out.println();
187             System.out.println(prefix + "\t" + range + "\t" + it.value);
188             if (show) {
189                 System.out.println(
190                         new UnicodeMap<String>()
191                                 .putAll(unassigned, "<reserved>")
192                                 .putAll(punassigned, "<reserved-for-syntax>")
193                                 .setMissing("<assigned>")
194                                 .putAll(range.complement(), null));
195             }
196         }
197     }
198 
199     /**
200      * @throws IOException
201      */
showExemplars()202     private static void showExemplars() throws IOException {
203         PrintWriter out =
204                 FileUtilities.openUTF8Writer(CLDRPaths.GEN_DIRECTORY, "fixed_exemplars.txt");
205         Factory cldrFactory = Factory.make(CLDRPaths.MAIN_DIRECTORY, ".*");
206         Set<String> locales = cldrFactory.getAvailable();
207         for (Iterator<String> it = locales.iterator(); it.hasNext(); ) {
208             System.out.print('.');
209             String locale = it.next();
210             CLDRFile cldrfile = cldrFactory.make(locale, false);
211             String v = cldrfile.getStringValue("//ldml/characters/exemplarCharacters");
212             if (v == null) continue;
213             UnicodeSet exemplars = new UnicodeSet(v);
214             if (exemplars.size() != 0 && exemplars.size() < 500) {
215                 out.println(locale + ":\t\u200E" + v + '\u200E');
216                 String fixed = UnicodeSetPrettyPrinter.fromIcuLocale(locale).format(exemplars);
217                 out.println(" =>\t\u200E" + fixed + '\u200E');
218 
219                 verifyEquality(exemplars, new UnicodeSet(fixed));
220                 out.flush();
221             }
222         }
223         out.close();
224     }
225 
226     /** */
verifyEquality(UnicodeSet exemplars, UnicodeSet others)227     private static void verifyEquality(UnicodeSet exemplars, UnicodeSet others) {
228         if (others.equals(exemplars)) return;
229         System.out.println("FAIL\ta-b\t" + new UnicodeSet(exemplars).removeAll(others));
230         System.out.println("\tb-a\t" + new UnicodeSet(others).removeAll(exemplars));
231     }
232 
233     /** */
generateSupplementalCurrencyItems()234     public static void generateSupplementalCurrencyItems() {
235         IsoCurrencyParser isoCurrencyParser = IsoCurrencyParser.getInstance();
236         Relation<String, Data> codeList = isoCurrencyParser.getCodeList();
237         Map<String, String> numericTocurrencyCode = new TreeMap<>();
238         StringBuffer list = new StringBuffer();
239 
240         for (Iterator<String> it = codeList.keySet().iterator(); it.hasNext(); ) {
241             String currencyCode = it.next();
242             int numericCode = -1;
243             Set<Data> dataSet = codeList.getAll(currencyCode);
244             boolean first = true;
245             for (Data data : dataSet) {
246                 if (first) {
247                     first = false;
248                 }
249                 numericCode = data.getNumericCode();
250             }
251 
252             String strNumCode = "" + numericCode;
253             String otherCode = numericTocurrencyCode.get(strNumCode);
254             if (otherCode != null) {
255                 System.out.println("Warning: duplicate code " + otherCode + "for " + numericCode);
256             }
257             numericTocurrencyCode.put(strNumCode, currencyCode);
258             if (list.length() != 0) list.append(" ");
259             String currencyLine =
260                     "<currencyCodes type="
261                             + "\""
262                             + currencyCode
263                             + "\""
264                             + " numeric="
265                             + "\""
266                             + numericCode
267                             + "\"/>";
268             list.append(currencyLine);
269             System.out.println(currencyLine);
270         }
271         System.out.println();
272     }
273 
274     /** */
generateCurrencyItems()275     public static void generateCurrencyItems() {
276         IsoCurrencyParser isoCurrencyParser = IsoCurrencyParser.getInstance();
277         Relation<String, Data> codeList = isoCurrencyParser.getCodeList();
278         StringBuffer list = new StringBuffer();
279         for (Iterator<String> it = codeList.keySet().iterator(); it.hasNext(); ) {
280             // String lastField = (String) it.next();
281             // String zone = (String) fullMap.get(lastField);
282             String currencyCode = it.next();
283             Set<Data> dataSet = codeList.getAll(currencyCode);
284             boolean first = true;
285             for (Data data : dataSet) {
286                 if (first) {
287                     System.out.print(currencyCode);
288                     first = false;
289                 }
290                 System.out.println("\t" + data);
291             }
292 
293             if (list.length() != 0) list.append(" ");
294             list.append(currencyCode);
295         }
296         System.out.println();
297         String sep = CldrUtility.LINE_SEPARATOR + "\t\t\t\t";
298         // "((?:[-+_A-Za-z0-9]+[/])+[A-Za-z0-9])[-+_A-Za-z0-9]*"
299         String broken =
300                 CldrUtility.breakLines(
301                         list.toString(),
302                         sep,
303                         PatternCache.get("([A-Z])[A-Z][A-Z]").matcher(""),
304                         80);
305         assert (list.toString().equals(broken.replace(sep, " ")));
306         // System.out.println("\t\t\t<variable id=\"$currency\" type=\"choice\">"
307         //    + broken + CldrUtility.LINE_SEPARATOR + "\t\t\t</variable>");
308         Set<String> isoTextFileCodes = StandardCodes.make().getAvailableCodes("currency");
309         Set<String> temp = new TreeSet<>(codeList.keySet());
310         temp.removeAll(isoTextFileCodes);
311         if (temp.size() != 0) {
312             throw new IllegalArgumentException("Missing from ISO4217.txt file: " + temp);
313         }
314     }
315 
genSupplementalZoneData()316     public static void genSupplementalZoneData() throws IOException {
317         genSupplementalZoneData(false);
318     }
319 
genSupplementalZoneData(boolean skipUnaliased)320     public static void genSupplementalZoneData(boolean skipUnaliased) throws IOException {
321         RuleBasedCollator col = (RuleBasedCollator) Collator.getInstance();
322         col.setNumericCollation(true);
323         StandardCodes sc = StandardCodes.make();
324         Map<String, String> zone_country = sc.getZoneToCounty();
325         Map<String, Set<String>> country_zone = sc.getCountryToZoneSet();
326         Factory cldrFactory = Factory.make(CLDRPaths.MAIN_DIRECTORY, ".*");
327         CLDRFile english = cldrFactory.make("en", true);
328 
329         writeZonePrettyPath(col, zone_country, english);
330         writeMetazonePrettyPath();
331 
332         Map<String, String> old_new = sc.getZoneLinkold_new();
333         Map<String, Set<String>> new_old = new TreeMap<>();
334 
335         for (Iterator<String> it = old_new.keySet().iterator(); it.hasNext(); ) {
336             String old = it.next();
337             String newOne = old_new.get(old);
338             Set<String> oldSet = new_old.get(newOne);
339             if (oldSet == null) new_old.put(newOne, oldSet = new TreeSet<>());
340             oldSet.add(old);
341         }
342         Map<String, String> fullMap = new TreeMap<>(col);
343         for (Iterator<String> it = zone_country.keySet().iterator(); it.hasNext(); ) {
344             String zone = it.next();
345             String defaultName = TimezoneFormatter.getFallbackName(zone);
346             Object already = fullMap.get(defaultName);
347             if (already != null) System.out.println("CONFLICT: " + already + ", " + zone);
348             fullMap.put(defaultName, zone);
349         }
350         // fullSet.addAll(zone_country.keySet());
351         // fullSet.addAll(new_old.keySet());
352 
353         System.out.println("<!-- Generated by org.unicode.cldr.tool.CountItems -->");
354         System.out.println("<supplementalData>");
355         System.out.println("\t<timezoneData>");
356         System.out.println();
357 
358         Set<String> multizone = new TreeSet<>();
359         for (Iterator<String> it = country_zone.keySet().iterator(); it.hasNext(); ) {
360             String country = it.next();
361             Set<String> zones = country_zone.get(country);
362             if (zones != null && zones.size() != 1) multizone.add(country);
363         }
364 
365         System.out.println(
366                 "\t\t<zoneFormatting multizone=\""
367                         + toString(multizone, " ")
368                         + "\""
369                         + " tzidVersion=\""
370                         + sc.getZoneVersion()
371                         + "\""
372                         + ">");
373 
374         Set<String> orderedSet = new TreeSet<>(col);
375         orderedSet.addAll(zone_country.keySet());
376         orderedSet.addAll(sc.getDeprecatedZoneIDs());
377         StringBuffer tzid = new StringBuffer();
378 
379         for (Iterator<String> it = orderedSet.iterator(); it.hasNext(); ) {
380             // String lastField = (String) it.next();
381             // String zone = (String) fullMap.get(lastField);
382             String zone = it.next();
383             if (tzid.length() != 0) tzid.append(' ');
384             tzid.append(zone);
385 
386             String country = zone_country.get(zone);
387             if (country == null) continue; // skip deprecated
388 
389             Set<String> aliases = new_old.get(zone);
390             if (aliases != null) {
391                 aliases = new TreeSet<>(aliases);
392                 aliases.remove(zone);
393             }
394             if (skipUnaliased) if (aliases == null || aliases.size() == 0) continue;
395 
396             System.out.println(
397                     "\t\t\t<zoneItem"
398                             + " type=\""
399                             + zone
400                             + "\""
401                             + " territory=\""
402                             + country
403                             + "\""
404                             + (aliases != null && aliases.size() > 0
405                                     ? " aliases=\"" + toString(aliases, " ") + "\""
406                                     : "")
407                             + "/>");
408         }
409 
410         System.out.println("\t\t</zoneFormatting>");
411         System.out.println();
412         System.out.println("\t</timezoneData>");
413         System.out.println("</supplementalData>");
414         System.out.println();
415         String sep = CldrUtility.LINE_SEPARATOR + "\t\t\t\t";
416         // "((?:[-+_A-Za-z0-9]+[/])+[A-Za-z0-9])[-+_A-Za-z0-9]*"
417         String broken =
418                 CldrUtility.breakLines(
419                         tzid,
420                         sep,
421                         PatternCache.get("((?:[-+_A-Za-z0-9]+[/])+[-+_A-Za-z0-9])[-+_A-Za-z0-9]*")
422                                 .matcher(""),
423                         80);
424         assert (tzid.toString().equals(broken.replace(sep, " ")));
425         System.out.println(
426                 "\t\t\t<variable id=\"$tzid\" type=\"choice\">"
427                         + broken
428                         + CldrUtility.LINE_SEPARATOR
429                         + "\t\t\t</variable>");
430     }
431 
writeMetazonePrettyPath()432     public static void writeMetazonePrettyPath() {
433         CLDRConfig testInfo = ToolConfig.getToolInstance();
434         Map<String, Map<String, String>> map =
435                 testInfo.getSupplementalDataInfo().getMetazoneToRegionToZone();
436         Map zoneToCountry = StandardCodes.make().getZoneToCounty();
437         Set<Pair<String, String>> results = new TreeSet<>();
438         Map<String, String> countryToContinent =
439                 getCountryToContinent(testInfo.getSupplementalDataInfo(), testInfo.getEnglish());
440 
441         for (String metazone : map.keySet()) {
442             Map<String, String> regionToZone = map.get(metazone);
443             String zone = regionToZone.get("001");
444             if (zone == null) {
445                 throw new IllegalArgumentException("Missing 001 for metazone " + metazone);
446             }
447             String continent = zone.split("/")[0];
448 
449             final Object country = zoneToCountry.get(zone);
450             results.add(
451                     new Pair<>(
452                             continent
453                                     + "\t"
454                                     + country
455                                     + "\t"
456                                     + countryToContinent.get(country)
457                                     + "\t"
458                                     + metazone,
459                             metazone));
460         }
461         for (Pair<String, String> line : results) {
462             System.out.println("'" + line.getSecond() + "'\t>\t'\t" + line.getFirst() + "\t'");
463         }
464     }
465 
getCountryToContinent( SupplementalDataInfo supplementalDataInfo, CLDRFile english)466     private static Map<String, String> getCountryToContinent(
467             SupplementalDataInfo supplementalDataInfo, CLDRFile english) {
468         Relation<String, String> countryToContinent =
469                 Relation.of(new TreeMap<String, Set<String>>(), TreeSet.class);
470         Set<String> continents = new HashSet<>(Arrays.asList("002", "019", "142", "150", "009"));
471         // note: we don't need more than 3 levels
472         for (String continent : continents) {
473             final Set<String> subcontinents = supplementalDataInfo.getContained(continent);
474             countryToContinent.putAll(subcontinents, continent);
475             for (String subcontinent : subcontinents) {
476                 if (subcontinent.equals("EU")) continue;
477                 final Set<String> countries = supplementalDataInfo.getContained(subcontinent);
478                 countryToContinent.putAll(countries, continent);
479             }
480         }
481         // convert to map
482         Map<String, String> results = new TreeMap<>();
483         for (String item : countryToContinent.keySet()) {
484             final Set<String> containees = countryToContinent.getAll(item);
485             if (containees.size() != 1) {
486                 throw new IllegalArgumentException(item + "\t" + containees);
487             }
488             results.put(
489                     item, english.getName(CLDRFile.TERRITORY_NAME, containees.iterator().next()));
490         }
491         return results;
492     }
493 
writeZonePrettyPath( RuleBasedCollator col, Map<String, String> zone_country, CLDRFile english)494     private static void writeZonePrettyPath(
495             RuleBasedCollator col, Map<String, String> zone_country, CLDRFile english)
496             throws IOException {
497         System.out.println("Writing zonePrettyPath");
498         Set<String> masked = new HashSet<>();
499         Map<String, String> zoneNew_Old = new TreeMap<>(col);
500         String lastZone = "XXX";
501         for (String zone : new TreeSet<>(zone_country.keySet())) {
502             String[] parts = zone.split("/");
503             String newPrefix =
504                     zone_country.get(zone); // english.getName("tzid", zone_country.get(zone),
505             // false).replace(' ', '_');
506             if (newPrefix.equals("001")) {
507                 newPrefix = "ZZ";
508             }
509             parts[0] = newPrefix;
510             String newName;
511             if (parts.length > 2) {
512                 System.out.println("\tMultifield: " + zone);
513                 if (parts.length == 3 && parts[1].equals("Argentina")) {
514                     newName = parts[0] + "/" + parts[1];
515                 } else {
516                     newName = CldrUtility.join(parts, "/");
517                 }
518             } else {
519                 newName = CldrUtility.join(parts, "/");
520             }
521             zoneNew_Old.put(newName, zone);
522             if (zone.startsWith(lastZone)) {
523                 masked.add(zone); // find "masked items" and do them first.
524             } else {
525                 lastZone = zone;
526             }
527         }
528 
529         Log.setLog(CLDRPaths.GEN_DIRECTORY + "/supplemental/prettyPathZone.txt");
530         String lastCountry = "";
531         for (int i = 0; i < 2; ++i) {
532             Set<String> orderedList = zoneNew_Old.keySet();
533             if (i == 0) {
534                 Log.println("# Short IDs for zone names: country code + last part of TZID");
535                 Log.println(
536                         "# First are items that would be masked, and are moved forwards and sorted in reverse order");
537                 Log.println();
538                 // Comparator c;
539                 Set<String> temp = new TreeSet<>(new ReverseComparator<>(col));
540                 temp.addAll(orderedList);
541                 orderedList = temp;
542             } else {
543                 Log.println();
544                 Log.println("# Normal items, sorted by country code");
545                 Log.println();
546             }
547 
548             // do masked items first
549 
550             for (String newName : orderedList) {
551                 String oldName = zoneNew_Old.get(newName);
552                 if (masked.contains(oldName) != (i == 0)) {
553                     continue;
554                 }
555                 String newCountry = newName.split("/")[0];
556                 if (!newCountry.equals(lastCountry)) {
557                     Log.println(
558                             "# " + newCountry + "\t" + english.getName("territory", newCountry));
559                     lastCountry = newCountry;
560                 }
561                 Log.println("\t'" + oldName + "'\t>\t'" + newName + "';");
562             }
563         }
564         Log.close();
565         System.out.println("Done Writing zonePrettyPath");
566     }
567 
568     public static class ReverseComparator<T> implements Comparator<T> {
569         Comparator<T> other;
570 
ReverseComparator(Comparator<T> other)571         public ReverseComparator(Comparator<T> other) {
572             this.other = other;
573         }
574 
575         @Override
compare(T o1, T o2)576         public int compare(T o1, T o2) {
577             return other.compare(o2, o1);
578         }
579     }
580 
getSubtagVariables2()581     public static void getSubtagVariables2() throws IOException {
582         Log.setLogNoBOM(CLDRPaths.GEN_DIRECTORY + "/supplemental", "supplementalMetadata.xml");
583         BufferedReader oldFile =
584                 FileUtilities.openUTF8Reader(
585                         CLDRPaths.SUPPLEMENTAL_DIRECTORY, "supplementalMetadata.xml");
586         CldrUtility.copyUpTo(
587                 oldFile,
588                 PatternCache.get("\\s*<!-- start of data generated with CountItems.*"),
589                 Log.getLog(),
590                 true);
591 
592         Map<String, String> variableSubstitutions = getVariables(VariableType.partial);
593         for (Entry<String, String> type : variableSubstitutions.entrySet()) {
594             Log.println(type.getValue());
595         }
596 
597         // String sep = CldrUtility.LINE_SEPARATOR + "\t\t\t";
598         // String broken = CldrUtility.breakLines(CldrUtility.join(defaultLocaleContent," "), sep,
599         // PatternCache.get("(\\S)\\S*").matcher(""), 80);
600         //
601         // Log.println("\t\t<defaultContent locales=\"" + broken + "\"");
602         // Log.println("\t\t/>");
603 
604         // Log.println("</supplementalData>");
605         CldrUtility.copyUpTo(
606                 oldFile,
607                 PatternCache.get("\\s<!-- end of data generated by CountItems.*"),
608                 null,
609                 true);
610         CldrUtility.copyUpTo(oldFile, null, Log.getLog(), true);
611 
612         Log.close();
613         oldFile.close();
614     }
615 
616     static final SupplementalDataInfo supplementalData =
617             SupplementalDataInfo.getInstance(CLDRPaths.SUPPLEMENTAL_DIRECTORY);
618     static final StandardCodes sc = StandardCodes.make();
619 
getSubtagVariables()620     public static void getSubtagVariables() {
621         //        This section no longer necessary, as it has been replaced by the new
622         // attributeValueValidity.xml
623         //
624         //        System.out.println("Validity variables");
625         //        System.out.println("Cut/paste into supplementalMetadata.xml under the line");
626         //        System.out.println("<!-- start of data generated with CountItems tool ...");
627         //        Map<String, String> variableSubstitutions = getVariables(VariableType.partial);
628 
629         //        for (Entry<String, String> type : variableSubstitutions.entrySet()) {
630         //            System.out.println(type.getValue());
631         //        }
632         //        System.out.println("<!-- end of Validity variables generated with CountItems tool
633         // ...");
634         //        System.out.println();
635         System.out.println("Language aliases");
636         System.out.println("Cut/paste into supplementalMetadata.xml under the line");
637         System.out.println("<!-- start of data generated with CountItems tool ...");
638 
639         Map<String, Map<String, String>> languageReplacement =
640                 StandardCodes.getLStreg().get("language");
641         Map<String, Map<String, R2<List<String>, String>>> localeAliasInfo =
642                 supplementalData.getLocaleAliasInfo();
643         Map<String, R2<List<String>, String>> languageAliasInfo = localeAliasInfo.get("language");
644 
645         Set<String> available = Iso639Data.getAvailable();
646         // <languageAlias type="aju" replacement="jrb"/> <!-- Moroccan Judeo-Arabic ⇒ Judeo-Arabic
647         // -->
648         Set<String> bad3letter = new HashSet<>();
649         for (String lang : available) {
650             if (lang.length() != 2) continue;
651             String target = lang;
652             Map<String, String> lstregData = languageReplacement.get(lang);
653             if (lstregData == null) {
654                 throw new IllegalArgumentException("illegal language code");
655             } else {
656                 String replacement = lstregData.get("Preferred-Value");
657                 if (replacement != null) {
658                     target = replacement;
659                 }
660             }
661             String alpha3 = Iso639Data.toAlpha3(lang);
662             bad3letter.add(alpha3);
663             String targetAliased;
664             if (languageAliasInfo.containsKey(target)) {
665                 targetAliased = Joiner.on(" ").join(languageAliasInfo.get(target).get0());
666             } else {
667                 targetAliased = target;
668             }
669             System.out.println(
670                     "\t\t\t<languageAlias type=\""
671                             + alpha3
672                             + "\" replacement=\""
673                             + targetAliased
674                             + "\" reason=\"overlong\"/> <!-- "
675                             + Iso639Data.getNames(target)
676                             + " -->");
677         }
678         System.out.println("\t\t\t<!-- Bibliographic -->");
679         TreeMap<String, String> sorted = new TreeMap<>();
680         for (String hasBiblio : Iso639Data.hasBiblio3()) {
681             String biblio = Iso639Data.toBiblio3(hasBiblio);
682             sorted.put(biblio, hasBiblio);
683         }
684         for (Entry<String, String> entry : sorted.entrySet()) {
685             String biblio = entry.getKey();
686             String hasBiblio = entry.getValue();
687             System.out.println(
688                     "\t\t\t<languageAlias type=\""
689                             + biblio
690                             + "\" replacement=\""
691                             + hasBiblio
692                             + "\" reason=\"bibliographic\"/> <!-- "
693                             + Iso639Data.getNames(hasBiblio)
694                             + " -->");
695         }
696         System.out.println("<!-- end of Language alises generated with CountItems tool ...");
697 
698         Set<String> encompassed = Iso639Data.getEncompassed();
699         Set<String> macros = Iso639Data.getMacros();
700         Map<String, String> encompassed_macro = new HashMap<>();
701         for (Entry<String, R2<List<String>, String>> typeAndData : languageAliasInfo.entrySet()) {
702             String type = typeAndData.getKey();
703             R2<List<String>, String> data = typeAndData.getValue();
704             List<String> replacements = data.get0();
705             if (!encompassed.contains(type)) continue;
706             if (replacements == null || replacements.size() != 1) continue;
707             String replacement = replacements.get(0);
708             if (macros.contains(replacement)) {
709                 // we have a match, encompassed => replacement
710                 encompassed_macro.put(type, replacement);
711             }
712         }
713         Set<String> missing = new TreeSet<>();
714         missing.addAll(macros);
715         missing.remove("no");
716         missing.remove("sh");
717 
718         missing.removeAll(encompassed_macro.values());
719         if (missing.size() != 0) {
720             for (String missingMacro : missing) {
721                 System.err.println(
722                         "ERROR: Missing <languageAlias type=\""
723                                 + "???"
724                                 + "\" replacement=\""
725                                 + missingMacro
726                                 + "\"/> <!-- ??? => "
727                                 + Iso639Data.getNames(missingMacro)
728                                 + " -->");
729                 System.out.println("\tOptions for ???:");
730                 for (String enc : Iso639Data.getEncompassedForMacro(missingMacro)) {
731                     System.out.println("\t" + enc + "\t// " + Iso639Data.getNames(enc));
732                 }
733             }
734         }
735         // verify that every macro language has a encompassed mapping to it
736         // and remember those codes
737 
738         // verify that nobody contains a bad code
739 
740         for (Entry<String, R2<List<String>, String>> typeAndData : languageAliasInfo.entrySet()) {
741             String type = typeAndData.getKey();
742             List<String> replacements = typeAndData.getValue().get0();
743             if (replacements == null) continue;
744             for (String replacement : replacements) {
745                 if (bad3letter.contains(replacement)) {
746                     System.err.println(
747                             "ERROR: Replacement(s) for type=\""
748                                     + type
749                                     + "\" contains "
750                                     + replacement
751                                     + ", which should be: "
752                                     + Iso639Data.fromAlpha3(replacement));
753                 }
754             }
755         }
756 
757         // get the bad ISO codes
758 
759         Factory cldrFactory = Factory.make(CLDRPaths.MAIN_DIRECTORY, ".*");
760         CLDRFile english = cldrFactory.make("en", true);
761 
762         Set<String> territories = new TreeSet<>();
763         Relation<String, String> containers = supplementalData.getTerritoryToContained();
764         for (String region : sc.getAvailableCodes("territory")) {
765             if (containers.containsKey(region)) continue;
766             territories.add(region);
767         }
768         System.out.println();
769         System.out.println("Territory aliases");
770         System.out.println("Cut/paste into supplementalMetadata.xml under the line");
771         System.out.println("<!-- start of data generated with CountItems tool ...");
772         // final Map<String, R2<List<String>, String>> territoryAliasInfo =
773         // localeAliasInfo.get("territory");
774 
775         addRegions(
776                 english,
777                 territories,
778                 "alpha3",
779                 "EA,EU,IC".split(","),
780                 new Transform<String, String>() {
781                     @Override
782                     public String transform(String region) {
783                         return IsoRegionData.get_alpha3(region);
784                     }
785                 });
786         addRegions(
787                 english,
788                 territories,
789                 "numeric",
790                 "AC,CP,DG,EA,EU,IC,TA".split(","),
791                 new Transform<String, String>() {
792                     @Override
793                     public String transform(String region) {
794                         return IsoRegionData.getNumeric(region);
795                     }
796                 });
797         System.out.println("<!-- end of Territory alises generated with CountItems tool ...");
798         System.out.println();
799         System.out.println("Deprecated codes check (informational)");
800         // check that all deprecated codes are in fact deprecated
801         Map<String, Map<String, Map<String, String>>> fullData = StandardCodes.getLStreg();
802 
803         checkCodes("language", sc, localeAliasInfo, fullData);
804         checkCodes("script", sc, localeAliasInfo, fullData);
805         checkCodes("territory", sc, localeAliasInfo, fullData);
806         System.out.println("End of Deprecated codes check...");
807 
808         // generate mapping equivalences
809         // { "aar", "aar", "aa" }, // Afar
810         // b, t, bcp47
811         System.out.println();
812         System.out.println("Mapping equivalences - (Informational only...)");
813         System.out.println("{ bib , tech , bcp47 }");
814 
815         Set<R3<String, String, String>> rows = new TreeSet<>();
816         for (String lang : Iso639Data.getAvailable()) {
817             String bib = Iso639Data.toBiblio3(lang);
818             String tech = Iso639Data.toAlpha3(lang);
819             R3<String, String, String> row = Row.of(tech, bib, lang);
820             rows.add(row);
821         }
822         for (R3<String, String, String> row : rows) {
823             String tech = row.get0();
824             String bib = row.get1();
825             String lang = row.get2();
826             String name = Iso639Data.getNames(lang).iterator().next(); // english.getName(lang);
827             if ((bib != null && !lang.equals(bib)) || (tech != null && !lang.equals(tech))) {
828                 System.out.println(
829                         "  { \"" + bib + "\", \"" + tech + "\", \"" + lang + "\" },  // " + name);
830             }
831         }
832         System.out.println("End of Mapping equivalences...");
833 
834         // generate the codeMappings
835         // <codeMappings>
836         // <territoryCodes type="CS" numeric="891" alpha3="SCG" fips10="YI"/>
837 
838         System.out.println();
839         System.out.println("Code Mappings");
840         System.out.println("Cut/paste into supplementaData.xml under the line");
841         System.out.println("<!-- start of data generated with CountItems tool ...");
842         List<String> warnings = new ArrayList<>();
843         territories.add("QO");
844         territories.add("EU");
845         // territories.add("MF");
846         // Map<String, R2<List<String>, String>> territoryAliases =
847         // supplementalData.getLocaleAliasInfo().get("territory");
848         Relation<String, String> numeric2region =
849                 Relation.of(new HashMap<String, Set<String>>(), TreeSet.class);
850         Relation<String, String> alpha32region =
851                 Relation.of(new HashMap<String, Set<String>>(), TreeSet.class);
852         for (String region : territories) {
853             String numeric = IsoRegionData.getNumeric(region);
854             String alpha3 = IsoRegionData.get_alpha3(region);
855             numeric2region.put(numeric, region);
856             alpha32region.put(alpha3, region);
857         }
858 
859         System.out.println("    <codeMappings>");
860 
861         for (String region : territories) {
862             String numeric = IsoRegionData.getNumeric(region);
863             String alpha3 = IsoRegionData.get_alpha3(region);
864             String fips10 = IsoRegionData.get_fips10(region);
865             System.out.println(
866                     "        <territoryCodes"
867                             + " type=\""
868                             + region
869                             + "\""
870                             + (numeric == null ? "" : " numeric=\"" + numeric + "\"")
871                             + (alpha3 == null ? "" : " alpha3=\"" + alpha3 + "\"")
872                             + (fips10 == null || fips10.equals(region)
873                                     ? ""
874                                     : " fips10=\"" + fips10 + "\"")
875                             + "/>");
876         }
877         System.out.println("    </codeMappings>");
878         System.out.println("<!-- end of Code Mappings generated with CountItems tool ...");
879         System.out.println(Joiner.on(CldrUtility.LINE_SEPARATOR).join(warnings));
880     }
881 
882     enum VariableType {
883         full,
884         partial
885     }
886 
getVariables(VariableType variableType)887     public static Map<String, String> getVariables(VariableType variableType) {
888         String sep = CldrUtility.LINE_SEPARATOR + "\t\t\t\t";
889         Map<String, String> variableSubstitutions = new LinkedHashMap<>();
890         for (String type : new String[] {"legacy", "territory", "script", "variant"}) {
891             Set<String> i;
892             i =
893                     (variableType == VariableType.full || type.equals("legacy"))
894                             ? sc.getAvailableCodes(type)
895                             : sc.getGoodAvailableCodes(type);
896             addVariable(variableSubstitutions, type, i, sep);
897         }
898 
899         Relation<String, String> bcp47Keys = supplementalData.getBcp47Keys();
900         Relation<R2<String, String>, String> aliases = supplementalData.getBcp47Aliases();
901         for (String key : bcp47Keys.keySet()) {
902             Set<String> keyAliases = aliases.getAll(Row.of(key, ""));
903             Set<String> rawsubtypes = bcp47Keys.getAll(key);
904             TreeSet<String> subtypes = new TreeSet<>();
905             for (String subtype : rawsubtypes) {
906                 Set<String> keySubtypeAliases = aliases.getAll(Row.of(key, subtype));
907                 if (keySubtypeAliases != null) {
908                     subtypes.addAll(keySubtypeAliases);
909                 }
910             }
911             subtypes.addAll(rawsubtypes);
912             String alias = (keyAliases == null ? key : keyAliases.iterator().next()) + "_XXX";
913             addVariable(variableSubstitutions, alias, subtypes, sep);
914         }
915         return variableSubstitutions;
916     }
917 
918     private static final Pattern BreakerPattern =
919             PatternCache.get("([-_A-Za-z0-9])[-/+_A-Za-z0-9]*");
920 
addVariable( Map<String, String> variableSubstitutions, String type, Set<String> sinput, String sep)921     private static void addVariable(
922             Map<String, String> variableSubstitutions,
923             String type,
924             Set<String> sinput,
925             String sep) {
926         TreeSet<String> s = new TreeSet<>(ROOT_PRIMARY_COLLATOR);
927         s.addAll(sinput);
928 
929         StringBuffer b = new StringBuffer();
930         for (String code : s) {
931             if (b.length() != 0) b.append(' ');
932             b.append(code);
933         }
934         // "((?:[-+_A-Za-z0-9]+[/])+[A-Za-z0-9])[-+_A-Za-z0-9]*"
935         String broken = CldrUtility.breakLines(b, sep, BreakerPattern.matcher(""), 80);
936         assert (b.toString().equals(broken.replace(sep, " ")));
937         variableSubstitutions.put(
938                 type,
939                 "\t\t\t<variable id=\"$"
940                         + type
941                         + "\" type=\"choice\">"
942                         + broken
943                         + CldrUtility.LINE_SEPARATOR
944                         + "\t\t\t</variable>");
945     }
946 
checkCodes( String type, StandardCodes sc, Map<String, Map<String, R2<List<String>, String>>> localeAliasInfo, Map<String, Map<String, Map<String, String>>> fullData)947     private static void checkCodes(
948             String type,
949             StandardCodes sc,
950             Map<String, Map<String, R2<List<String>, String>>> localeAliasInfo,
951             Map<String, Map<String, Map<String, String>>> fullData) {
952         Map<String, Map<String, String>> typeData =
953                 fullData.get("territory".equals(type) ? "region" : type);
954         Map<String, R2<List<String>, String>> aliasInfo = localeAliasInfo.get(type);
955         for (String code : sc.getAvailableCodes(type)) {
956             Map<String, String> subdata = typeData.get(code);
957             String deprecated = subdata.get("Deprecated");
958             if (deprecated == null) continue;
959             String replacement = subdata.get("Preferred-Value");
960             R2<List<String>, String> supplementalReplacements = aliasInfo.get(code);
961             if (supplementalReplacements == null) {
962                 System.out.println(
963                         "Deprecated in LSTR, but not in supplementalData: "
964                                 + type
965                                 + "\t"
966                                 + code
967                                 + "\t"
968                                 + replacement);
969             }
970         }
971     }
972 
addRegions( CLDRFile english, Set<String> availableCodes, String codeType, String[] exceptions, Transform<String, String> trans)973     private static void addRegions(
974             CLDRFile english,
975             Set<String> availableCodes,
976             String codeType,
977             String[] exceptions,
978             Transform<String, String> trans) {
979         Set<String> missingRegions = new TreeSet<>();
980         Set<String> exceptionSet = new HashSet<>(Arrays.asList(exceptions));
981         List<String> duplicateDestroyer = new ArrayList<>();
982         for (String region : availableCodes) {
983 
984             if (exceptionSet.contains(region)) continue;
985             String alpha3 = trans.transform(region);
986             if (alpha3 == null) {
987                 missingRegions.add(region);
988                 continue;
989             }
990             Map<String, R2<List<String>, String>> territoryAliasInfo =
991                     supplementalData.getLocaleAliasInfo().get("territory");
992             String result;
993             if (territoryAliasInfo.containsKey(region)) {
994                 result = Joiner.on(" ").join(territoryAliasInfo.get(region).get0());
995             } else {
996                 result = region;
997             }
998             String name = english.getName(CLDRFile.TERRITORY_NAME, result);
999             if (!(duplicateDestroyer.contains(alpha3 + result + name))) {
1000                 duplicateDestroyer.add(alpha3 + result + name);
1001                 System.out.println(
1002                         "\t\t\t<territoryAlias type=\""
1003                                 + alpha3
1004                                 + "\" replacement=\""
1005                                 + result
1006                                 + "\" reason=\"overlong\"/> <!-- "
1007                                 + name
1008                                 + " -->");
1009             }
1010         }
1011         for (String region : missingRegions) {
1012             String name = english.getName(CLDRFile.TERRITORY_NAME, region);
1013             System.err.println("ERROR: Missing " + codeType + " code for " + region + "\t" + name);
1014         }
1015     }
1016 
1017     /** */
toString(Collection aliases, String separator)1018     private static String toString(Collection aliases, String separator) {
1019         StringBuffer result = new StringBuffer();
1020         boolean first = true;
1021         for (Iterator<Object> it = aliases.iterator(); it.hasNext(); ) {
1022             Object item = it.next();
1023             if (first) first = false;
1024             else result.append(separator);
1025             result.append(item);
1026         }
1027         return result.toString();
1028     }
1029 
showZoneInfo()1030     public static void showZoneInfo() throws IOException {
1031         StandardCodes sc = StandardCodes.make();
1032         Map<String, String> m = sc.getZoneLinkold_new();
1033         int i = 0;
1034         System.out.println("/* Generated by org.unicode.cldr.tool.CountItems */");
1035         System.out.println();
1036         i = 0;
1037         System.out.println("/* zoneID, canonical zoneID */");
1038         for (Iterator<String> it = m.keySet().iterator(); it.hasNext(); ) {
1039             String old = it.next();
1040             String newOne = m.get(old);
1041             System.out.println("{\"" + old + "\", \"" + newOne + "\"},");
1042             ++i;
1043         }
1044         System.out.println("/* Total: " + i + " */");
1045 
1046         System.out.println();
1047         i = 0;
1048         System.out.println("/* All canonical zoneIDs */");
1049         for (Iterator<String> it = sc.getZoneData().keySet().iterator(); it.hasNext(); ) {
1050             String old = it.next();
1051             System.out.println("\"" + old + "\",");
1052             ++i;
1053         }
1054         System.out.println("/* Total: " + i + " */");
1055 
1056         Factory mainCldrFactory =
1057                 Factory.make(CLDRPaths.COMMON_DIRECTORY + "main" + File.separator, ".*");
1058         CLDRFile desiredLocaleFile = mainCldrFactory.make("root", true);
1059         String temp = desiredLocaleFile.getFullXPath("//ldml/dates/timeZoneNames/singleCountries");
1060         XPathParts parts = XPathParts.getFrozenInstance(temp);
1061         String singleCountriesList = parts.findAttributes("singleCountries").get("list");
1062         Set<String> singleCountriesSet =
1063                 new TreeSet<>(CldrUtility.splitList(singleCountriesList, ' '));
1064 
1065         Map<String, String> zone_countries = StandardCodes.make().getZoneToCounty();
1066         Map<String, Set<String>> countries_zoneSet = StandardCodes.make().getCountryToZoneSet();
1067         System.out.println();
1068         i = 0;
1069         System.out.println("/* zoneID, country, isSingle */");
1070         for (Iterator<String> it = zone_countries.keySet().iterator(); it.hasNext(); ) {
1071             String old = it.next();
1072             String newOne = zone_countries.get(old);
1073             Set<String> s = countries_zoneSet.get(newOne);
1074             String isSingle =
1075                     (s != null && s.size() == 1 || singleCountriesSet.contains(old)) ? "T" : "F";
1076             System.out.println("{\"" + old + "\", \"" + newOne + "\", \"" + isSingle + "\"},");
1077             ++i;
1078         }
1079         System.out.println("/* Total: " + i + " */");
1080 
1081         if (true) return;
1082 
1083         Factory cldrFactory = Factory.make(CLDRPaths.MAIN_DIRECTORY, ".*");
1084         Map<Organization, Map<String, Level>> platform_locale_status =
1085                 StandardCodes.make().getLocaleTypes();
1086         Map<String, Level> onlyLocales = platform_locale_status.get(Organization.ibm);
1087         Set<String> locales = onlyLocales.keySet();
1088         CLDRFile english = cldrFactory.make("en", true);
1089         for (Iterator<String> it = locales.iterator(); it.hasNext(); ) {
1090             String locale = it.next();
1091             System.out.println(
1092                     locale + "\t" + english.getName(locale) + "\t" + onlyLocales.get(locale));
1093         }
1094     }
1095 
1096     static final NumberFormat decimal = NumberFormat.getNumberInstance();
1097 
1098     static {
1099         decimal.setGroupingUsed(true);
1100     }
1101 
countItems()1102     public static void countItems() {
1103         // CLDRKey.main(new String[]{"-mde.*"});
1104         String dir = CldrUtility.getProperty("source", CLDRPaths.MAIN_DIRECTORY);
1105         Factory cldrFactory = Factory.make(dir, ".*");
1106         countItems(cldrFactory, false);
1107     }
1108 
1109     /**
1110      * @param cldrFactory
1111      * @param resolved
1112      */
countItems(Factory cldrFactory, boolean resolved)1113     private static int countItems(Factory cldrFactory, boolean resolved) {
1114         int count = 0;
1115         int resolvedCount = 0;
1116         Set<String> locales = cldrFactory.getAvailable();
1117         Set<String> keys = new HashSet<>();
1118         Set<String> values = new HashSet<>();
1119         Set<String> fullpaths = new HashSet<>();
1120         Matcher alt = CLDRFile.ALT_PROPOSED_PATTERN.matcher("");
1121 
1122         Set<String> temp = new HashSet<>();
1123         for (Iterator<String> it = locales.iterator(); it.hasNext(); ) {
1124             String locale = it.next();
1125             if (CLDRFile.isSupplementalName(locale)) continue;
1126             CLDRFile item = cldrFactory.make(locale, false);
1127 
1128             temp.clear();
1129             for (Iterator<String> it2 = item.iterator(); it2.hasNext(); ) {
1130                 String path = it2.next();
1131                 if (alt.reset(path).matches()) {
1132                     continue;
1133                 }
1134                 temp.add(path);
1135                 keys.add(path);
1136                 values.add(item.getStringValue(path));
1137                 fullpaths.add(item.getFullXPath(path));
1138             }
1139             int current = temp.size();
1140 
1141             CLDRFile itemResolved = cldrFactory.make(locale, true);
1142             temp.clear();
1143             itemResolved.forEach(temp::add);
1144             int resolvedCurrent = temp.size();
1145 
1146             System.out.println(
1147                     locale
1148                             + "\tPlain:\t"
1149                             + current
1150                             + "\tResolved:\t"
1151                             + resolvedCurrent
1152                             + "\tUnique Paths:\t"
1153                             + keys.size()
1154                             + "\tUnique Values:\t"
1155                             + values.size()
1156                             + "\tUnique Full Paths:\t"
1157                             + fullpaths.size());
1158             count += current;
1159             resolvedCount += resolvedCurrent;
1160         }
1161         System.out.println("Total Items\t" + decimal.format(count));
1162         System.out.println("Total Resolved Items\t" + decimal.format(resolvedCount));
1163         System.out.println("Unique Paths\t" + decimal.format(keys.size()));
1164         System.out.println("Unique Values\t" + decimal.format(values.size()));
1165         System.out.println("Unique Full Paths\t" + decimal.format(fullpaths.size()));
1166         return count;
1167     }
1168 }
1169