1 package org.unicode.cldr.tool; 2 3 import static org.unicode.cldr.util.XMLSource.CODE_FALLBACK_ID; 4 5 import java.io.BufferedReader; 6 import java.io.FileInputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.InputStreamReader; 10 import java.nio.charset.StandardCharsets; 11 import java.util.Set; 12 import org.unicode.cldr.test.DisplayAndInputProcessor; 13 import org.unicode.cldr.tool.Option.Options; 14 import org.unicode.cldr.util.*; 15 import org.unicode.cldr.util.CLDRFile.Status; 16 import org.unicode.cldr.util.XMLSource.SourceLocation; 17 18 @CLDRTool(alias = "pathinfo", description = "Get information about paths such as inheritance") 19 public class PathInfo { 20 static final Options options = 21 new Options(PathInfo.class) 22 .add("locale", ".*", "und", "Locale ID for the path info") 23 .add("infile", ".*", null, "File to read paths from or '--infile=-' for stdin") 24 .add("nosource", "Don’t print the XML Source line") 25 .add("OutputDaip", ".*", "run a string through DAIP for output") 26 .add("InputDaip", ".*", "run a string through DAIP for input"); 27 main(String args[])28 public static void main(String args[]) throws IOException { 29 final Set<String> paths = options.parse(args, true); 30 31 final String inPath = options.get("infile").getValue(); 32 if (inPath != null) { 33 if (inPath.equals("-")) { 34 addLines(System.in, paths); 35 } else { 36 addLines(inPath, paths); 37 } 38 } 39 40 if (paths.isEmpty()) { 41 System.err.println("Error: No paths were specified."); 42 System.out.println(options.getHelp()); 43 System.exit(1); 44 } 45 46 CLDRFile file = null; 47 48 final String locale = options.get("locale").getValue(); 49 try { 50 file = CLDRConfig.getInstance().getCLDRFile(locale, true); 51 } catch (Throwable t) { 52 System.err.println("Could not load locale " + locale + " due to " + t); 53 } 54 55 showPaths(paths, file); 56 if (file == null) { 57 System.err.println("To enable inheritance lookup, use a different path."); 58 } 59 } 60 showPaths(final Set<String> paths, CLDRFile file)61 private static void showPaths(final Set<String> paths, CLDRFile file) { 62 boolean prePopulated = false; 63 boolean hadStringMisses = false; 64 65 for (final String path : paths) { 66 if (path.startsWith("//")) { 67 showPath(path, file); 68 } else { 69 if (!prePopulated && file != null) { 70 // scan all possible XPaths 71 System.err.println("INFO: Scanning all possible xpaths for hex IDs..."); 72 file.getExtraPaths().forEach(x -> StringId.getHexId(x)); 73 file.fullIterable().forEach(x -> StringId.getHexId(x)); 74 prePopulated = true; 75 } 76 final String xpath = StringId.getStringFromHexId(path); 77 if (xpath == null) { 78 System.err.println( 79 "• ERROR: could not find hex id " 80 + path 81 + " - may not have been seen yet."); 82 hadStringMisses = true; 83 } 84 showPath(xpath, file); 85 } 86 } 87 if (hadStringMisses) { 88 System.err.println("ERROR: One or more XPaths could not be converted from hex form."); 89 if (file == null) { 90 System.err.println("Tip: Set a locale ID with -l when using hex ids"); 91 } 92 System.exit(1); 93 } 94 } 95 showPath(final String path, CLDRFile file)96 private static void showPath(final String path, CLDRFile file) { 97 final boolean nosource = options.get("nosource").doesOccur(); 98 System.out.println("-------------------\n"); 99 System.out.println("• " + path); 100 System.out.println("• " + StringId.getHexId(path)); 101 // TODO: PathHeader, etc. 102 if (file == null) { 103 return; 104 } 105 final String dPath = CLDRFile.getDistinguishingXPath(path, null); 106 if (dPath != null && !dPath.equals(path)) { 107 System.out.println("• Distinguishing: " + dPath); 108 System.out.println("• Distinguishing:" + StringId.getHexId(dPath)); 109 } 110 System.out.println("• Value: " + file.getStringValue(dPath)); 111 // File lookup 112 if (!nosource) { 113 SourceLocation source = file.getSourceLocation(path); 114 if (source != null) { 115 System.out.println(source + " XML Source Location"); 116 } 117 } 118 // Inheritance lookup 119 final String fullPath = file.getFullXPath(path); 120 if (!fullPath.equals(path)) { 121 System.out.println("• Full path: " + fullPath); 122 System.out.println("• Full path: " + StringId.getHexId(fullPath)); 123 } 124 125 Option inputDaip = options.get("InputDaip"); 126 Option outputDaip = options.get("OutputDaip"); 127 if (inputDaip.doesOccur() || outputDaip.doesOccur()) { 128 DisplayAndInputProcessor daip = new DisplayAndInputProcessor(file); 129 if (inputDaip.doesOccur()) { 130 String input = inputDaip.getValue(); 131 System.out.println("INPUT: " + input); 132 Exception[] e = new Exception[1]; 133 final String raw = daip.processInput(path, input, e); 134 System.out.println("RAW<<: " + raw); 135 if (e.length > 0) { 136 for (final Exception ex : e) { 137 System.err.println(ex); 138 } 139 } 140 } 141 if (outputDaip.doesOccur()) { 142 String output = outputDaip.getValue(); 143 System.out.println("RAW : " + output); 144 final String disp = daip.processForDisplay(path, output); 145 System.out.println("DISP>>: " + disp); 146 } 147 return; // skip inheritance chain 148 } 149 150 // inheritance 151 Status status = new Status(); 152 if (false) { 153 // For debugging: compare the below to calling getSourceLocaleIdExtended directly. 154 final String xlocale = file.getSourceLocaleIdExtended(dPath, status, true, null); 155 System.out.println("• SLIE = " + xlocale + ":" + status.pathWhereFound); 156 } 157 System.out.println("• Inheritance chain:"); 158 for (final LocaleInheritanceInfo e : file.getPathsWhereFound(dPath)) { 159 System.out.print(" "); 160 if (e.getReason().isTerminal()) { 161 System.out.print("•"); // terminal 162 } else { 163 System.out.print("|"); // non-terminal 164 } 165 System.out.println(" " + e); // reason : locale + xpath 166 if (e.getAttribute() != null) { 167 System.out.println(" attribute=" + e.getAttribute()); 168 } 169 if (e.getLocale() != null 170 && e.getPath() != null 171 && !e.getLocale().equals(CODE_FALLBACK_ID)) { 172 final CLDRFile subFile = CLDRConfig.getInstance().getCLDRFile(e.getLocale(), false); 173 SourceLocation subsource = subFile.getSourceLocation(e.getPath()); 174 if (subsource != null && !nosource) { 175 System.out.println(" " + subsource + " XML Source"); 176 } 177 } 178 } 179 } 180 181 @SuppressWarnings("unchecked") addLines(final InputStream in, Set<String> set)182 private static void addLines(final InputStream in, Set<String> set) throws IOException { 183 try (BufferedReader br = 184 new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { 185 With.in(new FileReaders.ReadLineSimpleIterator(br)) 186 .forEach( 187 str -> { 188 if (!str.isBlank()) { 189 set.add(str.trim()); 190 } 191 }); 192 } 193 } 194 addLines(final String path, Set<String> set)195 private static void addLines(final String path, Set<String> set) throws IOException { 196 try (FileInputStream fis = new FileInputStream(path)) { 197 addLines(fis, set); 198 } 199 } 200 } 201