< prev index next >

make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java

Print this page
rev 49533 : [mq]: 8189784
   1 /*
   2  * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package build.tools.cldrconverter;
  27 
  28 import static build.tools.cldrconverter.Bundle.jreTimeZoneNames;
  29 import build.tools.cldrconverter.BundleGenerator.BundleType;
  30 import java.io.File;
  31 import java.nio.file.DirectoryStream;
  32 import java.nio.file.FileSystems;
  33 import java.nio.file.Files;
  34 import java.nio.file.Path;
  35 import java.util.*;
  36 import java.util.ResourceBundle.Control;
  37 import java.util.logging.Level;
  38 import java.util.logging.Logger;
  39 import java.util.stream.Collectors;
  40 import java.util.stream.IntStream;

  41 import javax.xml.parsers.SAXParser;
  42 import javax.xml.parsers.SAXParserFactory;
  43 import org.xml.sax.SAXNotRecognizedException;
  44 import org.xml.sax.SAXNotSupportedException;
  45 
  46 
  47 /**
  48  * Converts locale data from "Locale Data Markup Language" format to
  49  * JRE resource bundle format. LDML is the format used by the Common
  50  * Locale Data Repository maintained by the Unicode Consortium.
  51  */
  52 public class CLDRConverter {
  53 
  54     static final String LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldml.dtd";
  55     static final String SPPL_LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldmlSupplemental.dtd";
  56     static final String BCP47_LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldmlBCP47.dtd";
  57 
  58 
  59     private static String CLDR_BASE = "../CLDR/21.0.1/";
  60     static String LOCAL_LDML_DTD;
  61     static String LOCAL_SPPL_LDML_DTD;
  62     static String LOCAL_BCP47_LDML_DTD;
  63     private static String SOURCE_FILE_DIR;
  64     private static String SPPL_SOURCE_FILE;

  65     private static String NUMBERING_SOURCE_FILE;
  66     private static String METAZONES_SOURCE_FILE;
  67     private static String LIKELYSUBTAGS_SOURCE_FILE;
  68     private static String TIMEZONE_SOURCE_FILE;
  69     static String DESTINATION_DIR = "build/gensrc";
  70 
  71     static final String LOCALE_NAME_PREFIX = "locale.displayname.";
  72     static final String LOCALE_SEPARATOR = LOCALE_NAME_PREFIX + "separator";
  73     static final String LOCALE_KEYTYPE = LOCALE_NAME_PREFIX + "keytype";
  74     static final String LOCALE_KEY_PREFIX = LOCALE_NAME_PREFIX + "key.";
  75     static final String LOCALE_TYPE_PREFIX = LOCALE_NAME_PREFIX + "type.";
  76     static final String LOCALE_TYPE_PREFIX_CA = LOCALE_TYPE_PREFIX + "ca.";
  77     static final String CURRENCY_SYMBOL_PREFIX = "currency.symbol.";
  78     static final String CURRENCY_NAME_PREFIX = "currency.displayname.";
  79     static final String CALENDAR_NAME_PREFIX = "calendarname.";
  80     static final String CALENDAR_FIRSTDAY_PREFIX = "firstDay.";
  81     static final String CALENDAR_MINDAYS_PREFIX = "minDays.";
  82     static final String TIMEZONE_ID_PREFIX = "timezone.id.";
  83     static final String ZONE_NAME_PREFIX = "timezone.displayname.";
  84     static final String METAZONE_ID_PREFIX = "metazone.id.";
  85     static final String PARENT_LOCALE_PREFIX = "parentLocale.";
  86 
  87     private static SupplementDataParseHandler handlerSuppl;

  88     private static LikelySubtagsParseHandler handlerLikelySubtags;
  89     static NumberingSystemsParseHandler handlerNumbering;
  90     static MetaZonesParseHandler handlerMetaZones;
  91     static TimeZoneParseHandler handlerTimeZone;
  92     private static BundleGenerator bundleGenerator;
  93 
  94     // java.base module related
  95     static boolean isBaseModule = false;
  96     static final Set<Locale> BASE_LOCALES = new HashSet<>();
  97 
  98     // "parentLocales" map
  99     private static final Map<String, SortedSet<String>> parentLocalesMap = new HashMap<>();
 100     private static final ResourceBundle.Control defCon =
 101         ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
 102 



 103     static enum DraftType {
 104         UNCONFIRMED,
 105         PROVISIONAL,
 106         CONTRIBUTED,
 107         APPROVED;
 108 
 109         private static final Map<String, DraftType> map = new HashMap<>();
 110         static {
 111             for (DraftType dt : values()) {
 112                 map.put(dt.getKeyword(), dt);
 113             }
 114         }
 115         static private DraftType defaultType = CONTRIBUTED;
 116 
 117         private final String keyword;
 118 
 119         private DraftType() {
 120             keyword = this.name().toLowerCase(Locale.ROOT);
 121 
 122         }


 178                         break;
 179 
 180                     case "-basemodule":
 181                         // indicates java.base module resource generation
 182                         isBaseModule = true;
 183                         break;
 184 
 185                     case "-o":
 186                         // output directory
 187                         DESTINATION_DIR = args[++i];
 188                         break;
 189 
 190                     case "-utf8":
 191                         USE_UTF8 = true;
 192                         break;
 193 
 194                     case "-verbose":
 195                         verbose = true;
 196                         break;
 197 




 198                     case "-help":
 199                         usage();
 200                         System.exit(0);
 201                         break;
 202 
 203                     default:
 204                         throw new RuntimeException();
 205                     }
 206                 }
 207             } catch (RuntimeException e) {
 208                 severe("unknown or imcomplete arg(s): " + currentArg);
 209                 usage();
 210                 System.exit(1);
 211             }
 212         }
 213 
 214         // Set up path names
 215         LOCAL_LDML_DTD = CLDR_BASE + "/dtd/ldml.dtd";
 216         LOCAL_SPPL_LDML_DTD = CLDR_BASE + "/dtd/ldmlSupplemental.dtd";
 217         LOCAL_BCP47_LDML_DTD = CLDR_BASE + "/dtd/ldmlBCP47.dtd";
 218         SOURCE_FILE_DIR = CLDR_BASE + "/main";
 219         SPPL_SOURCE_FILE = CLDR_BASE + "/supplemental/supplementalData.xml";
 220         LIKELYSUBTAGS_SOURCE_FILE = CLDR_BASE + "/supplemental/likelySubtags.xml";
 221         NUMBERING_SOURCE_FILE = CLDR_BASE + "/supplemental/numberingSystems.xml";
 222         METAZONES_SOURCE_FILE = CLDR_BASE + "/supplemental/metaZones.xml";
 223         TIMEZONE_SOURCE_FILE = CLDR_BASE + "/bcp47/timezone.xml";

 224 
 225         if (BASE_LOCALES.isEmpty()) {
 226             setupBaseLocales("en-US");
 227         }
 228 
 229         bundleGenerator = new ResourceBundleGenerator();
 230 
 231         // Parse data independent of locales
 232         parseSupplemental();
 233         parseBCP47();
 234 
 235         List<Bundle> bundles = readBundleList();
 236         convertBundles(bundles);





 237     }
 238 
 239     private static void usage() {
 240         errout("Usage: java CLDRConverter [options]%n"
 241                 + "\t-help          output this usage message and exit%n"
 242                 + "\t-verbose       output information%n"
 243                 + "\t-draft [contributed | approved | provisional | unconfirmed]%n"
 244                 + "\t\t       draft level for using data (default: contributed)%n"
 245                 + "\t-base dir      base directory for CLDR input files%n"
 246                 + "\t-basemodule    generates bundles that go into java.base module%n"
 247                 + "\t-baselocales loc(,loc)*      locales that go into the base module%n"
 248                 + "\t-o dir         output directory (default: ./build/gensrc)%n"
 249                 + "\t-o dir         output directory (defaut: ./build/gensrc)%n"
 250                 + "\t-utf8          use UTF-8 rather than \\uxxxx (for debug)%n");
 251     }
 252 
 253     static void info(String fmt, Object... args) {
 254         if (verbose) {
 255             System.out.printf(fmt, args);
 256         }
 257     }
 258 
 259     static void info(String msg) {
 260         if (verbose) {
 261             System.out.println(msg);
 262         }
 263     }
 264 
 265     static void warning(String fmt, Object... args) {
 266         System.err.print("Warning: ");
 267         System.err.printf(fmt, args);
 268     }
 269 


 384         parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl);
 385         Map<String, Object> parentData = handlerSuppl.getData("root");
 386         parentData.keySet().stream()
 387                 .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
 388                 .forEach(key -> {
 389                 parentLocalesMap.put(key, new TreeSet(
 390                     Arrays.asList(((String)parentData.get(key)).split(" "))));
 391             });
 392 
 393         // Parse numberingSystems to get digit zero character information.
 394         handlerNumbering = new NumberingSystemsParseHandler();
 395         parseLDMLFile(new File(NUMBERING_SOURCE_FILE), handlerNumbering);
 396 
 397         // Parse metaZones to create mappings between Olson tzids and CLDR meta zone names
 398         handlerMetaZones = new MetaZonesParseHandler();
 399         parseLDMLFile(new File(METAZONES_SOURCE_FILE), handlerMetaZones);
 400 
 401         // Parse likelySubtags
 402         handlerLikelySubtags = new LikelySubtagsParseHandler();
 403         parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags);





 404     }
 405 
 406     // Parsers for data in "bcp47" directory
 407     //
 408     private static void parseBCP47() throws Exception {
 409         // Parse timezone
 410         handlerTimeZone = new TimeZoneParseHandler();
 411         parseLDMLFile(new File(TIMEZONE_SOURCE_FILE), handlerTimeZone);
 412     }
 413 
 414     private static void parseLDMLFile(File srcfile, AbstractLDMLHandler handler) throws Exception {
 415         info("..... Parsing " + srcfile.getName() + " .....");
 416         SAXParserFactory pf = SAXParserFactory.newInstance();
 417         pf.setValidating(true);
 418         SAXParser parser = pf.newSAXParser();
 419         enableFileAccess(parser);
 420         parser.parse(srcfile, handler);
 421     }
 422 
 423     private static StringBuilder getCandLocales(Locale cldrLoc) {


 639                         names.put(tzid, cldrMeta.get().getValue());
 640                     } else {
 641                         // check the JRE meta key, add if there is not.
 642                         Optional<Map.Entry<String[], String>> jreMeta =
 643                             jreMetaMap.entrySet().stream()
 644                                 .filter(jm -> Arrays.deepEquals(data, jm.getKey()))
 645                                 .findAny();
 646                         if (jreMeta.isPresent()) {
 647                             names.put(tzid, jreMeta.get().getValue());
 648                         } else {
 649                             String metaName = "JRE_" + tzid.replaceAll("[/-]", "_");
 650                             names.put(METAZONE_ID_PREFIX + metaName, data);
 651                             names.put(tzid, metaName);
 652                             jreMetaMap.put(data, metaName);
 653                         }
 654                     }
 655                 }
 656             });
 657         }
 658 
 659         for (String tzid : handlerMetaZones.keySet()) {
 660             String tzKey = TIMEZONE_ID_PREFIX + tzid;
 661             Object data = map.get(tzKey);



 662             if (data instanceof String[]) {
 663                 names.put(tzid, data);
 664             } else {
 665                 String meta = handlerMetaZones.get(tzid);
 666                 if (meta != null) {
 667                     String metaKey = METAZONE_ID_PREFIX + meta;
 668                     data = map.get(metaKey);
 669                     if (data instanceof String[]) {
 670                         // Keep the metazone prefix here.
 671                         names.put(metaKey, data);
 672                         names.put(tzid, meta);
 673                     }
 674                 }
 675             }
 676         }

 677         return names;
 678     }
 679 
 680     /**
 681      * Extracts the language independent calendar data. Each of the two keys,
 682      * "firstDayOfWeek" and "minimalDaysInFirstWeek" has a string value consists of
 683      * one or multiple occurrences of:
 684      *  i: rg1 rg2 ... rgn;
 685      * where "i" is the data for the following regions (delimited by a space) after
 686      * ":", and ends with a ";".
 687      */
 688     private static Map<String, Object> extractCalendarData(Map<String, Object> map, String id) {
 689         Map<String, Object> calendarData = new LinkedHashMap<>();
 690         if (id.equals("root")) {
 691             calendarData.put("firstDayOfWeek",
 692                 IntStream.range(1, 8)
 693                     .mapToObj(String::valueOf)
 694                     .filter(d -> map.keySet().contains(CALENDAR_FIRSTDAY_PREFIX + d))
 695                     .map(d -> d + ": " + map.get(CALENDAR_FIRSTDAY_PREFIX + d))
 696                     .collect(Collectors.joining(";")));


 931                         "root".equals(parent) ? Locale.ROOT : Locale.forLanguageTag(parent));
 932                 });
 933             });
 934         }
 935 
 936         // check irregular parents
 937         for (int i = 0; i < candidates.size(); i++) {
 938             Locale l = candidates.get(i);
 939             Locale p = childToParentLocaleMap.get(l);
 940             if (!l.equals(Locale.ROOT) &&
 941                 Objects.nonNull(p) &&
 942                 !candidates.get(i+1).equals(p)) {
 943                 List<Locale> applied = candidates.subList(0, i+1);
 944                 applied.addAll(applyParentLocales(baseName, defCon.getCandidateLocales(baseName, p)));
 945                 return applied;
 946             }
 947         }
 948 
 949         return candidates;
 950     }








































 951 }
   1 /*
   2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package build.tools.cldrconverter;
  27 
  28 import static build.tools.cldrconverter.Bundle.jreTimeZoneNames;
  29 import build.tools.cldrconverter.BundleGenerator.BundleType;
  30 import java.io.File;
  31 import java.nio.file.*;
  32 import java.time.*;


  33 import java.util.*;
  34 import java.util.ResourceBundle.Control;
  35 import java.util.logging.Level;
  36 import java.util.logging.Logger;
  37 import java.util.stream.Collectors;
  38 import java.util.stream.IntStream;
  39 import java.util.stream.Stream;
  40 import javax.xml.parsers.SAXParser;
  41 import javax.xml.parsers.SAXParserFactory;
  42 import org.xml.sax.SAXNotRecognizedException;
  43 import org.xml.sax.SAXNotSupportedException;
  44 
  45 
  46 /**
  47  * Converts locale data from "Locale Data Markup Language" format to
  48  * JRE resource bundle format. LDML is the format used by the Common
  49  * Locale Data Repository maintained by the Unicode Consortium.
  50  */
  51 public class CLDRConverter {
  52 
  53     static final String LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldml.dtd";
  54     static final String SPPL_LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldmlSupplemental.dtd";
  55     static final String BCP47_LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldmlBCP47.dtd";
  56 
  57 
  58     private static String CLDR_BASE;
  59     static String LOCAL_LDML_DTD;
  60     static String LOCAL_SPPL_LDML_DTD;
  61     static String LOCAL_BCP47_LDML_DTD;
  62     private static String SOURCE_FILE_DIR;
  63     private static String SPPL_SOURCE_FILE;
  64     private static String SPPL_META_SOURCE_FILE;
  65     private static String NUMBERING_SOURCE_FILE;
  66     private static String METAZONES_SOURCE_FILE;
  67     private static String LIKELYSUBTAGS_SOURCE_FILE;
  68     private static String TIMEZONE_SOURCE_FILE;
  69     static String DESTINATION_DIR = "build/gensrc";
  70 
  71     static final String LOCALE_NAME_PREFIX = "locale.displayname.";
  72     static final String LOCALE_SEPARATOR = LOCALE_NAME_PREFIX + "separator";
  73     static final String LOCALE_KEYTYPE = LOCALE_NAME_PREFIX + "keytype";
  74     static final String LOCALE_KEY_PREFIX = LOCALE_NAME_PREFIX + "key.";
  75     static final String LOCALE_TYPE_PREFIX = LOCALE_NAME_PREFIX + "type.";
  76     static final String LOCALE_TYPE_PREFIX_CA = LOCALE_TYPE_PREFIX + "ca.";
  77     static final String CURRENCY_SYMBOL_PREFIX = "currency.symbol.";
  78     static final String CURRENCY_NAME_PREFIX = "currency.displayname.";
  79     static final String CALENDAR_NAME_PREFIX = "calendarname.";
  80     static final String CALENDAR_FIRSTDAY_PREFIX = "firstDay.";
  81     static final String CALENDAR_MINDAYS_PREFIX = "minDays.";
  82     static final String TIMEZONE_ID_PREFIX = "timezone.id.";
  83     static final String ZONE_NAME_PREFIX = "timezone.displayname.";
  84     static final String METAZONE_ID_PREFIX = "metazone.id.";
  85     static final String PARENT_LOCALE_PREFIX = "parentLocale.";
  86 
  87     private static SupplementDataParseHandler handlerSuppl;
  88     private static SupplementalMetadataParseHandler handlerSupplMeta;
  89     private static LikelySubtagsParseHandler handlerLikelySubtags;
  90     static NumberingSystemsParseHandler handlerNumbering;
  91     static MetaZonesParseHandler handlerMetaZones;
  92     static TimeZoneParseHandler handlerTimeZone;
  93     private static BundleGenerator bundleGenerator;
  94 
  95     // java.base module related
  96     static boolean isBaseModule = false;
  97     static final Set<Locale> BASE_LOCALES = new HashSet<>();
  98 
  99     // "parentLocales" map
 100     private static final Map<String, SortedSet<String>> parentLocalesMap = new HashMap<>();
 101     private static final ResourceBundle.Control defCon =
 102         ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
 103 
 104     private static final String[] AVAILABLE_TZIDS = TimeZone.getAvailableIDs();
 105     private static String zoneNameTempFile;
 106 
 107     static enum DraftType {
 108         UNCONFIRMED,
 109         PROVISIONAL,
 110         CONTRIBUTED,
 111         APPROVED;
 112 
 113         private static final Map<String, DraftType> map = new HashMap<>();
 114         static {
 115             for (DraftType dt : values()) {
 116                 map.put(dt.getKeyword(), dt);
 117             }
 118         }
 119         static private DraftType defaultType = CONTRIBUTED;
 120 
 121         private final String keyword;
 122 
 123         private DraftType() {
 124             keyword = this.name().toLowerCase(Locale.ROOT);
 125 
 126         }


 182                         break;
 183 
 184                     case "-basemodule":
 185                         // indicates java.base module resource generation
 186                         isBaseModule = true;
 187                         break;
 188 
 189                     case "-o":
 190                         // output directory
 191                         DESTINATION_DIR = args[++i];
 192                         break;
 193 
 194                     case "-utf8":
 195                         USE_UTF8 = true;
 196                         break;
 197 
 198                     case "-verbose":
 199                         verbose = true;
 200                         break;
 201 
 202                     case "-zntempfile":
 203                         zoneNameTempFile = args[++i];
 204                         break;
 205 
 206                     case "-help":
 207                         usage();
 208                         System.exit(0);
 209                         break;
 210 
 211                     default:
 212                         throw new RuntimeException();
 213                     }
 214                 }
 215             } catch (RuntimeException e) {
 216                 severe("unknown or imcomplete arg(s): " + currentArg);
 217                 usage();
 218                 System.exit(1);
 219             }
 220         }
 221 
 222         // Set up path names
 223         LOCAL_LDML_DTD = CLDR_BASE + "/dtd/ldml.dtd";
 224         LOCAL_SPPL_LDML_DTD = CLDR_BASE + "/dtd/ldmlSupplemental.dtd";
 225         LOCAL_BCP47_LDML_DTD = CLDR_BASE + "/dtd/ldmlBCP47.dtd";
 226         SOURCE_FILE_DIR = CLDR_BASE + "/main";
 227         SPPL_SOURCE_FILE = CLDR_BASE + "/supplemental/supplementalData.xml";
 228         LIKELYSUBTAGS_SOURCE_FILE = CLDR_BASE + "/supplemental/likelySubtags.xml";
 229         NUMBERING_SOURCE_FILE = CLDR_BASE + "/supplemental/numberingSystems.xml";
 230         METAZONES_SOURCE_FILE = CLDR_BASE + "/supplemental/metaZones.xml";
 231         TIMEZONE_SOURCE_FILE = CLDR_BASE + "/bcp47/timezone.xml";
 232         SPPL_META_SOURCE_FILE = CLDR_BASE + "/supplemental/supplementalMetadata.xml";
 233 
 234         if (BASE_LOCALES.isEmpty()) {
 235             setupBaseLocales("en-US");
 236         }
 237 
 238         bundleGenerator = new ResourceBundleGenerator();
 239 
 240         // Parse data independent of locales
 241         parseSupplemental();
 242         parseBCP47();
 243 
 244         List<Bundle> bundles = readBundleList();
 245         convertBundles(bundles);
 246 
 247         // Generate java.time.format.ZoneName.java
 248         if (isBaseModule) {
 249             generateZoneName();
 250         }
 251     }
 252 
 253     private static void usage() {
 254         errout("Usage: java CLDRConverter [options]%n"
 255                 + "\t-help          output this usage message and exit%n"
 256                 + "\t-verbose       output information%n"
 257                 + "\t-draft [contributed | approved | provisional | unconfirmed]%n"
 258                 + "\t\t       draft level for using data (default: contributed)%n"
 259                 + "\t-base dir      base directory for CLDR input files%n"
 260                 + "\t-basemodule    generates bundles that go into java.base module%n"
 261                 + "\t-baselocales loc(,loc)*      locales that go into the base module%n"
 262                 + "\t-o dir         output directory (default: ./build/gensrc)%n"
 263                 + "\t-zntempfile    template file for java.time.format.ZoneName.java%n"
 264                 + "\t-utf8          use UTF-8 rather than \\uxxxx (for debug)%n");
 265     }
 266 
 267     static void info(String fmt, Object... args) {
 268         if (verbose) {
 269             System.out.printf(fmt, args);
 270         }
 271     }
 272 
 273     static void info(String msg) {
 274         if (verbose) {
 275             System.out.println(msg);
 276         }
 277     }
 278 
 279     static void warning(String fmt, Object... args) {
 280         System.err.print("Warning: ");
 281         System.err.printf(fmt, args);
 282     }
 283 


 398         parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl);
 399         Map<String, Object> parentData = handlerSuppl.getData("root");
 400         parentData.keySet().stream()
 401                 .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
 402                 .forEach(key -> {
 403                 parentLocalesMap.put(key, new TreeSet(
 404                     Arrays.asList(((String)parentData.get(key)).split(" "))));
 405             });
 406 
 407         // Parse numberingSystems to get digit zero character information.
 408         handlerNumbering = new NumberingSystemsParseHandler();
 409         parseLDMLFile(new File(NUMBERING_SOURCE_FILE), handlerNumbering);
 410 
 411         // Parse metaZones to create mappings between Olson tzids and CLDR meta zone names
 412         handlerMetaZones = new MetaZonesParseHandler();
 413         parseLDMLFile(new File(METAZONES_SOURCE_FILE), handlerMetaZones);
 414 
 415         // Parse likelySubtags
 416         handlerLikelySubtags = new LikelySubtagsParseHandler();
 417         parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags);
 418 
 419         // Parse supplementalMetadata
 420         // Currently only interested in deprecated time zone ids.
 421         handlerSupplMeta = new SupplementalMetadataParseHandler();
 422         parseLDMLFile(new File(SPPL_META_SOURCE_FILE), handlerSupplMeta);
 423     }
 424 
 425     // Parsers for data in "bcp47" directory
 426     //
 427     private static void parseBCP47() throws Exception {
 428         // Parse timezone
 429         handlerTimeZone = new TimeZoneParseHandler();
 430         parseLDMLFile(new File(TIMEZONE_SOURCE_FILE), handlerTimeZone);
 431     }
 432 
 433     private static void parseLDMLFile(File srcfile, AbstractLDMLHandler handler) throws Exception {
 434         info("..... Parsing " + srcfile.getName() + " .....");
 435         SAXParserFactory pf = SAXParserFactory.newInstance();
 436         pf.setValidating(true);
 437         SAXParser parser = pf.newSAXParser();
 438         enableFileAccess(parser);
 439         parser.parse(srcfile, handler);
 440     }
 441 
 442     private static StringBuilder getCandLocales(Locale cldrLoc) {


 658                         names.put(tzid, cldrMeta.get().getValue());
 659                     } else {
 660                         // check the JRE meta key, add if there is not.
 661                         Optional<Map.Entry<String[], String>> jreMeta =
 662                             jreMetaMap.entrySet().stream()
 663                                 .filter(jm -> Arrays.deepEquals(data, jm.getKey()))
 664                                 .findAny();
 665                         if (jreMeta.isPresent()) {
 666                             names.put(tzid, jreMeta.get().getValue());
 667                         } else {
 668                             String metaName = "JRE_" + tzid.replaceAll("[/-]", "_");
 669                             names.put(METAZONE_ID_PREFIX + metaName, data);
 670                             names.put(tzid, metaName);
 671                             jreMetaMap.put(data, metaName);
 672                         }
 673                     }
 674                 }
 675             });
 676         }
 677 
 678         Arrays.stream(AVAILABLE_TZIDS).forEach(tzid -> {
 679             // If the tzid is deprecated, get the data for the replacement id
 680             String tzKey = Optional.ofNullable((String)handlerSupplMeta.get(tzid))
 681                                    .orElse(tzid);
 682             Object data = map.get(TIMEZONE_ID_PREFIX + tzKey);   
 683 
 684             if (data instanceof String[]) {
 685                 names.put(tzid, data);
 686             } else {
 687                 String meta = handlerMetaZones.get(tzKey);
 688                 if (meta != null) {
 689                     String metaKey = METAZONE_ID_PREFIX + meta;
 690                     data = map.get(metaKey);
 691                     if (data instanceof String[]) {
 692                         // Keep the metazone prefix here.
 693                         names.put(metaKey, data);
 694                         names.put(tzid, meta);
 695                     }
 696                 }
 697             }
 698         });
 699 
 700         return names;
 701     }
 702 
 703     /**
 704      * Extracts the language independent calendar data. Each of the two keys,
 705      * "firstDayOfWeek" and "minimalDaysInFirstWeek" has a string value consists of
 706      * one or multiple occurrences of:
 707      *  i: rg1 rg2 ... rgn;
 708      * where "i" is the data for the following regions (delimited by a space) after
 709      * ":", and ends with a ";".
 710      */
 711     private static Map<String, Object> extractCalendarData(Map<String, Object> map, String id) {
 712         Map<String, Object> calendarData = new LinkedHashMap<>();
 713         if (id.equals("root")) {
 714             calendarData.put("firstDayOfWeek",
 715                 IntStream.range(1, 8)
 716                     .mapToObj(String::valueOf)
 717                     .filter(d -> map.keySet().contains(CALENDAR_FIRSTDAY_PREFIX + d))
 718                     .map(d -> d + ": " + map.get(CALENDAR_FIRSTDAY_PREFIX + d))
 719                     .collect(Collectors.joining(";")));


 954                         "root".equals(parent) ? Locale.ROOT : Locale.forLanguageTag(parent));
 955                 });
 956             });
 957         }
 958 
 959         // check irregular parents
 960         for (int i = 0; i < candidates.size(); i++) {
 961             Locale l = candidates.get(i);
 962             Locale p = childToParentLocaleMap.get(l);
 963             if (!l.equals(Locale.ROOT) &&
 964                 Objects.nonNull(p) &&
 965                 !candidates.get(i+1).equals(p)) {
 966                 List<Locale> applied = candidates.subList(0, i+1);
 967                 applied.addAll(applyParentLocales(baseName, defCon.getCandidateLocales(baseName, p)));
 968                 return applied;
 969             }
 970         }
 971 
 972         return candidates;
 973     }
 974 
 975     private static void generateZoneName() throws Exception {
 976         Files.createDirectories(Paths.get(DESTINATION_DIR, "java", "time", "format"));
 977         Files.write(Paths.get(DESTINATION_DIR, "java", "time", "format", "ZoneName.java"),
 978             Files.lines(Paths.get(zoneNameTempFile))
 979                 .flatMap(l -> {
 980                     if (l.equals("%%%%ZIDMAP%%%%")) {
 981                         return zidMapEntry();
 982                     } else if (l.equals("%%%%MZONEMAP%%%%")) {
 983                         return handlerMetaZones.mzoneMapEntry();
 984                     } else if (l.equals("%%%%DEPRECATED%%%%")) {
 985                         return handlerSupplMeta.deprecatedMap();
 986                     } else {
 987                         return Stream.of(l);
 988                     }
 989                 })
 990                 .collect(Collectors.toList()),
 991             StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
 992     }
 993 
 994     private static Stream<String> zidMapEntry() {
 995         Map<String, String> canonMap = new HashMap<>();
 996         handlerTimeZone.getData().entrySet().stream()
 997             .forEach(e -> {
 998                 String[] ids = ((String)e.getValue()).split("\\s");
 999                 for (int i = 1; i < ids.length; i++) {
1000                     canonMap.put(ids[i], ids[0]);
1001                 }});
1002         return ZoneId.getAvailableZoneIds().stream()
1003                 .map(id -> {
1004                     String canonId = canonMap.getOrDefault(id, id);
1005                     String meta = handlerMetaZones.get(canonId);
1006                     String zone001 = handlerMetaZones.zidMap().get(meta);
1007                     return zone001 == null ? "" :
1008                             String.format("        \"%s\", \"%s\", \"%s\",",
1009                                             id, meta, zone001);
1010                 })
1011                 .filter(s -> !s.isEmpty())
1012                 .sorted();
1013     }
1014 }
< prev index next >