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 24 import java.io.*; 25 import java.nio.charset.*; 26 import java.nio.file.*; 27 import java.util.*; 28 29 public 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 }