xref: /aosp_15_r20/external/cldr/tools/cldr-code/src/main/java/org/unicode/cldr/tool/CompareResolved.java (revision 912701f9769bb47905792267661f0baf2b85bed5)
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