1 package org.unicode.cldr.tool; 2 3 import com.ibm.icu.text.ListFormatter; 4 import com.ibm.icu.util.ICUUncheckedIOException; 5 import com.ibm.icu.util.ULocale; 6 import java.io.IOException; 7 import java.io.OutputStream; 8 import java.io.OutputStreamWriter; 9 import java.io.Writer; 10 import java.util.Arrays; 11 import java.util.stream.Collectors; 12 import org.unicode.cldr.tool.FormattedFileWriter.Anchors; 13 import org.unicode.cldr.util.CLDRConfig; 14 import org.unicode.cldr.util.CLDRFile; 15 import org.unicode.cldr.util.CLDRURLS; 16 import org.unicode.cldr.util.Factory; 17 import org.unicode.cldr.util.PathHeader; 18 import org.unicode.cldr.util.SupplementalDataInfo; 19 import org.unicode.cldr.util.VoterReportStatus.ReportId; 20 21 /** 22 * To add a new chart, subclass this, and add the subclass to {@link 23 * ShowLanguages.printLanguageData()}. There isn't much documentation, so best to look at a simple 24 * subclass to see how it works. 25 * 26 * @author markdavis 27 */ 28 public abstract class Chart { 29 public static final CLDRConfig CONFIG = CLDRConfig.getInstance(); 30 public static final SupplementalDataInfo SDI = CONFIG.getSupplementalDataInfo(); 31 public static final CLDRFile ENGLISH = CONFIG.getEnglish(); 32 public static final String LS = System.lineSeparator(); 33 34 public static final String PREV_CHART_VERSION_DIRECTORY = 35 ToolConstants.getBaseDirectory(ToolConstants.PREV_CHART_VERSION); 36 public static final String CHART_VERSION_DIRECTORY = 37 ToolConstants.getBaseDirectory(ToolConstants.CHART_VERSION); 38 39 public static final String GITHUB_ROOT = CLDRURLS.CLDR_REPO_ROOT + "/blob/main/"; 40 public static final String LDML_SPEC = "https://unicode.org/reports/tr35/"; 41 dataScrapeMessage(String specPart, String testFile, String... dataFiles)42 public static String dataScrapeMessage(String specPart, String testFile, String... dataFiles) { 43 final String dataFileList = 44 dataFiles.length == 0 45 ? null 46 : ListFormatter.getInstance(ULocale.ENGLISH) 47 .format( 48 Arrays.asList(dataFiles).stream() 49 .map(dataFile -> Chart.dataFileLink(dataFile)) 50 .collect(Collectors.toSet())); 51 52 return "<p>" 53 + "<b>Warning:</b> Do not scrape this chart for production data.\n" 54 + "Instead, for the meaning of the fields and data consult the " 55 + Chart.ldmlSpecLink(specPart) 56 + (dataFileList == null 57 ? "" 58 : ", and for machine-readable source data, access " + dataFileList) 59 + (testFile == null ? "" : ", and for test data, access " + dataFileLink(testFile)) 60 + ".</p>\n"; 61 } 62 dataFileLink(String dataFile)63 private static String dataFileLink(String dataFile) { 64 return "<a href='" 65 + GITHUB_ROOT 66 + dataFile 67 + "' target='" 68 + dataFile 69 + "'>" 70 + dataFile 71 + "</a>"; 72 } 73 ldmlSpecLink(String specPart)74 public static String ldmlSpecLink(String specPart) { 75 return "<a href='" 76 + LDML_SPEC 77 + (specPart == null ? "" : specPart) 78 + "' target='units.xml'>LDML specification</a>"; 79 } 80 81 /** 82 * null means a string will be constructed from the title. Otherwise a real file name (no html 83 * extension). 84 * 85 * @return 86 */ getFileName()87 public String getFileName() { 88 return null; 89 } 90 91 /** 92 * Show Date? 93 * 94 * @return 95 */ getExplanation()96 public String getExplanation() { 97 return null; 98 } 99 100 /** 101 * Short explanation that will go just after the title/dates. 102 * 103 * @return 104 */ getShowDate()105 public boolean getShowDate() { 106 return true; 107 } 108 109 /** 110 * Directory for the file to go into. 111 * 112 * @return 113 */ getDirectory()114 public abstract String getDirectory(); 115 116 /** 117 * Short title for page. Will appear at the top, and in the window title, and in the index. 118 * 119 * @return 120 */ getTitle()121 public abstract String getTitle(); 122 123 /** 124 * Work 125 * 126 * @param pw 127 * @throws IOException 128 */ writeContents(FormattedFileWriter pw)129 public void writeContents(FormattedFileWriter pw) throws IOException { 130 writeContents(pw.getStringWriter()); 131 } 132 133 /** 134 * Helper function to use the default factory. Not for use within SurveyTool. 135 * 136 * @param pw 137 * @throws IOException 138 */ writeContents(Writer pw)139 public void writeContents(Writer pw) throws IOException { 140 writeContents(pw, CLDRConfig.getInstance().getCldrFactory()); 141 } 142 writeContents(OutputStream output, Factory factory)143 public void writeContents(OutputStream output, Factory factory) throws IOException { 144 try (final Writer w = new OutputStreamWriter(output); ) { 145 writeContents(w, factory); 146 } 147 } 148 149 /** 150 * Do the work of generating the chart. 151 * 152 * @param pw 153 * @param factory 154 * @throws IOException 155 */ writeContents(Writer pw, Factory factory)156 public void writeContents(Writer pw, Factory factory) throws IOException { 157 // TODO: this should be an abstract function. 158 throw new IllegalArgumentException("Not implemented yet"); 159 } 160 161 private static final class AnalyticsHelper { 162 private static final AnalyticsHelper INSTANCE = new AnalyticsHelper(); 163 164 public final String str; 165 AnalyticsHelper()166 AnalyticsHelper() { 167 str = 168 ToolUtilities.getUTF8Data("analytics.html") 169 .lines() 170 .collect(Collectors.joining("\n")); 171 } 172 } 173 174 public enum AnalyticsID { 175 CLDR("G-BPN1D3SEJM"), 176 ICU("G-06PL1DM20S"), 177 ICU_GUIDE("UA-7670256-1"), 178 UNICODE("G-GC4HXC4GVQ"), 179 UNICODE_UTILITY("G-0M7Q5QLZPV"); 180 public final String id; 181 AnalyticsID(String id)182 private AnalyticsID(String id) { 183 this.id = id; 184 } 185 getScript()186 public String getScript() { 187 return AnalyticsHelper.INSTANCE.str.replaceAll("TAG_ID", id); 188 } 189 } 190 writeChart(Anchors anchors)191 public final void writeChart(Anchors anchors) { 192 try (FormattedFileWriter x = 193 new FormattedFileWriter(getFileName(), getTitle(), getExplanation(), anchors); ) { 194 x.setDirectory(getDirectory()); 195 x.setShowDate(getShowDate()); 196 writeContents(x); 197 } catch (IOException e) { 198 throw new ICUUncheckedIOException(e); 199 } 200 } 201 getTsvDir(String targetDir, String topicName)202 public static String getTsvDir(String targetDir, String topicName) { 203 String target = targetDir.replaceAll(topicName, "tsv"); 204 if (target.equals(targetDir)) { 205 throw new IllegalArgumentException("Can't make TSV directory from " + targetDir); 206 } 207 return target; 208 } 209 getFixLinkFromPath(CLDRFile cldrFile, String path)210 public String getFixLinkFromPath(CLDRFile cldrFile, String path) { 211 String result = PathHeader.getLinkedView(CLDRConfig.getInstance().urls(), cldrFile, path); 212 return result == null ? "" : result; 213 } 214 215 /** 216 * Attempt to allocate the Chart that goes along with this report Also see {@link 217 * org.unicode.cldr.util.VoterReportStatus.ReportId} and keep up to date 218 */ forReport(final ReportId report, final String locale)219 public static Chart forReport(final ReportId report, final String locale) { 220 switch (report) { 221 case personnames: 222 return new ChartPersonName(locale); 223 default: 224 return null; 225 } 226 } 227 } 228