Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java
32287 views
/*1* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package build.tools.generatelsrequivmaps;2627import java.io.BufferedWriter;28import java.io.IOException;29import java.nio.charset.Charset;30import java.nio.charset.StandardCharsets;31import java.nio.file.Files;32import java.nio.file.Paths;33import java.util.ArrayList;34import java.util.Calendar;35import java.util.List;36import java.util.Locale;37import java.util.Map;38import java.util.TimeZone;39import java.util.TreeMap;4041/**42* This tool reads the IANA Language Subtag Registry data file downloaded from43* http://www.iana.org/assignments/language-subtag-registry, which is specified44* in the command line and generates a .java source file as specified in45* command line. The generated .java source file contains equivalent language46* maps. These equivalent language maps are used by LocaleMatcher.java47* for the locale matching mechanism specified in RFC 4647 "Matching of Language48* Tags".49*/50public class EquivMapsGenerator {5152public static void main(String[] args) throws Exception {53if (args.length != 2) {54System.err.println("Usage: java EquivMapsGenerator"55+ " language-subtag-registry.txt LocaleEquivalentMaps.java");56System.exit(1);57}58readLSRfile(args[0]);59generateEquivalentMap();60generateSourceCode(args[1]);61}6263private static String LSRrevisionDate;64private static Map<String, StringBuilder> initialLanguageMap =65new TreeMap<>();66private static Map<String, StringBuilder> initialRegionVariantMap =67new TreeMap<>();6869private static Map<String, String> sortedLanguageMap1 = new TreeMap<>();70private static Map<String, String[]> sortedLanguageMap2 = new TreeMap<>();71private static Map<String, String> sortedRegionVariantMap =72new TreeMap<>();7374private static void readLSRfile(String filename) throws Exception {75String type = null;76String tag = null;77String preferred = null;7879for (String line : Files.readAllLines(Paths.get(filename),80Charset.forName("UTF-8"))) {81line = line.toLowerCase(Locale.ROOT);82int index = line.indexOf(' ')+1;83if (line.startsWith("file-date:")) {84LSRrevisionDate = line.substring(index);85} else if (line.startsWith("type:")) {86type = line.substring(index);87} else if (line.startsWith("tag:") || line.startsWith("subtag:")) {88tag = line.substring(index);89} else if (line.startsWith("preferred-value:")90&& !type.equals("extlang")) {91preferred = line.substring(index);92processDeprecatedData(type, tag, preferred);93} else if (line.equals("%%")) {94type = null;95tag = null;96}97}98}99100private static void processDeprecatedData(String type,101String tag,102String preferred) {103StringBuilder sb;104if (type.equals("region") || type.equals("variant")) {105if (!initialRegionVariantMap.containsKey(preferred)) {106sb = new StringBuilder("-");107sb.append(preferred);108sb.append(",-");109sb.append(tag);110initialRegionVariantMap.put("-"+preferred, sb);111} else {112throw new RuntimeException("New case, need implementation."113+ " A region/variant subtag \"" + preferred114+ "\" is registered for more than one subtags.");115}116} else { // language, grandfahered, and redundant117if (!initialLanguageMap.containsKey(preferred)) {118sb = new StringBuilder(preferred);119sb.append(',');120sb.append(tag);121initialLanguageMap.put(preferred, sb);122} else {123sb = initialLanguageMap.get(preferred);124sb.append(',');125sb.append(tag);126initialLanguageMap.put(preferred, sb);127}128}129}130131private static void generateEquivalentMap() {132String[] subtags;133for (String preferred : initialLanguageMap.keySet()) {134subtags = initialLanguageMap.get(preferred).toString().split(",");135136if (subtags.length == 2) {137sortedLanguageMap1.put(subtags[0], subtags[1]);138sortedLanguageMap1.put(subtags[1], subtags[0]);139} else if (subtags.length > 2) {140for (int i = 0; i < subtags.length; i++) {141sortedLanguageMap2.put(subtags[i], createLangArray(i, subtags));142}143} else {144throw new RuntimeException("New case, need implementation."145+ " A language subtag \"" + preferred146+ "\" is registered for more than two subtags. ");147}148}149150for (String preferred : initialRegionVariantMap.keySet()) {151subtags =152initialRegionVariantMap.get(preferred).toString().split(",");153154sortedRegionVariantMap.put(subtags[0], subtags[1]);155sortedRegionVariantMap.put(subtags[1], subtags[0]);156}157158}159160/* create the array of subtags excluding the subtag at index location */161private static String[] createLangArray(int index, String[] subtags) {162List<String> list = new ArrayList<>();163for (int i = 0; i < subtags.length; i++) {164if (i != index) {165list.add(subtags[i]);166}167}168return list.toArray(new String[list.size()]);169}170171private static String generateValuesString(String[] values) {172String outputStr = "";173for (int i = 0; i < values.length; i++) {174if (i != values.length - 1) {175outputStr = outputStr + "\"" + values[i] + "\", ";176} else {177outputStr = outputStr + "\"" + values[i] + "\"";178}179180}181return outputStr;182}183184private static final String COPYRIGHT = "/*\n"185+ " * Copyright (c) 2012, %d, Oracle and/or its affiliates. All rights reserved.\n"186+ " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n"187+ " *\n"188+ " * This code is free software; you can redistribute it and/or modify it\n"189+ " * under the terms of the GNU General Public License version 2 only, as\n"190+ " * published by the Free Software Foundation. Oracle designates this\n"191+ " * particular file as subject to the \"Classpath\" exception as provided\n"192+ " * by Oracle in the LICENSE file that accompanied this code.\n"193+ " *\n"194+ " * This code is distributed in the hope that it will be useful, but WITHOUT\n"195+ " * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n"196+ " * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n"197+ " * version 2 for more details (a copy is included in the LICENSE file that\n"198+ " * accompanied this code).\n"199+ " *\n"200+ " * You should have received a copy of the GNU General Public License version\n"201+ " * 2 along with this work; if not, write to the Free Software Foundation,\n"202+ " * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n"203+ " *\n"204+ " * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n"205+ " * or visit www.oracle.com if you need additional information or have any\n"206+ " * questions.\n"207+ "*/\n\n";208209private static final String headerText =210"package sun.util.locale;\n\n"211+ "import java.util.HashMap;\n"212+ "import java.util.Map;\n\n"213+ "final class LocaleEquivalentMaps {\n\n"214+ " static final Map<String, String> singleEquivMap;\n"215+ " static final Map<String, String[]> multiEquivsMap;\n"216+ " static final Map<String, String> regionVariantEquivMap;\n\n"217+ " static {\n"218+ " singleEquivMap = new HashMap<>();\n"219+ " multiEquivsMap = new HashMap<>();\n"220+ " regionVariantEquivMap = new HashMap<>();\n\n"221+ " // This is an auto-generated file and should not be manually edited.\n";222223private static final String footerText =224" }\n\n"225+ "}";226227private static String getOpenJDKCopyright() {228int year = Calendar.getInstance(TimeZone229.getTimeZone("America/Los_Angeles")).get(Calendar.YEAR);230return String.format(Locale.US, COPYRIGHT, year);231}232233/**234* The input lsr data file is in UTF-8, so theoretically for the characters235* beyond US-ASCII, the generated Java String literals need to be Unicode236* escaped (\\uXXXX) while writing to a file. But as of now, there is not237* the case since we don't use "description", "comment" or alike.238*/239private static void generateSourceCode(String fileName) {240241try (BufferedWriter writer = Files.newBufferedWriter(242Paths.get(fileName), StandardCharsets.UTF_8)) {243writer.write(getOpenJDKCopyright());244writer.write(headerText245+ " // LSR Revision: " + LSRrevisionDate);246writer.newLine();247248for (String key : sortedLanguageMap1.keySet()) {249String value = sortedLanguageMap1.get(key);250writer.write(" singleEquivMap.put(\""251+ key + "\", \"" + value + "\");");252writer.newLine();253}254255writer.newLine();256for (String key : sortedLanguageMap2.keySet()) {257String[] values = sortedLanguageMap2.get(key);258259if (values.length >= 2) {260writer.write(" multiEquivsMap.put(\""261+ key + "\", new String[] {"262+ generateValuesString(values) + "});");263writer.newLine();264}265}266267writer.newLine();268for (String key : sortedRegionVariantMap.keySet()) {269String value = sortedRegionVariantMap.get(key);270writer.write(" regionVariantEquivMap.put(\""271+ key + "\", \"" + value + "\");");272writer.newLine();273}274275writer.write(footerText);276} catch (IOException ex) {277ex.printStackTrace(System.err);278System.exit(1);279}280281}282283}284285286