• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ******************************************************************************
3  * Copyright (C) 2005-2010, International Business Machines Corporation and        *
4  * others. All Rights Reserved.                                               *
5  ******************************************************************************
6  */
7 package org.unicode.cldr.tool;
8 
9 import java.io.BufferedReader;
10 import java.io.IOException;
11 import java.io.PrintWriter;
12 import java.util.Arrays;
13 import java.util.Collections;
14 import java.util.Date;
15 import java.util.HashSet;
16 import java.util.Iterator;
17 import java.util.Map;
18 import java.util.Map.Entry;
19 import java.util.Set;
20 import java.util.TreeMap;
21 import java.util.TreeSet;
22 
23 import org.unicode.cldr.draft.FileUtilities;
24 import org.unicode.cldr.test.CoverageLevel2;
25 import org.unicode.cldr.util.CLDRConfig;
26 import org.unicode.cldr.util.CLDRFile;
27 import org.unicode.cldr.util.CLDRPaths;
28 import org.unicode.cldr.util.CldrUtility;
29 import org.unicode.cldr.util.CldrUtility.VariableReplacer;
30 import org.unicode.cldr.util.ExtractCollationRules;
31 import org.unicode.cldr.util.Factory;
32 import org.unicode.cldr.util.FileCopier;
33 import org.unicode.cldr.util.LanguageTagParser;
34 import org.unicode.cldr.util.Level;
35 import org.unicode.cldr.util.LocaleIDParser;
36 import org.unicode.cldr.util.PathHeader;
37 import org.unicode.cldr.util.PathHeader.SectionId;
38 import org.unicode.cldr.util.TransliteratorUtilities;
39 
40 import com.ibm.icu.dev.tool.UOption;
41 import com.ibm.icu.dev.util.CollectionUtilities;
42 import com.ibm.icu.impl.Relation;
43 import com.ibm.icu.lang.UScript;
44 import com.ibm.icu.text.Collator;
45 import com.ibm.icu.text.RuleBasedCollator;
46 import com.ibm.icu.text.Transliterator;
47 import com.ibm.icu.text.UnicodeSet;
48 import com.ibm.icu.text.UnicodeSetIterator;
49 import com.ibm.icu.util.ULocale;
50 
51 public class ShowData {
52     private static final int HELP1 = 0, HELP2 = 1, SOURCEDIR = 2, DESTDIR = 3,
53         MATCH = 4, GET_SCRIPTS = 5,
54         LAST_DIR = 6,
55         COVERAGE = 7;
56 
57     private static final UOption[] options = {
58         UOption.HELP_H(),
59         UOption.HELP_QUESTION_MARK(),
60         UOption.SOURCEDIR().setDefault(CLDRPaths.MAIN_DIRECTORY),
61         UOption.DESTDIR().setDefault(CLDRPaths.CHART_DIRECTORY + "summary/"),
62         UOption.create("match", 'm', UOption.REQUIRES_ARG).setDefault(".*"),
63         UOption.create("getscript", 'g', UOption.NO_ARG),
64         UOption.create("last", 'l', UOption.REQUIRES_ARG).setDefault(CLDRPaths.LAST_DIRECTORY + "common/main/"),
65         UOption.create("coverage", 'c', UOption.REQUIRES_ARG).setDefault(Level.MODERN.toString()),
66     };
67 
dateFooter()68     public static String dateFooter() {
69         return "<p>Generation: " + CldrUtility.isoFormatDateOnly(new java.util.Date()) + "</p>" +
70             System.lineSeparator();
71     }
72 
73     static RuleBasedCollator uca = (RuleBasedCollator) Collator
74         .getInstance(ULocale.ROOT);
75 
76     {
77         uca.setNumericCollation(true);
78     }
79 
80     static PathHeader.Factory prettyPathMaker = PathHeader.getFactory(CLDRConfig.getInstance().getEnglish());
81 
82     static CLDRFile english;
83 
84     static Set<String> locales;
85 
86     static Relation<String, String> parentToChildren = Relation.of(new TreeMap<String, Set<String>>(), TreeSet.class);
87 
88     static Factory cldrFactory;
89 
main(String[] args)90     public static void main(String[] args) throws Exception {
91         // String p =
92         // prettyPathMaker.getPrettyPath("//ldml/characters/exemplarCharacters[@alt=\"proposed-u151-4\"]");
93         // String q = prettyPathMaker.getOriginal(p);
94 
95         double deltaTime = System.currentTimeMillis();
96         try {
97             CLDRConfig testInfo = ToolConfig.getToolInstance();
98             UOption.parseArgs(args, options);
99             String sourceDir = options[SOURCEDIR].value; // Utility.COMMON_DIRECTORY
100             // + "main/";
101             String targetDir = options[DESTDIR].value; // Utility.GEN_DIRECTORY +
102             // "main/";
103             cldrFactory = Factory.make(sourceDir, ".*");
104             english = cldrFactory.make("en", true);
105             String lastSourceDir = options[LAST_DIR].value; // Utility.COMMON_DIRECTORY
106 
107             Level requiredCoverage = Level.fromString(options[COVERAGE].toString()); // Utility.COMMON_DIRECTORY
108 
109             if (options[GET_SCRIPTS].doesOccur) {
110                 getScripts();
111                 return;
112             }
113 
114             FileCopier.ensureDirectoryExists(options[DESTDIR].value);
115             FileCopier.copy(ShowData.class, "summary-index.css", options[DESTDIR].value, "index.css");
116             FileCopier.copy(ShowData.class, "summary-index.html", options[DESTDIR].value, "index.html");
117 
118             ToolUtilities.registerExtraTransliterators();
119 
120             // Factory collationFactory = Factory
121             // .make(sourceDir.replace("incoming/vetted/","common/") + "../collation/", ".*");
122             // ExtractCollationRules collationRules = new ExtractCollationRules();
123 
124             locales = new TreeSet<String>(cldrFactory.getAvailable());
125             new CldrUtility.MatcherFilter(options[MATCH].value).retainAll(locales);
126             // Set paths = new TreeSet();
127             Set<PathHeader> prettySet = new TreeSet<PathHeader>();
128 
129             CLDRFile.Status status = new CLDRFile.Status();
130             LocaleIDParser localeIDParser = new LocaleIDParser();
131 
132             //Map nonDistinguishingAttributes = new LinkedHashMap();
133             //CLDRFile parent = null;
134 
135             Map<PathHeader, Relation<String, String>> pathHeaderToValuesToLocale = new TreeMap<PathHeader, Relation<String, String>>();
136 
137             Set<String> defaultContents = testInfo.getSupplementalDataInfo().getDefaultContentLocales();
138 
139             // get all the locales in a group (with same written language)
140             LanguageTagParser ltp = new LanguageTagParser();
141 
142             LikelySubtags ls = new LikelySubtags();
143 
144             for (String locale : locales) {
145                 if (defaultContents.contains(locale)) {
146                     continue;
147                 }
148                 if (locale.startsWith("supplem") || locale.startsWith("character") || locale.equals("root")) {
149                     continue;
150                 }
151                 String max = ls.maximize(locale);
152                 if (max == null) {
153                     max = locale;
154                 }
155                 String baseLanguage = ls.minimize(ltp.set(max).getLanguageScript());
156                 if (baseLanguage.equals(locale)) {
157                     parentToChildren.put("root", locale);
158                     parentToChildren.put(locale, locale);
159                 } else {
160                     parentToChildren.put(baseLanguage, locale);
161                 }
162             }
163 
164             for (Entry<String, Set<String>> group : parentToChildren.keyValuesSet()) {
165                 String locale = group.getKey();
166                 Set<String> children = group.getValue();
167                 Map<String, CLDRFile> sublocales = new TreeMap<String, CLDRFile>();
168 
169                 boolean doResolved = localeIDParser.set(locale).getRegion().length() == 0;
170                 String languageSubtag = localeIDParser.getLanguage();
171                 //boolean isLanguageLocale = locale.equals(languageSubtag);
172 
173                 CLDRFile file = cldrFactory.make(locale, true);
174                 if (file.isNonInheriting())
175                     continue; // skip supplementals
176 
177                 // get all of the paths
178                 Set<String> allPaths = new HashSet<>();
179                 CollectionUtilities.addAll(file.iterator(), allPaths);
180 
181                 if (!locale.equals("root")) {
182                     for (String childLocale : children) {
183                         CLDRFile childCldrFile = cldrFactory.make(childLocale, false);
184                         if (childCldrFile != null) {
185                             CollectionUtilities.addAll(childCldrFile.iterator(), allPaths);
186                         }
187                         sublocales.put(childLocale, childCldrFile);
188                     }
189                 }
190 
191                 boolean showEnglish = !languageSubtag.equals("en");
192                 CoverageLevel2 coverageLevel = CoverageLevel2.getInstance(testInfo.getSupplementalDataInfo(), locale);
193 
194                 // put into set of simpler paths
195                 // and filter if necessary
196                 int skippedCount = 0;
197                 int aliasedCount = 0;
198                 int inheritedCount = 0;
199                 prettySet.clear();
200                 for (Iterator<String> it2 = allPaths.iterator(); it2.hasNext();) {
201                     String path = it2.next();
202                     if (path.indexOf("/alias") >= 0) {
203                         skippedCount++;
204                         continue; // skip code fllback
205                     }
206                     if (path.indexOf("/usesMetazone") >= 0) {
207                         skippedCount++;
208                         continue; // skip code fllback
209                     }
210                     if (path.indexOf("/references") >= 0) {
211                         skippedCount++;
212                         continue; // skip references
213                     }
214                     if (path.indexOf("[@alt=\"proposed") >= 0) {
215                         skippedCount++;
216                         continue; // skip code fllback
217                     }
218                     if (path.indexOf("/identity") >= 0) {
219                         skippedCount++;
220                         continue; // skip code fllback
221                     }
222                     PathHeader prettyString = prettyPathMaker.fromPath(path);
223                     if (prettyString.getSectionId() != SectionId.Special) {
224                         prettySet.add(prettyString);
225                     }
226                 }
227 
228                 PrintWriter pw = FileUtilities.openUTF8Writer(targetDir, locale + ".html");
229 
230                 String[] headerAndFooter = new String[2];
231 
232                 getChartTemplate(
233                     "Locale Data Summary for " + getLocaleNameAndCode(locale),
234                     ToolConstants.CHART_DISPLAY_VERSION,
235                     "<script type='text/javascript'>" + System.lineSeparator()
236                         + "if (location.href.split('?')[1].split(',')[0]=='hide') {" + System.lineSeparator()
237                         + "document.write('<style>');" + System.lineSeparator()
238                         + "document.write('.xx {display:none}');" + System.lineSeparator()
239                         + "document.write('</style>');" + System.lineSeparator() + "}" + System.lineSeparator()
240                         + "</script>",
241                     headerAndFooter, locale.equals("root") ? "Main Charts Index" : null, false);
242                 pw.println(headerAndFooter[0]);
243                 showLinks(pw, locale);
244                 showChildren(pw, locale);
245                 if (true) {
246                     pw.println("<p><b>Aliased/Inherited: </b><a href='" + locale
247                         + ".html?hide'>Hide</a> <a href='" + locale
248                         + ".html'>Show </a></p>");
249                 }
250                 pw.println("<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\">");
251 
252                 pw.println("<tr><th>No</th>"
253                     + "<th width='10%'>Section</th>"
254                     + "<th width='10%'>Page</th>"
255                     + "<th width='10%'>Header</th>"
256                     + "<th width='10%'>Code</th>"
257                     + (showEnglish ? "<th>English</th>" : "")
258                     + "<th>Native</th>"
259                     + "<th>Sublocales…</th>"
260                     + "</tr>");
261 
262                 int count = 0;
263                 PathHeader oldParts = null;
264 
265                 Relation<String, String> childValueToLocales = Relation.of(
266                     new TreeMap<String, Set<String>>(), TreeSet.class);
267 
268                 for (PathHeader prettyPath : prettySet) {
269                     String path = prettyPath.getOriginalPath();
270                     boolean zeroOutEnglish = path.indexOf("/references") < 0;
271 
272                     String source = file.getSourceLocaleID(path, status);
273                     boolean isAliased = !status.pathWhereFound.equals(path);
274                     if (isAliased) {
275                         aliasedCount++;
276                         continue;
277                     }
278                     String value = file.getStringValue(path);
279 
280                     //String baileyValue = file.getBaileyValue(path, null, null);
281                     boolean isInherited = !source.equals(locale); // !CldrUtility.equals(baileyValue, value);
282                     if (isInherited) {
283                         inheritedCount++;
284                     }
285 
286                     //StringBuffer tempDraftRef = new StringBuffer();
287 
288                     String lastValue = null;
289                     boolean lastEquals = false;
290 
291                     childValueToLocales.clear();
292 
293                     for (Entry<String, CLDRFile> s : sublocales.entrySet()) {
294                         String newChildValue = s.getValue().getStringValue(path);
295                         if (newChildValue == null || CldrUtility.equals(newChildValue, value)) {
296                             continue;
297                         }
298                         childValueToLocales.put(newChildValue, s.getKey());
299                     }
300 
301                     String englishValue = null;
302                     if (zeroOutEnglish) {
303                         englishValue = "";
304                     }
305                     if (showEnglish
306                         && null != (englishValue = english.getStringValue(path))) {
307                     }
308 
309                     String statusClass = isAliased ? (isInherited ? " class='ah'"
310                         : " class='a'") : (isInherited ? " class='h'" : "");
311 
312 //                    Level currentCoverage = coverageLevel.getLevel(path);
313 //                    boolean hideCoverage = false;
314 //                    if (requiredCoverage.compareTo(currentCoverage) < 0) {
315 //                        hideCoverage = true;
316 //                    }
317 
318                     boolean hide = isAliased || isInherited;
319                     if (!hide) {
320                         Relation<String, String> valuesToLocales = pathHeaderToValuesToLocale.get(prettyPath);
321                         if (valuesToLocales == null) {
322                             pathHeaderToValuesToLocale.put(prettyPath, valuesToLocales = Relation.of(new TreeMap<String, Set<String>>(), TreeSet.class));
323                         }
324                         valuesToLocales.put(lastValue + "→→" + value, locale);
325                     }
326                     pw.println(
327                         (hide ? "<tr class='xx'><td" : "<tr><td")
328                             + statusClass
329                             + ">"
330                             + CldrUtility.getDoubleLinkedText(String.valueOf(++count))
331                             + addPart(oldParts == null ? null : oldParts.getSection(), prettyPath.getSection())
332                             + addPart(oldParts == null ? null : oldParts.getPage(), prettyPath.getPage())
333                             + addPart(oldParts == null ? null : oldParts.getHeader(), prettyPath.getHeader())
334                             + addPart(oldParts == null ? null : oldParts.getCode(), prettyPath.getCode())
335                             // + "</td><td>" +
336                             // TransliteratorUtilities.toHTML.transliterate(lastElement)
337                             + showValue(showEnglish, englishValue, value, false)
338                             + "</td>");
339                     boolean isExemplar = path.contains("/exemplar");
340                     showValue(pw, value, null, isExemplar);
341                     if (!childValueToLocales.keyValuesSet().isEmpty()) {
342                         for (Entry<String, Set<String>> x : childValueToLocales.keyValuesSet()) {
343                             showValue(pw, x.getKey(), x.getValue(), isExemplar);
344                         }
345                         pw.println("<td class='info'><a class='rightLink' target='CLDR-ST-DOCS' href='http://cldr.org/index/charts#TOC-Summary'>ⓘ</a></td>");
346                     }
347                     pw.println("</tr>");
348                     oldParts = prettyPath;
349                 }
350                 pw.println("</table><br><table>");
351                 pw.println("<tr><td class='a'>Aliased items: </td><td>" + aliasedCount
352                     + "</td></tr>");
353                 pw.println("<tr><td class='h'>Inherited items:</td><td>"
354                     + inheritedCount + "</td></tr>");
355                 if (skippedCount != 0)
356                     pw.println("<tr><td>Omitted items:</td><td>" + skippedCount
357                         + "</td></tr>");
358                 pw.println("</table>");
359 
360                 // pw.println("</body></html>");
361                 pw.println(headerAndFooter[1]);
362                 pw.close();
363             }
364             PrintWriter pw = FileUtilities.openUTF8Writer(targetDir, "all-changed.html");
365             String[] headerAndFooter = new String[2];
366 
367             getChartTemplate(
368                 "Locale Data Summary for ALL-CHANGED",
369                 ToolConstants.CHART_DISPLAY_VERSION,
370                 "",
371                 headerAndFooter, null, false);
372             pw.println(headerAndFooter[0]);
373             pw.println("<table border=\"1\" cellpadding=\"2\" cellspacing=\"0\">");
374             pw.println("<tr>" +
375                 "<th>Section</th>" +
376                 "<th>Page</th>" +
377                 "<th>Header</th>" +
378                 "<th>Code</th>" +
379                 "<th>Old</th>" +
380                 "<th>Changed</th>" +
381                 "<th>Locales</th>" +
382                 "</tr>");
383             for (Entry<PathHeader, Relation<String, String>> entry : pathHeaderToValuesToLocale.entrySet()) {
384                 PathHeader ph = entry.getKey();
385                 Set<Entry<String, Set<String>>> keyValuesSet = entry.getValue().keyValuesSet();
386                 String rowspan = keyValuesSet.size() == 1 ? ">" : " rowSpan='" + keyValuesSet.size() + "'>";
387                 pw
388                     .append("<tr><td class='g'").append(rowspan)
389                     .append(ph.getSectionId().toString())
390                     .append("</td><td class='g'").append(rowspan)
391                     .append(ph.getPageId().toString())
392                     .append("</td><td class='g'").append(rowspan)
393                     .append(ph.getHeader() == null ? "<i>n/a</i>" : ph.getHeader())
394                     .append("</td><td class='g'").append(rowspan)
395                     .append(ph.getCode())
396                     .append("</td>");
397                 boolean addRow = false;
398                 for (Entry<String, Set<String>> s : keyValuesSet) {
399                     String value = s.getKey();
400                     int breakPoint = value.indexOf("→→");
401                     if (addRow) {
402                         pw.append("<tr>");
403                     }
404                     pw.append("<td>")
405                         .append(DataShower.getPrettyValue(value.substring(0, breakPoint)))
406                         .append("</td><td class='v'>")
407                         .append(DataShower.getPrettyValue(value.substring(breakPoint + 2)))
408                         .append("</td><td>")
409                         .append(CollectionUtilities.join(s.getValue(), ", "))
410                         .append("</td></tr>")
411                         .append(System.lineSeparator());
412                     addRow = true;
413                 }
414             }
415             pw.println(headerAndFooter[1]);
416             pw.close();
417         } finally {
418             deltaTime = System.currentTimeMillis() - deltaTime;
419             System.out.println("Elapsed: " + deltaTime / 1000.0 + " seconds");
420             System.out.println("Done");
421         }
422     }
423 
424     public static void showValue(PrintWriter pw, String value, Set<String> locales, boolean isExemplar) {
425         final boolean noLocales = locales == null || locales.isEmpty();
426         pw.println("<td"
427             + (isExemplar ? " style='max-width:20%'" : "")
428             + (noLocales ? "" : " title='" + CollectionUtilities.join(locales, ", ") + "'")
429             + (value == null ? "></i>n/a</i>" : " class='v'" + DataShower.getBidiStyle(value) + ">" + DataShower.getPrettyValue(value))
430             + "</td>");
431     }
432 
433     private static String addPart(String oldPart, String newPart) {
434         String prefix;
435         if (newPart.equals(oldPart)) {
436             prefix = "</td><td class='n'>";
437         } else if (newPart.length() == 0) {
438             prefix = "</td><td>";
439         } else {
440             prefix = "</td><td class='g'>";
441         }
442         return prefix + TransliteratorUtilities.toHTML.transform(newPart);
443     }
444 
445     private static void getScripts() throws IOException {
446         Set<String> locales = cldrFactory.getAvailableLanguages();
447         Set<String> scripts = new TreeSet<String>();
448         //XPathParts parts = new XPathParts();
449         Map<String, Map<String, Set<String>>> script_name_locales = new TreeMap<String, Map<String, Set<String>>>();
450         PrintWriter out = FileUtilities.openUTF8Writer(CLDRPaths.GEN_DIRECTORY, "scriptNames.txt");
451         for (Iterator<String> it = locales.iterator(); it.hasNext();) {
452             String locale = it.next();
453             System.out.println(locale);
454             CLDRFile file = cldrFactory.make(locale, false);
455             if (file.isNonInheriting())
456                 continue;
457             String localeName = file.getName(locale);
458             getScripts(localeName, scripts);
459             if (!scripts.contains("Latn")) {
460                 out
461                     .println(locale + "\t" + english.getName(locale) + "\t"
462                         + localeName);
463             }
464             for (Iterator<String> it2 = UnicodeScripts.iterator(); it2.hasNext();) {
465                 String script = it2.next();
466                 if (script.equals("Latn"))
467                     continue;
468                 String name = file.getName(CLDRFile.SCRIPT_NAME, script);
469                 if (getScripts(name, scripts).contains(script)) {
470                     Map<String, Set<String>> names_locales = script_name_locales.get(script);
471                     if (names_locales == null)
472                         script_name_locales.put(script, names_locales = new TreeMap<String, Set<String>>());
473                     Set<String> localeSet = names_locales.get(name);
474                     if (localeSet == null)
475                         names_locales.put(name, localeSet = new TreeSet<String>());
476                     localeSet.add(getLocaleNameAndCode(locale));
477                 }
478             }
479         }
480         for (Iterator<String> it2 = UnicodeScripts.iterator(); it2.hasNext();) {
481             String script = it2.next();
482             Object names = script_name_locales.get(script);
483             out.println(script + "\t("
484                 + english.getName(CLDRFile.SCRIPT_NAME, script) + ")\t" + names);
485         }
486         out.close();
487     }
488 
489     static Set<String> UnicodeScripts = Collections.unmodifiableSet(new TreeSet<String>(Arrays
490         .asList(new String[] { "Arab", "Armn", "Bali", "Beng", "Bopo", "Brai",
491             "Bugi", "Buhd", "Cans", "Cher", "Copt", "Cprt", "Cyrl", "Deva",
492             "Dsrt", "Ethi", "Geor", "Glag", "Goth", "Grek", "Gujr", "Guru",
493             "Hang", "Hani", "Hano", "Hebr", "Hira", "Hrkt", "Ital", "Kana",
494             "Khar", "Khmr", "Knda", "Laoo", "Latn", "Limb", "Linb", "Mlym",
495             "Mong", "Mymr", "Nkoo", "Ogam", "Orya", "Osma", "Phag", "Phnx",
496             "Qaai", "Runr", "Shaw", "Sinh", "Sylo", "Syrc", "Tagb", "Tale",
497             "Talu", "Taml", "Telu", "Tfng", "Tglg", "Thaa", "Thai", "Tibt",
498             "Ugar", "Xpeo", "Xsux", "Yiii" })));
499 
500     private static Set<String> getScripts(String exemplars, Set<String> results) {
501         results.clear();
502         if (exemplars == null)
503             return results;
504         for (UnicodeSetIterator it = new UnicodeSetIterator(new UnicodeSet()
505             .addAll(exemplars)); it.next();) {
506             int cp = it.codepoint;
507             int script = UScript.getScript(cp);
508             results.add(UScript.getShortName(script));
509         }
510         return results;
511     }
512 
513     private static void showCollation(Factory collationFactory, String locale,
514         ExtractCollationRules collationRules) {
515         CLDRFile collationFile;
516         try {
517             collationFile = collationFactory.make(locale, false);
518         } catch (RuntimeException e) {
519             return; // skip
520         }
521         collationRules.set(collationFile);
522         for (Iterator<String> it = collationRules.iterator(); it.hasNext();) {
523             String key = it.next();
524             System.out.println(key + ": ");
525             String rules = collationRules.getRules(key);
526             System.out.println(rules);
527         }
528     }
529 
530     private static String showValue(boolean showEnglish, String comparisonValue,
531         String mainValue, boolean lastEquals) {
532         return !showEnglish ? ""
533             : comparisonValue == null ? (lastEquals ? "</td><td>=" : "</td><td><i>n/a</i>")
534                 : comparisonValue.length() == 0 ? "</td><td>&nbsp;"
535                     : comparisonValue.equals(mainValue) ? "</td><td>="
536                         : "</td><td class='e'" + DataShower.getBidiStyle(comparisonValue) + ">" + DataShower.getPrettyValue(comparisonValue);
537     }
538 
539     static DataShower dataShower = new DataShower();
540 
541     public static class DataShower {
542         static Transliterator toLatin = Transliterator.getInstance("any-latin");
543 
544         static UnicodeSet BIDI_R = new UnicodeSet(
545             "[[:Bidi_Class=R:][:Bidi_Class=AL:]]");
546 
547         static String getBidiStyle(String cellValue) {
548             return BIDI_R.containsSome(cellValue) ? " style='direction:rtl'" : "";
549         }
550 
551         public static String getPrettyValue(String textToInsert) {
552             String outValue = TransliteratorUtilities.toHTML
553                 .transliterate(textToInsert);
554             String transValue = textToInsert;
555             //String span = "";
556             try {
557                 transValue = toLatin.transliterate(textToInsert);
558             } catch (RuntimeException e) {
559             }
560             if (!transValue.equals(textToInsert)) {
561                 // WARNING: we use toXML in attributes
562                 outValue = "<span title='"
563                     + TransliteratorUtilities.toXML.transliterate(transValue) + "'>"
564                     + outValue + "</span>";
565             }
566             return outValue;
567         }
568     }
569 
570     private static String getNda(Set<String> skipList, Map<String, String> nonDistinguishingAttributes,
571         CLDRFile file, String path, String parentFullPath, StringBuffer draftRef) {
572         draftRef.setLength(0);
573         if (parentFullPath != null && !parentFullPath.equals(path)) {
574             file.getNonDistinguishingAttributes(parentFullPath,
575                 nonDistinguishingAttributes, skipList);
576             if (nonDistinguishingAttributes.size() != 0) {
577                 String parentNda = "";
578                 for (Iterator<String> it = nonDistinguishingAttributes.keySet().iterator(); it
579                     .hasNext();) {
580                     String key = it.next();
581                     String value = nonDistinguishingAttributes.get(key);
582                     if (key.equals("draft") && !value.equals("contributed")) {
583                         if (draftRef.length() != 0)
584                             draftRef.append(",");
585                         draftRef.append("d");
586                     } else if (key.equals("alt")) {
587                         if (draftRef.length() != 0)
588                             draftRef.append(",");
589                         draftRef.append("a");
590                     } else if (key.equals("references")) {
591                         if (draftRef.length() != 0)
592                             draftRef.append(",");
593                         draftRef.append(nonDistinguishingAttributes.get(key));
594                     } else {
595                         if (parentNda.length() != 0)
596                             parentNda += ", ";
597                         parentNda += key + "=" + nonDistinguishingAttributes.get(key);
598                     }
599                 }
600                 if (parentNda.length() != 0) {
601                     parentNda = parentNda.replaceAll("[/]", "/\u200B");
602                     parentNda = "[" + parentNda + "]";
603                 }
604                 return parentNda;
605             }
606         }
607         return "";
608     }
609 
610     private static void showLinks(PrintWriter pw, String locale) {
611         pw.print("<p>");
612         showLinks2(pw, locale);
613         pw.println("</p>");
614     }
615 
616     private static void showLinks2(PrintWriter pw, String locale) {
617         String parent = LocaleIDParser.getParent(locale);
618         if (parent != null) {
619             showLinks2(pw, parent);
620             pw.print(" &gt; ");
621         }
622         pw.println(getLinkedLocaleName(locale));
623     }
624 
625     private static void showChildren(PrintWriter pw, String locale) {
626         LanguageTagParser ltp = new LanguageTagParser();
627         TreeMap<String, String> nameToLocale = new TreeMap<>();
628         for (String sublocale : parentToChildren.get(locale)) {
629             String minimized = LIKELY.minimize(sublocale);
630             nameToLocale.put(getEnglishLocaleName(sublocale), minimized == null ? sublocale : minimized);
631         }
632 
633         boolean isRoot = locale.equals("root");
634         char lastFirstChar = 0;
635         boolean first = true;
636         for (Entry<String, String> nameAndCode : nameToLocale.entrySet()) {
637             String name = nameAndCode.getKey();
638             String localeCode = nameAndCode.getValue();
639             if (localeCode.equals(locale)) {
640                 continue;
641             }
642             char firstChar = name.charAt(0);
643             if (first) {
644                 pw.print(System.lineSeparator() + "<p style='margin-left:5em'>&gt; ");
645                 lastFirstChar = firstChar;
646                 first = false;
647             } else if (firstChar != lastFirstChar) {
648                 pw.print("</p>" + System.lineSeparator() + "<p style='margin-left:5em'> ");
649                 lastFirstChar = firstChar;
650             } else {
651                 pw.print(", ");
652             }
653             if (isRoot) {
654                 pw.print(getLinkedLocaleName(localeCode));
655             } else {
656                 pw.print(getLocaleMinusBaseAndCode(localeCode));
657             }
658         }
659         if (first) {
660             pw.println("</p>");
661         }
662     }
663 
664     public static String getLinkedLocaleName(String locale) {
665         return "<a href='" + locale + ".html'>" + getEnglishLocaleName(locale) + "</a> [" + locale + "]";
666     }
667 
668     public static String getEnglishLocaleName(String locale) {
669         return english.getName(locale, true, CLDRFile.SHORT_ALTS);
670     }
671 
672     private static String getLocaleNameAndCode(String locale) {
673         return getEnglishLocaleName(locale) + " [" + locale + "]";
674     }
675 
676     private static String getLocaleMinusBaseAndCode(String locale) {
677         String full = getEnglishLocaleName(locale);
678         int leftParen = full.indexOf('(');
679         if (leftParen >= 0) {
680             full = full.substring(leftParen + 1, full.lastIndexOf(')'));
681         }
682         return full + " [" + locale + "]";
683     }
684 
685     static final LikelySubtags LIKELY = new LikelySubtags();
686 
687     // public static SimpleDateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm",
688     // ULocale.ENGLISH);
689 
getChartTemplate(String title, String version, String header, String[] headerAndFooter, String indexTitle, boolean showDate)690     static public void getChartTemplate(String title, String version,
691         String header, String[] headerAndFooter, String indexTitle, boolean showDate) throws IOException {
692         if (version == null) {
693             version = ToolConstants.CHART_DISPLAY_VERSION;
694         }
695         VariableReplacer langTag = new VariableReplacer()
696             .add("%title%", title)
697             .add("%header%", header)
698             .add("%index-title%", "Index")
699             .add("%index%", "index.html")
700             .add("%header%", header)
701             .add("%version%", version)
702             .add("%date%", showDate ? CldrUtility.isoFormatDateOnly(new Date()) : "");
703         if (indexTitle != null) {
704             langTag
705                 .add("%index-title%", indexTitle)
706                 .add("%index%", "../index.html");
707         }
708         // "$" //
709         // + "Date" //
710         // + "$") // odd style to keep CVS from substituting
711         ; // isoDateFormat.format(new Date())
712         BufferedReader input = ToolUtilities.getUTF8Data("chart-template.html");
713         StringBuffer result = new StringBuffer();
714         while (true) {
715             String line = input.readLine();
716             if (line == null)
717                 break;
718             String langTagPattern = langTag.replace(line);
719             if (line.indexOf("%body%") >= 0) {
720                 headerAndFooter[0] = result.toString();
721                 result.setLength(0);
722                 continue;
723             }
724             result.append(langTagPattern).append(System.lineSeparator());
725         }
726         headerAndFooter[1] = result.toString();
727     }
728 }
729