EquivMapsGenerator.java revision 8729:0242fce0f717
1/*
2 * Copyright (c) 2012, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.io.*;
25import java.nio.charset.*;
26import java.nio.file.*;
27import java.util.*;
28
29public class EquivMapsGenerator {
30
31    /*
32     * IANA Language Subtag Registry file downloaded from
33     *     http://www.iana.org/assignments/language-subtag-registry
34     */
35    private static final String DEFAULT_LSR_FILE =
36        "language-subtag-registry.txt";
37
38    private static boolean verbose = false;
39
40    public static void main(String[] args) throws Exception {
41        String fileLSR = DEFAULT_LSR_FILE;
42
43        for (int i = 0; i < args.length; i++) {
44            String s = args[i];
45            if (s.equals("-lsr")) {
46                fileLSR = args[++i];
47            } else if (s.equals("-verbose")) {
48                verbose = true;
49            }
50        }
51
52        readLSRfile(fileLSR);
53        generateEquivalentMap();
54        generateSourceCode();
55    }
56
57    private static String LSRrevisionDate;
58    private static Map<String, StringBuilder> initialLanguageMap =
59        new TreeMap<>();
60    private static Map<String, StringBuilder> initialRegionVariantMap =
61        new TreeMap<>();
62
63    private static Map<String, String> sortedLanguageMap1 = new TreeMap<>();
64    private static Map<String, String[]> sortedLanguageMap2 = new TreeMap<>();
65    private static Map<String, String> sortedRegionVariantMap =
66        new TreeMap<>();
67
68    private static void readLSRfile(String filename) throws Exception {
69        String type = null;
70        String tag = null;
71        String preferred = null;
72        int mappingNum = 0;
73
74        for (String line : Files.readAllLines(Paths.get(filename),
75                                              Charset.forName("UTF-8"))) {
76            line = line.toLowerCase();
77            int index = line.indexOf(' ')+1;
78            if (line.startsWith("file-date:")) {
79                LSRrevisionDate = line.substring(index);
80                if (verbose) {
81                    System.out.println("LSR revision date=" + LSRrevisionDate);
82                }
83            } else if (line.startsWith("type:")) {
84                type = line.substring(index);
85            } else if (line.startsWith("tag:") || line.startsWith("subtag:")) {
86                tag = line.substring(index);
87            } else if (line.startsWith("preferred-value:")
88                       && !type.equals("extlang")) {
89                preferred = line.substring(index);
90                mappingNum++;
91                processDeprecatedData(type, tag, preferred);
92            } else if (line.equals("%%")) {
93                type = null;
94                tag = null;
95                preferred = null;
96            }
97        }
98
99        if (verbose) {
100            System.out.println("readLSRfile(" + filename + ")");
101            System.out.println("  Total number of mapping=" + mappingNum);
102            System.out.println("\n  Map for language. Size="
103                + initialLanguageMap.size());
104
105            for (String key : initialLanguageMap.keySet()) {
106                System.out.println("    " + key + ": \""
107                    + initialLanguageMap.get(key) + "\"");
108            }
109
110            System.out.println("\n  Map for region and variant. Size="
111                + initialRegionVariantMap.size());
112
113            for (String key : initialRegionVariantMap.keySet()) {
114                System.out.println("    " + key + ": \""
115                    + initialRegionVariantMap.get(key) + "\"");
116            }
117        }
118    }
119
120    private static void processDeprecatedData(String type,
121                                              String tag,
122                                              String preferred) {
123        StringBuilder sb;
124        if (type.equals("region") || type.equals("variant")) {
125            if (!initialRegionVariantMap.containsKey(preferred)) {
126                sb = new StringBuilder("-");
127                sb.append(preferred);
128                sb.append(",-");
129                sb.append(tag);
130                initialRegionVariantMap.put("-"+preferred, sb);
131            } else {
132                throw new RuntimeException("New case, need implementation."
133                    + " A region/variant subtag \"" + preferred
134                    + "\" is registered for more than one subtags.");
135            }
136        } else { // language, grandfahered, and redundant
137            if (!initialLanguageMap.containsKey(preferred)) {
138                sb = new StringBuilder(preferred);
139                sb.append(',');
140                sb.append(tag);
141                initialLanguageMap.put(preferred, sb);
142            } else {
143                sb = initialLanguageMap.get(preferred);
144                sb.append(',');
145                sb.append(tag);
146                initialLanguageMap.put(preferred, sb);
147            }
148        }
149    }
150
151    private static void generateEquivalentMap() {
152        String[] subtags;
153        for (String preferred : initialLanguageMap.keySet()) {
154            subtags = initialLanguageMap.get(preferred).toString().split(",");
155
156            if (subtags.length == 2) {
157                sortedLanguageMap1.put(subtags[0], subtags[1]);
158                sortedLanguageMap1.put(subtags[1], subtags[0]);
159            } else if (subtags.length == 3) {
160                sortedLanguageMap2.put(subtags[0],
161                                     new String[]{subtags[1], subtags[2]});
162                sortedLanguageMap2.put(subtags[1],
163                                     new String[]{subtags[0], subtags[2]});
164                sortedLanguageMap2.put(subtags[2],
165                                     new String[]{subtags[0], subtags[1]});
166            } else {
167                    throw new RuntimeException("New case, need implementation."
168                        + " A language subtag \"" + preferred
169                        + "\" is registered for more than two subtags. ");
170            }
171        }
172
173        for (String preferred : initialRegionVariantMap.keySet()) {
174            subtags =
175                initialRegionVariantMap.get(preferred).toString().split(",");
176
177            sortedRegionVariantMap.put(subtags[0], subtags[1]);
178            sortedRegionVariantMap.put(subtags[1], subtags[0]);
179        }
180
181        if (verbose) {
182            System.out.println("generateEquivalentMap()");
183            System.out.println("  \nSorted map for language subtags which have only one equivalent. Size="
184                + sortedLanguageMap1.size());
185            for (String key : sortedLanguageMap1.keySet()) {
186                System.out.println("    " + key + ": \""
187                    + sortedLanguageMap1.get(key) + "\"");
188            }
189
190            System.out.println("\n  Sorted map for language subtags which have multiple equivalents. Size="
191                + sortedLanguageMap2.size());
192            for (String key : sortedLanguageMap2.keySet()) {
193                String[] s = sortedLanguageMap2.get(key);
194                System.out.println("    " + key + ": \""
195                    + s[0] + "\", \"" + s[1] + "\"");
196            }
197
198            System.out.println("\n  Sorted map for region and variant subtags. Size="
199                + sortedRegionVariantMap.size());
200            for (String key : sortedRegionVariantMap.keySet()) {
201                System.out.println("    " + key + ": \""
202                    + sortedRegionVariantMap.get(key) + "\"");
203            }
204        }
205        System.out.println();
206    }
207
208    private final static String headerText =
209        "final class LocaleEquivalentMaps {\n\n"
210        + "    static final Map<String, String> singleEquivMap;\n"
211        + "    static final Map<String, String[]> multiEquivsMap;\n"
212        + "    static final Map<String, String> regionVariantEquivMap;\n\n"
213        + "    static {\n"
214        + "        singleEquivMap = new HashMap<>();\n"
215        + "        multiEquivsMap = new HashMap<>();\n"
216        + "        regionVariantEquivMap = new HashMap<>();\n\n"
217        + "        // This is an auto-generated file and should not be manually edited.\n";
218
219    private final static String footerText =
220        "    }\n\n"
221        + "}";
222
223    private static void generateSourceCode() {
224        System.out.println(headerText
225            + "        //   LSR Revision: " + LSRrevisionDate);
226
227        for (String key : sortedLanguageMap1.keySet()) {
228            String value = sortedLanguageMap1.get(key);
229            System.out.println("        singleEquivMap.put(\""
230                + key + "\", \"" + value + "\");");
231        }
232        System.out.println();
233        for (String key : sortedLanguageMap2.keySet()) {
234            String[] values = sortedLanguageMap2.get(key);
235            System.out.println("        multiEquivsMap.put(\""
236                + key + "\", new String[] {\"" + values[0] + "\", \""
237                + values[1] + "\"});");
238        }
239        System.out.println();
240        for (String key : sortedRegionVariantMap.keySet()) {
241            String value = sortedRegionVariantMap.get(key);
242            System.out.println("        regionVariantEquivMap.put(\""
243                + key + "\", \"" + value + "\");");
244        }
245
246        System.out.println(footerText);
247    }
248
249}
250