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