1 package org.unicode.cldr.tool; 2 3 import java.io.IOException; 4 import java.util.Arrays; 5 import java.util.stream.Collectors; 6 7 import org.unicode.cldr.tool.FormattedFileWriter.Anchors; 8 import org.unicode.cldr.util.CLDRConfig; 9 import org.unicode.cldr.util.CLDRFile; 10 import org.unicode.cldr.util.CLDRURLS; 11 import org.unicode.cldr.util.SupplementalDataInfo; 12 13 import com.ibm.icu.text.ListFormatter; 14 import com.ibm.icu.util.ICUUncheckedIOException; 15 import com.ibm.icu.util.ULocale; 16 17 /** 18 * To add a new chart, subclass this, and add the subclass to {@link ShowLanguages.printLanguageData()}. There isn't much 19 * documentation, so best to look at a simple subclass to see how it works. 20 * @author markdavis 21 */ 22 public abstract class Chart { 23 public static final CLDRConfig CONFIG = CLDRConfig.getInstance(); 24 public static final SupplementalDataInfo SDI = CONFIG.getSupplementalDataInfo(); 25 public static final CLDRFile ENGLISH = CONFIG.getEnglish(); 26 public static final String LS = System.lineSeparator(); 27 28 public static final String PREV_CHART_VERSION_DIRECTORY = ToolConstants.getBaseDirectory(ToolConstants.PREV_CHART_VERSION); 29 public static final String CHART_VERSION_DIRECTORY = ToolConstants.getBaseDirectory(ToolConstants.CHART_VERSION); 30 31 public static final String GITHUB_ROOT = CLDRURLS.CLDR_REPO_ROOT + "/blob/main/"; 32 public static final String LDML_SPEC = "https://unicode.org/reports/tr35/"; 33 dataScrapeMessage(String specPart, String testFile, String... dataFiles)34 public static String dataScrapeMessage(String specPart, String testFile, String... dataFiles) { 35 final String dataFileList = dataFiles.length == 0 ? null : 36 ListFormatter.getInstance(ULocale.ENGLISH).format( 37 Arrays.asList(dataFiles).stream() 38 .map(dataFile -> Chart.dataFileLink(dataFile)) 39 .collect(Collectors.toSet())); 40 41 return "<p>" 42 + "<b>Warning:</b> Do not scrape this chart for production data.\n" 43 + "Instead, for the meaning of the fields and data consult the " + Chart.ldmlSpecLink(specPart) 44 + (dataFileList == null ? "" : ", and for machine-readable source data, access " + dataFileList) 45 + (testFile == null ? "" : ", and for test data, access " + dataFileLink(testFile)) 46 + ".</p>\n"; 47 } 48 dataFileLink(String dataFile)49 private static String dataFileLink(String dataFile) { 50 return "<a href='" + GITHUB_ROOT + dataFile + "' target='" + dataFile + "'>" + dataFile + "</a>"; 51 } 52 ldmlSpecLink(String specPart)53 public static String ldmlSpecLink(String specPart) { 54 return "<a href='" + LDML_SPEC + (specPart == null ? "" : specPart) + "' target='units.xml'>LDML specification</a>"; 55 } 56 57 /** 58 * null means a string will be constructed from the title. Otherwise a real file name (no html extension). 59 * @return 60 */ getFileName()61 public String getFileName() { 62 return null; 63 } 64 65 /** 66 * Show Date? 67 * @return 68 */ getExplanation()69 public String getExplanation() { 70 return null; 71 } 72 73 /** 74 * Short explanation that will go just after the title/dates. 75 * @return 76 */ getShowDate()77 public boolean getShowDate() { 78 return true; 79 } 80 81 /** 82 * Directory for the file to go into. 83 * @return 84 */ getDirectory()85 public abstract String getDirectory(); 86 87 /** 88 * Short title for page. Will appear at the top, and in the window title, and in the index. 89 * @return 90 */ getTitle()91 public abstract String getTitle(); 92 93 /** 94 * Work 95 * @param pw 96 * @throws IOException 97 */ writeContents(FormattedFileWriter pw)98 public abstract void writeContents(FormattedFileWriter pw) throws IOException; 99 writeFooter(FormattedFileWriter pw)100 public void writeFooter(FormattedFileWriter pw) throws IOException { 101 standardFooter(pw, AnalyticsID.CLDR); 102 } 103 104 private enum AnalyticsID { 105 CLDR("UA-7672775-1"), ICU("UA-7670213-1"), ICU_GUIDE("UA-7670256-1"), UNICODE("UA-7670213-1"), UNICODE_UTILITY("UA-8314904-1"); 106 public final String id; 107 AnalyticsID(String id)108 private AnalyticsID(String id) { 109 this.id = id; 110 } 111 } 112 standardFooter(FormattedFileWriter pw, AnalyticsID analytics)113 private static void standardFooter(FormattedFileWriter pw, AnalyticsID analytics) throws IOException { 114 pw.write("<div style='text-align: center; margin-top:2em; margin-bottom: 60em;'><br>\n" 115 + "<a href='https://www.unicode.org/copyright.html'>\n" 116 + "<img src='https://www.unicode.org/img/hb_notice.gif' style='border-style: none; width: 216px; height:50px;' alt='Access to Copyright and terms of use'>" 117 + "</a>\n" 118 + "</div><script>\n\n" 119 + "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){" 120 + "(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o)," 121 + "m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)" 122 + "})(window,document,'script','//www.google-analytics.com/analytics.js','ga');" 123 + " ga('create', '" 124 + analytics 125 + "', 'auto');" 126 + " ga('send', 'pageview');" 127 + "</script>\n"); 128 } 129 writeChart(Anchors anchors)130 public final void writeChart(Anchors anchors) { 131 try ( 132 FormattedFileWriter x = new FormattedFileWriter(getFileName(), getTitle(), getExplanation(), anchors);) { 133 x.setDirectory(getDirectory()); 134 x.setShowDate(getShowDate()); 135 writeContents(x); 136 writeFooter(x); 137 } catch (IOException e) { 138 throw new ICUUncheckedIOException(e); 139 } 140 } 141 getTsvDir(String targetDir, String topicName)142 public static String getTsvDir(String targetDir, String topicName) { 143 String target = targetDir.replaceAll(topicName, "tsv"); 144 if (target.equals(targetDir)) { 145 throw new IllegalArgumentException("Can't make TSV directory from " + targetDir); 146 } 147 return target; 148 } 149 } 150