• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.tool;
2 
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6 import java.util.Locale;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.TreeMap;
10 import java.util.TreeSet;
11 import java.util.regex.Matcher;
12 
13 import org.unicode.cldr.draft.FileUtilities;
14 import org.unicode.cldr.util.CLDRFile;
15 import org.unicode.cldr.util.CLDRFile.WinningChoice;
16 import org.unicode.cldr.util.CLDRPaths;
17 import org.unicode.cldr.util.CldrUtility;
18 import org.unicode.cldr.util.Factory;
19 import org.unicode.cldr.util.Pair;
20 import org.unicode.cldr.util.PatternCache;
21 import org.unicode.cldr.util.SimpleFactory;
22 import org.unicode.cldr.util.StandardCodes;
23 import org.unicode.cldr.util.TransliteratorUtilities;
24 import org.unicode.cldr.util.XMLFileReader;
25 
26 import com.ibm.icu.impl.Relation;
27 import com.ibm.icu.lang.UCharacter;
28 import com.ibm.icu.text.Collator;
29 import com.ibm.icu.text.DateFormatSymbols;
30 import com.ibm.icu.text.UnicodeSet;
31 import com.ibm.icu.util.ULocale;
32 
33 class ExtractMessages {
34     public static final UnicodeSet LATIN_SCRIPT = new UnicodeSet("[:script=latin:]").freeze();
35 
36     private static Matcher fileMatcher;
37 
38     public static PrintWriter output;
39 
40     public static boolean SKIPEQUALS = true;
41     public static boolean SKIPIFCLDR = true;
42     public static String DIR = CLDRPaths.GEN_DIRECTORY + "/../additions/";
43 
main(String[] args)44     public static void main(String[] args) throws IOException {
45         double startTime = System.currentTimeMillis();
46         output = FileUtilities.openUTF8Writer(DIR, "additions.txt");
47         int totalCount = 0;
48         Set<String> skipped = new TreeSet<String>();
49 
50         try {
51             String sourceDirectory = getProperty("SOURCE", null);
52             if (sourceDirectory == null) {
53                 System.out.println("Need Source Directory! ");
54                 return;
55             }
56             fileMatcher = PatternCache.get(getProperty("FILE", ".*")).matcher("");
57 
58             SKIPIFCLDR = getProperty("SKIPIFCLDR", null) != null;
59 
60             boolean showMissing = true;
61 
62             File src = new File(sourceDirectory);
63 
64             XMLFileReader xfr = new XMLFileReader().setHandler(new EnglishHandler());
65             xfr.read(src + "/en.xmb", XMLFileReader.CONTENT_HANDLER
66                 | XMLFileReader.ERROR_HANDLER, false);
67 
68             for (File file : src.listFiles()) {
69                 if (file.isDirectory())
70                     continue;
71                 if (file.length() == 0)
72                     continue;
73                 String canonicalFile = file.getCanonicalPath();
74                 if (!canonicalFile.endsWith(".xtb")) {
75                     continue;
76                 }
77 
78                 String name = file.getName();
79                 name = name.substring(0, name.length() - 4);
80 
81                 if (!fileMatcher.reset(name).matches()) {
82                     continue;
83                 }
84                 System.out.println("* " + canonicalFile);
85 
86                 try {
87                     otherHandler.setLocale(name);
88                 } catch (RuntimeException e1) {
89                     System.out.println("Skipping, no CLDR locale file: " + name + "\t" + english.getName(name) + "\t"
90                         + e1.getClass().getName() + "\t" + e1.getMessage());
91                     skipped.add(name);
92                     continue;
93                 }
94 
95                 xfr = new XMLFileReader().setHandler(otherHandler);
96                 try {
97                     xfr.read(canonicalFile, XMLFileReader.CONTENT_HANDLER
98                         | XMLFileReader.ERROR_HANDLER, false);
99                 } catch (RuntimeException e) {
100                     System.out.println(e.getMessage());
101                     continue;
102                 }
103 
104                 // now write it out
105                 CLDRFile newFile = SimpleFactory.makeFile(otherHandler.getLocale());
106                 int itemCount = 0;
107                 for (DataHandler dataHandler : dataHandlers) {
108                     if (showMissing) {
109                         System.out.println("case " + dataHandler.type + ":");
110                         for (String value : dataHandler.missing) {
111                             System.out.println("addName(\"" + value + "\", \"XXX\", true);");
112                         }
113                     }
114 
115                     for (String id : dataHandler.id_to_value.keySet()) {
116                         Set<String> otherValue = dataHandler.id_to_value.getAll(id);
117                         if (otherValue == null || otherValue.size() == 0) continue;
118                         String cldrValue = dataHandler.id_to_cldrValue.get(id);
119                         int count = 0;
120                         for (String oValue : otherValue) {
121                             itemCount++;
122                             output.println(otherHandler.getLocale()
123                                 + "\t" + dataHandler.type
124                                 + "\t" + id
125                                 + "\t" + oValue
126                                 + (cldrValue == null ? "" : "\tcldr:\t" + cldrValue)
127                                 + (count == 0 ? "" : "\talt:\t" + String.valueOf(count)));
128                             newFile.add(dataHandler.getPath(id, count), oValue);
129                         }
130                     }
131                 }
132                 PrintWriter cldrOut = FileUtilities.openUTF8Writer(DIR, otherHandler.getLocale() + ".xml");
133                 newFile.write(cldrOut);
134                 cldrOut.close();
135 
136                 output.println();
137                 showMissing = false;
138                 output.flush();
139                 System.out.println("\titems: " + itemCount);
140                 totalCount += itemCount;
141             }
142 
143             for (String name : skipped) {
144                 System.out.println("\tSkipping, no CLDR locale file: " + name + "\t" + english.getName(name));
145             }
146             double deltaTime = System.currentTimeMillis() - startTime;
147             System.out.println("Elapsed: " + deltaTime / 1000.0 + " seconds");
148             System.out.println("\ttotal items: " + totalCount);
149         } finally {
150             output.close();
151         }
152     }
153 
getProperty(String key, String defaultValue)154     private static String getProperty(String key, String defaultValue) {
155         String fileRegex = System.getProperty(key);
156         if (fileRegex == null)
157             fileRegex = defaultValue;
158         System.out.println("-D" + key + "=" + fileRegex);
159         return fileRegex;
160     }
161 
162     private static Map<String, Pair<String, DataHandler>> numericId_Id = new TreeMap<String, Pair<String, DataHandler>>();
163     private static Matcher numericIdMatcher = PatternCache.get("\\[@id=\"([^\"]+)\"\\]").matcher("");
164     private static Factory cldrFactory = Factory.make(CLDRPaths.MAIN_DIRECTORY, ".*");
165     private static CLDRFile english = cldrFactory.make("en", true);
166 
167     private static class EnglishHandler extends XMLFileReader.SimpleHandler {
168 
handlePathValue(String path, String value)169         public void handlePathValue(String path, String value) {
170             for (DataHandler handler : dataHandlers) {
171                 if (handler.matches(path)) {
172                     // //messagebundle/msg[@id="1907015897505457162"][@seq="71982"][@desc="Andorra is a display name for a timezone"][@xml:space="default"]
173                     numericIdMatcher.reset(path).find();
174                     String id = numericIdMatcher.group(1);
175                     value = value.trim();
176                     if (value.length() == 0) return; // skip empties
177                     value = TransliteratorUtilities.fromXML.transliterate(value);
178                     String realID = handler.getCode(value);
179                     if (realID == null) {
180                         handler.missing.add(value);
181                         return;
182                     }
183                     numericId_Id.put(id, new Pair<String, DataHandler>(realID, handler));
184                     // System.out.println(id + "\t" + path + "\t" + value);
185                 }
186             }
187         }
188     }
189 
190     public static Collator col = Collator.getInstance(ULocale.ENGLISH);
191     static {
192         col.setStrength(Collator.SECONDARY);
193     }
194 
195     private static OtherHandler otherHandler = new OtherHandler();
196 
197     private static class OtherHandler extends XMLFileReader.SimpleHandler {
198         private String locale;
199         private ULocale uLocale;
200         CLDRFile cldrFile;
201         boolean usesLatin;
202 
handlePathValue(String path, String value)203         public void handlePathValue(String path, String value) {
204             // //messagebundle/msg[@id="1907015897505457162"][@seq="71982"][@desc="Andorra is a display name for a timezone"][@xml:space="default"]
205             value = value.trim();
206             if (value.length() == 0) return; // skip empties
207 
208             numericIdMatcher.reset(path).find();
209             String numericId = numericIdMatcher.group(1);
210             Pair<String, DataHandler> id_handler = numericId_Id.get(numericId);
211             if (id_handler == null) return;
212             String id = id_handler.getFirst();
213             DataHandler dataHandler = id_handler.getSecond();
214 
215             if (!usesLatin && LATIN_SCRIPT.containsSome(value)) {
216                 // output.println(locale + "\tSkipping item with latin characters\t" + id + "\t" + value);
217                 return;
218             }
219 
220             // this should be reorganized to put more in the DataHandler, but for now...
221 
222             value = dataHandler.fixValue(uLocale, value);
223 
224             String cldrValue = dataHandler.getCldrValue(cldrFile, id);
225             if (cldrValue != null) {
226                 if (col.compare(cldrValue, value) == 0) {
227                     // System.out.println("Duplicate for " + id + "\t" + value);
228                     if (SKIPEQUALS) return;
229                 } else {
230                     if (SKIPIFCLDR) return;
231                     // output.println(locale + "\tDifferent value for\t" + id + "\t" + value + "\tcldr:\t" + cldrValue);
232                 }
233             }
234             dataHandler.addValues(id, value, cldrValue);
235         }
236 
setLocale(String locale)237         public void setLocale(String locale) {
238 
239             // skip en, fr_CA
240             // as, sa bad
241             // ku cldr-latin, g-arabic
242             // ml, my, pa, te has mixed english
243             // TODO move this into datahandler eventually
244             locale = fixLocale(locale);
245             this.locale = locale;
246             this.uLocale = new ULocale(locale);
247             String lang = uLocale.getLanguage();
248             if (locale.equals("fr_CA") || lang.equals("en")) {
249                 throw new RuntimeException("Skipping " + locale);
250             }
251             cldrFile = cldrFactory.make(locale, false);
252             UnicodeSet exemplars = cldrFile.getExemplarSet("", WinningChoice.WINNING);
253             usesLatin = exemplars != null && exemplars.containsSome(LATIN_SCRIPT);
254             for (DataHandler dataHandler : dataHandlers) {
255                 dataHandler.reset(cldrFile);
256             }
257         }
258 
getLocale()259         public String getLocale() {
260             return locale;
261         }
262     }
263 
264     static Map<String, String> fixLocaleMap = CldrUtility.asMap(new String[][] {
265         { "zh_CN", "zh" },
266         { "zh_TW", "zh_Hant" },
267         { "pt_BR", "pt" },
268         { "in", "id" },
269         { "iw", "he" },
270         { "jw", "jv" },
271         { "no", "nb" },
272         { "ku", "ku_Arab" },
273     });
274 
fixLocale(String locale)275     static private String fixLocale(String locale) {
276         locale = locale.replace('-', '_');
277         String newLocale = fixLocaleMap.get(locale);
278         if (newLocale != null) {
279             locale = newLocale;
280         }
281         return locale;
282     }
283 
284     /*
285      * Language
286      * -DXMLPATH=".*form of language.*"
287      *
288      * Country
289      * -DXMLPATH=".*the country or region.*"
290      *
291      * Currency
292      * -DXMLPATH=".*currency name.*"
293      *
294      * Month Long/Short
295      * -DXMLPATH=".*Name of the month of .*"
296      * -DXMLPATH=".*3 letter abbreviation for name of Month.*"
297      *
298      * Week Long/Short
299      * -DXMLPATH=".*day in week.*"
300      * -DXMLPATH=".*Short Version of .*"
301      *
302      * Timezone
303      * DXMLPATH=".*is a display name for a timezone.*"
304      */
305 
306     enum Type {
307         LANGUAGE, REGION, CURRENCY, MONTH, MONTHSHORT, DAY, DAYSHORT, TIMEZONE
308     };
309 
310     static StandardCodes sc = StandardCodes.make();
311     static DateFormatSymbols dfs = new DateFormatSymbols(ULocale.ENGLISH);
312 
313     static DataHandler[] dataHandlers = {
314         new DataHandler(Type.LANGUAGE, ".*form of language.*"),
315         new DataHandler(Type.REGION, ".*the country or region.*"),
316         new DataHandler(Type.CURRENCY, ".*currency name.*"),
317         new DataHandler(Type.MONTH, ".*Name of the month of .*"),
318         new DataHandler(Type.MONTHSHORT, ".*3 letter abbreviation for name of Month.*"),
319         new DataHandler(Type.DAY, ".*day in week.*"),
320         new DataHandler(Type.DAYSHORT, ".*Short Version of .*"),
321         new DataHandler(Type.TIMEZONE, ".*is a display name for a timezone.*"),
322     };
323 
324     enum CasingAction {
325         NONE, FORCE_TITLE, FORCE_LOWER
326     }
327 
328     static class DataHandler implements Comparable<DataHandler> {
329         // mostly stable
330         private Matcher matcher;
331         private Type type;
332         private Map<String, String> name_code = new TreeMap<String, String>();
333         // private Map<String,String> code_name = new TreeMap();
334         private Set<String> missing = new TreeSet<String>();
335 
336         // changes with each locale, must call reset
337         private Relation<String, String> id_to_value = Relation.of(new TreeMap<String, Set<String>>(), TreeSet.class);
338         private Map<String, String> id_to_cldrValue = new TreeMap<String, String>();
339         private CasingAction forceCasing = CasingAction.NONE;
340 
reset(CLDRFile cldrFile)341         public void reset(CLDRFile cldrFile) {
342             id_to_value.clear();
343             id_to_cldrValue.clear();
344             forceCasing = CasingAction.NONE;
345             String key = null;
346             switch (type) {
347             case LANGUAGE:
348                 key = "en";
349                 break;
350             case REGION:
351                 key = "FR";
352                 break;
353             case CURRENCY:
354                 key = "GBP";
355                 break;
356             case MONTH:
357             case MONTHSHORT:
358                 key = "1";
359                 break;
360             case DAY:
361             case DAYSHORT:
362                 key = "mon";
363                 break;
364             case TIMEZONE:
365                 key = "America/New_York";
366                 break;
367             }
368             String sample = getCldrValue(cldrFile, key);
369             if (sample != null) {
370                 if (UCharacter.isLowerCase(sample.charAt(0))) {
371                     forceCasing = CasingAction.FORCE_LOWER;
372                 } else if (UCharacter.isUpperCase(sample.charAt(0))) {
373                     forceCasing = CasingAction.FORCE_TITLE;
374                 }
375             }
376         }
377 
fixValue(ULocale uLocale, String value)378         public String fixValue(ULocale uLocale, String value) {
379             value = TransliteratorUtilities.fromXML.transliterate(value);
380 
381             if (forceCasing == CasingAction.FORCE_LOWER) {
382                 if (!UCharacter.isLowerCase(value.charAt(0))) {
383                     value = UCharacter.toLowerCase(value);
384                 }
385             } else if (forceCasing == CasingAction.FORCE_TITLE) {
386                 if (!UCharacter.isUpperCase(value.charAt(0))) {
387                     value = UCharacter.toTitleCase(uLocale, value, null);
388                 }
389             }
390 
391             return value;
392         }
393 
addValues(String id, String value, String cldrValue)394         public void addValues(String id, String value, String cldrValue) {
395             id_to_value.put(id, value);
396             if (cldrValue != null) {
397                 id_to_cldrValue.put(id, cldrValue);
398             }
399         }
400 
addName(String name, String code, boolean skipMessage)401         public void addName(String name, String code, boolean skipMessage) {
402             // String old = code_name.get(code);
403             // if (old != null) {
404             // if (!skipMessage) {
405             // System.out.println("Name collision:\t" + code + "\tnew: " + name + "\tkeeping: " + old);
406             // }
407             // } else {
408             // }
409             // code_name.put(code, name);
410             name_code.put(name, code);
411         }
412 
DataHandler(Type type, String pattern)413         DataHandler(Type type, String pattern) {
414             this.type = type;
415             matcher = PatternCache.get(pattern).matcher("");
416             switch (type) {
417             case LANGUAGE:
418                 for (String code : sc.getAvailableCodes("language")) {
419                     String name = english.getName("language", code);
420                     if (name == null) {
421                         // System.out.println("Missing name for: " + code);
422                         continue;
423                     }
424                     addName(name, code.replace("-", "_"), false);
425                 }
426                 // add irregular names
427                 addName("English (US)", "en_US", true);
428                 addName("English (UK)", "en_GB", true);
429                 // addName("English (AU)", "en_AU/short");
430                 // addName("Portuguese (PT)", "pt_PT/short");
431                 // addName("Portuguese (BR)", "pt_BR/short");
432                 addName("Chinese (Simplified)", "zh_Hans", true);
433                 addName("Chinese (Traditional)", "zh_Hant", true);
434                 addName("Norwegian (Nynorsk)", "nn", true);
435                 addName("Portuguese (Portugal)", "pt_PT", true);
436                 addName("Portuguese (Brazil)", "pt_BR", true);
437                 addName("English (Australia)", "en_AU", true);
438                 addName("Scots Gaelic", "gd", true);
439                 addName("Frisian", "fy", true);
440                 addName("Sesotho", "st", true);
441                 addName("Kyrgyz", "ky", true);
442                 addName("Laothian", "lo", true);
443                 addName("Cambodian", "km", true);
444                 addName("Greenlandic", "kl", true);
445                 addName("Inupiak", "ik", true);
446                 addName("Volapuk", "vo", true);
447                 addName("Byelorussian", "be", true);
448                 addName("Faeroese", "fo", true);
449                 addName("Singhalese", "si", true);
450                 addName("Gaelic", "ga", true); // IRISH
451                 addName("Bhutani", "dz", true);
452                 addName("Setswana", "tn", true);
453                 addName("Siswati", "ss", true);
454                 addName("Sangro", "sg", true);
455                 // addName("Kirundi", "XXX"); // no ISO2 code
456                 // addName("Sudanese", "XXX"); // ???
457                 break;
458             case REGION:
459                 for (String code : sc.getAvailableCodes("territory")) {
460                     String name = english.getName("territory", code);
461                     if (name == null) {
462                         // System.out.println("Missing name for: " + code);
463                         continue;
464                     }
465                     addName(name, code, false);
466                 }
467                 // add irregular names
468                 addName("Bosnia and Herzegowina", "BA", true);
469                 addName("Congo", "CG", true);
470                 addName("Congo, Democratic Republic of the", "CD", true);
471                 addName("Congo, The Democratic Republic of the", "CD", true);
472                 addName("Cote D'ivoire", "CI", true);
473                 addName("Côte d'Ivoire", "CI", true);
474                 addName("Equitorial Guinea", "GQ", true);
475                 addName("French Quiana", "GF", true);
476                 addName("Heard and Mc Donald Islands", "HM", true);
477                 addName("Holy See (Vatican City State)", "VA", true);
478                 addName("Iran (Islamic Republic of)", "IR", true);
479                 addName("Korea, Democratic People's Republic of", "KP", true);
480                 addName("Korea, Republic of", "KR", true);
481                 addName("Libyan Arab Jamahiriya", "LY", true);
482                 addName("Lichtenstein", "LI", true);
483                 addName("Macao", "MO", true);
484                 addName("Micronesia, Federated States of", "FM", true);
485                 addName("Palestine", "PS", true);
486                 addName("Serbia and Montenegro", "CS", true);
487                 addName("Slovakia (Slovak Republic)", "SK", true);
488                 addName("São Tomé and Príncipe", "ST", true);
489                 addName("The Former Yugoslav Republic of Macedonia", "MK", true);
490                 addName("United States minor outlying islands", "UM", true);
491                 addName("Vatican City", "VA", true);
492                 addName("Virgin Islands, British", "VG", true);
493                 addName("Virgin Islands, U.S.", "VI", true);
494                 addName("Zaire", "CD", true);
495                 addName("Åland Islands", "AX", true);
496                 break;
497             case CURRENCY:
498                 for (String code : sc.getAvailableCodes("currency")) {
499                     String name = english.getName("currency", code);
500                     if (name == null) {
501                         // System.out.println("Missing name for: " + code);
502                         continue;
503                     }
504                     addName(name, code, false);
505                 }
506                 // add irregular names
507                 addName("Australian Dollars", "AUD", true);
508                 addName("Bolivian Boliviano", "BOB", true);
509                 addName("British Pounds Sterling", "GBP", true);
510                 addName("Bulgarian Lev", "BGN", true);
511                 addName("Canadian Dollars", "CAD", true);
512                 addName("Czech Koruna", "CZK", true);
513                 addName("Danish Kroner", "DKK", true);
514                 addName("Denmark Kroner", "DKK", true);
515                 addName("Deutsche Marks", "DEM", true);
516                 addName("Euros", "EUR", true);
517                 addName("French Franks", "FRF", true);
518                 addName("Hong Kong Dollars", "HKD", true);
519                 addName("Israeli Shekel", "ILS", true);
520                 addName("Lithuanian Litas", "LTL", true);
521                 addName("Mexico Peso", "MXN", true);
522                 addName("New Romanian Leu", "RON", true);
523                 addName("New Taiwan Dollar", "TWD", true);
524                 addName("New Zealand Dollars", "NZD", true);
525                 addName("Norway Kroner", "NOK", true);
526                 addName("Norwegian Kroner", "NOK", true);
527                 addName("Peruvian Nuevo Sol", "PEN", true);
528                 addName("Polish New Zloty", "PLN", true);
529                 addName("Polish NewZloty", "PLN", true);
530                 addName("Russian Rouble", "RUB", true);
531                 addName("Singapore Dollars", "SGD", true);
532                 addName("Slovenian Tolar", "SIT", true);
533                 addName("Sweden Kronor", "SEK", true);
534                 addName("Swedish Kronor", "SEK", true);
535                 addName("Swiss Francs", "CHF", true);
536                 addName("US Dollars", "USD", true);
537                 addName("United Arab EmiratesD irham", "AED", true);
538                 addName("Venezuela Bolivar", "VEB", true);
539                 addName("Yuan Renminbi", "CNY", true);
540                 break;
541             case TIMEZONE:
542                 for (String code : sc.getAvailableCodes("tzid")) {
543                     String[] parts = code.split("/");
544                     addName(parts[parts.length - 1].replace("_", " "), code, false);
545                 }
546                 // add irregular names
547                 addName("Alaska Time", "America/Anchorage", true);
548                 // addName("Atlantic Time", "XXX", true);
549                 // addName("Atlantic Time - Halifax", "America/Halifax", true);
550                 addName("Canary Islands", "Atlantic/Canary", true);
551                 // addName("Central European Time", "XXX", true);
552                 // addName("Central European Time - Madrid", "Europe/Madrid", true);
553                 // addName("Central Time", "America/Chicago", true);
554                 // addName("Central Time - Adelaide", "Australia/Adelaide", true);
555                 // addName("Central Time - Darwin", "Australia/Darwin", true);
556                 // addName("Central Time - Mexico City", "America/Mexico_City", true);
557                 // addName("Central Time - Mexico City, Monterrey", "America/Monterrey", true);
558                 // addName("Central Time - Regina", "America/Regina", true);
559                 // addName("Central Time - Sasketchewan", "XXX", true);
560                 // addName("Central Time - Winnipeg", "America/Winnipeg", true);
561                 // addName("China Time - Beijing", "XXX", true);
562                 addName("Dumont D'Urville", "Antarctica/DumontDUrville", true);
563                 addName("Easter Island", "Pacific/Easter", true);
564                 // addName("Eastern European Time", "XXX", true);
565                 // addName("Eastern Standard Time", "XXX", true);
566                 // addName("Eastern Time", "XXX", true);
567                 // addName("Eastern Time - Brisbane", "Australia/Brisbane", true);
568                 // addName("Eastern Time - Hobart", "Australia/Hobart", true);
569                 // addName("Eastern Time - Iqaluit", "America/Iqaluit", true);
570                 // addName("Eastern Time - Melbourne, Sydney", "XXX", true);
571                 // addName("Eastern Time - Montreal", "XXX", true);
572                 // addName("Eastern Time - Toronto", "XXX", true);
573                 // addName("GMT (no daylight saving)", "XXX", true);
574                 // addName("Greenwich Mean Time", "XXX", true);
575                 // addName("Hanoi", "XXX", true);
576                 // addName("Hawaii Time", "XXX", true);
577                 // addName("India Standard Time", "XXX", true);
578                 // addName("International Date Line West", "XXX", true);
579                 // addName("Japan Time", "XXX", true);
580                 // addName("Moscow+00", "XXX", true);
581                 // addName("Moscow+01 - Samara", "XXX", true);
582                 // addName("Moscow+02 - Yekaterinburg", "XXX", true);
583                 // addName("Moscow+03 - Omsk, Novosibirsk", "XXX", true);
584                 // addName("Moscow+04 - Krasnoyarsk", "XXX", true);
585                 // addName("Moscow+05 - Irkutsk", "XXX", true);
586                 // addName("Moscow+06 - Yakutsk", "XXX", true);
587                 // addName("Moscow+07 - Vladivostok, Sakhalin", "XXX", true);
588                 // addName("Moscow+07 - Yuzhno-Sakhalinsk", "XXX", true);
589                 // addName("Moscow+08 - Magadan", "XXX", true);
590                 // addName("Moscow+09 - Kamchatka, Anadyr", "XXX", true);
591                 // addName("Moscow+09 - Petropavlovsk-Kamchatskiy", "XXX", true);
592                 // addName("Moscow-01 - Kaliningrad", "XXX", true);
593                 // addName("Mountain Time", "XXX", true);
594                 // addName("Mountain Time - Arizona", "XXX", true);
595                 // addName("Mountain Time - Chihuahua, Mazatlan", "XXX", true);
596                 // addName("Mountain Time - Dawson Creek", "XXX", true);
597                 // addName("Mountain Time - Edmonton", "XXX", true);
598                 // addName("Mountain Time - Hermosillo", "XXX", true);
599                 // addName("Mountain Time - Yellowknife", "XXX", true);
600                 // addName("Newfoundland Time - St. Johns", "XXX", true);
601                 // addName("Pacific Time", "XXX", true);
602                 // addName("Pacific Time - Tijuana", "XXX", true);
603                 // addName("Pacific Time - Vancouver", "XXX", true);
604                 // addName("Pacific Time - Whitehorse", "XXX", true);
605                 addName("Salvador", "America/El_Salvador", true);
606                 addName("St. Kitts", "America/St_Kitts", true);
607                 addName("St. Lucia", "America/St_Lucia", true);
608                 addName("St. Thomas", "America/St_Thomas", true);
609                 addName("St. Vincent", "America/St_Vincent", true);
610                 // addName("Tel Aviv", "XXX", true);
611                 // addName("Western European Time", "XXX", true);
612                 // addName("Western European Time - Canary Islands", "XXX", true);
613                 // addName("Western European Time - Ceuta", "XXX", true);
614                 // addName("Western Time - Perth", "XXX", true);
615                 break;
616             case MONTH:
617             case MONTHSHORT:
618                 String[] names = type == Type.MONTH ? dfs.getMonths() : dfs.getShortMonths();
619                 for (int i = 0; i < names.length; ++i) {
620                     addName(names[i], String.valueOf(i + 1), true);
621                 }
622                 break;
623             case DAY:
624             case DAYSHORT:
625                 String[] names2 = type == Type.DAY ? dfs.getWeekdays() : dfs.getShortWeekdays();
626                 for (int i = 1; i < names2.length; ++i) {
627                     addName(names2[i], names2[i].substring(0, 3).toLowerCase(Locale.ENGLISH), true);
628                 }
629                 break;
630             default:
631                 // throw new IllegalArgumentException();
632                 break;
633             }
634         }
635 
getCldrValue(CLDRFile cldrFile, String id)636         public String getCldrValue(CLDRFile cldrFile, String id) {
637             String result = cldrFile.getStringValue(getPath(id));
638             // cldrFile.getName(CLDRFile.LANGUAGE_NAME, id, false);
639             if (result == null && type == Type.TIMEZONE) {
640                 String[] parts = id.split("/");
641                 result = parts[parts.length - 1].replace("_", " ");
642             }
643             return result;
644         }
645 
matches(String text)646         boolean matches(String text) {
647             return matcher.reset(text).matches();
648         }
649 
getCode(String value)650         String getCode(String value) {
651             return name_code.get(value);
652         }
653 
compareTo(DataHandler o)654         public int compareTo(DataHandler o) {
655             throw new IllegalArgumentException();
656         }
657 
getPath(String id, int count)658         String getPath(String id, int count) {
659             String result = getPath(id);
660             count += 650;
661             result += "[@alt=\"proposed-x" + count + "\"]";
662             result += "[@draft=\"provisional\"]";
663             return result;
664         }
665 
getPath(String id)666         String getPath(String id) {
667             switch (type) {
668             case LANGUAGE:
669                 return CLDRFile.getKey(CLDRFile.LANGUAGE_NAME, id);
670             case REGION:
671                 return CLDRFile.getKey(CLDRFile.TERRITORY_NAME, id);
672             case CURRENCY:
673                 return CLDRFile.getKey(CLDRFile.CURRENCY_NAME, id);
674             case TIMEZONE:
675                 return "//ldml/dates/timeZoneNames/zone[@type=\"$1\"]/exemplarCity".replace("$1", id);
676             case MONTH:
677                 return "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/months/monthContext[@type=\"format\"]/monthWidth[@type=\"wide\"]/month[@type=\"$1\"]"
678                     .replace("$1", id);
679             case MONTHSHORT:
680                 return "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/months/monthContext[@type=\"format\"]/monthWidth[@type=\"abbreviated\"]/month[@type=\"$1\"]"
681                     .replace("$1", id);
682             case DAY:
683                 return "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/days/dayContext[@type=\"format\"]/dayWidth[@type=\"wide\"]/day[@type=\"$1\"]"
684                     .replace("$1", id);
685             case DAYSHORT:
686                 return "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/days/dayContext[@type=\"format\"]/dayWidth[@type=\"abbreviated\"]/day[@type=\"$1\"]"
687                     .replace("$1", id);
688             }
689             return null;
690             //
691         }
692     }
693 }
694