1 /* 2 * Copyright (c) 2012, 2016, 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 java.io.File; 29 import java.io.IOException; 30 import java.io.PrintWriter; 31 import java.util.Formatter; 32 import java.util.HashSet; 33 import java.util.LinkedHashMap; 34 import java.util.Map; 35 import java.util.Set; 36 import java.util.SortedSet; 37 38 class ResourceBundleGenerator implements BundleGenerator { 39 // preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations 40 private static final String[] preferredTZIDs = { 41 "America/Los_Angeles", 42 "America/Denver", 43 "America/Phoenix", 44 "America/Chicago", 45 "America/New_York", 46 "America/Indianapolis", 47 "Pacific/Honolulu", 48 "America/Anchorage", 49 "America/Halifax", 50 "America/Sitka", 51 "America/St_Johns", 52 "Europe/Paris", 53 // Although CLDR does not support abbreviated zones, handle "GMT" as a 54 // special case here, as it is specified in the javadoc. 55 "GMT", 56 "Africa/Casablanca", 57 "Asia/Jerusalem", 58 "Asia/Tokyo", 59 "Europe/Bucharest", 60 "Asia/Shanghai", 61 "UTC", 62 }; 63 64 @Override 65 public void generateBundle(String packageName, String baseName, String localeID, boolean useJava, 66 Map<String, ?> map, BundleType type) throws IOException { 67 String suffix = useJava ? ".java" : ".properties"; 68 String lang = CLDRConverter.getLanguageCode(localeID); 69 String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator 70 + packageName + File.separator + "resources" + File.separator + "cldr"; 71 if (lang.length() > 0) { 72 dirName = dirName + File.separator + lang; 73 packageName = packageName + ".resources.cldr." + lang; 74 } else { 75 packageName = packageName + ".resources.cldr"; 76 } 77 File dir = new File(dirName); 78 if (!dir.exists()) { 79 dir.mkdirs(); 80 } 81 File file = new File(dir, baseName + ("root".equals(localeID) ? "" : "_" + localeID) + suffix); 82 if (!file.exists()) { 83 file.createNewFile(); 84 } 85 CLDRConverter.info("\tWriting file " + file); 86 87 String encoding; 88 if (useJava) { 89 if (CLDRConverter.USE_UTF8) { 90 encoding = "utf-8"; 91 } else { 92 encoding = "us-ascii"; 93 } 94 } else { 95 encoding = "iso-8859-1"; 96 } 97 98 Formatter fmt = null; 99 if (type == BundleType.TIMEZONE) { 100 fmt = new Formatter(); 101 Set<String> metaKeys = new HashSet<>(); 102 for (String key : map.keySet()) { 103 if (key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) { 104 String meta = key.substring(CLDRConverter.METAZONE_ID_PREFIX.length()); 105 String[] value; 106 value = (String[]) map.get(key); 107 fmt.format(" final String[] %s = new String[] {\n", meta); 108 for (String s : value) { 109 fmt.format(" \"%s\",\n", CLDRConverter.saveConvert(s, useJava)); 110 } 111 fmt.format(" };\n"); 112 metaKeys.add(key); 113 } 114 } 115 for (String key : metaKeys) { 116 map.remove(key); 117 } 118 119 // Make it preferred ordered 120 LinkedHashMap<String, Object> newMap = new LinkedHashMap<>(); 121 for (String preferred : preferredTZIDs) { 122 if (map.containsKey(preferred)) { 123 newMap.put(preferred, map.remove(preferred)); 124 } else if (("GMT".equals(preferred) || "UTC".equals(preferred)) && 125 metaKeys.contains(CLDRConverter.METAZONE_ID_PREFIX+preferred)) { 126 newMap.put(preferred, preferred); 127 } 128 } 129 newMap.putAll(map); 130 map = newMap; 131 } 132 133 try (PrintWriter out = new PrintWriter(file, encoding)) { 134 // Output copyright headers 135 out.println(CopyrightHeaders.getOpenJDKCopyright()); 136 out.println(CopyrightHeaders.getUnicodeCopyright()); 137 138 if (useJava) { 139 out.println("package sun." + packageName + ";\n"); 140 out.printf("import %s;\n\n", type.getPathName()); 141 out.printf("public class %s%s extends %s {\n", baseName, "root".equals(localeID) ? "" : "_" + localeID, type.getClassName()); 142 143 out.println(" @Override\n" + 144 " protected final Object[][] getContents() {"); 145 if (fmt != null) { 146 out.print(fmt.toString()); 147 } 148 out.println(" final Object[][] data = new Object[][] {"); 149 } 150 for (String key : map.keySet()) { 151 if (useJava) { 152 Object value = map.get(key); 153 if (value == null) { 154 CLDRConverter.warning("null value for " + key); 155 } else if (value instanceof String) { 156 if (type == BundleType.TIMEZONE) { 157 out.printf(" { \"%s\", %s },\n", key, CLDRConverter.saveConvert((String) value, useJava)); 158 } else { 159 out.printf(" { \"%s\", \"%s\" },\n", key, CLDRConverter.saveConvert((String) value, useJava)); 160 } 161 } else if (value instanceof String[]) { 162 String[] values = (String[]) value; 163 out.println(" { \"" + key + "\",\n new String[] {"); 164 for (String s : values) { 165 out.println(" \"" + CLDRConverter.saveConvert(s, useJava) + "\","); 166 } 167 out.println(" }\n },"); 168 } else { 169 throw new RuntimeException("unknown value type: " + value.getClass().getName()); 170 } 171 } else { 172 out.println(key + "=" + CLDRConverter.saveConvert((String) map.get(key), useJava)); 173 } 174 } 175 if (useJava) { 176 out.println(" };\n return data;\n }\n}"); 177 } 178 } 179 } 180 181 private static final String METAINFO_CLASS = "CLDRLocaleDataMetaInfo"; 182 183 @Override 184 public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException { 185 String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" + File.separator 186 + "cldr" + File.separator; 187 File dir = new File(dirName); 188 if (!dir.exists()) { 189 dir.mkdirs(); 190 } 191 File file = new File(dir, METAINFO_CLASS + ".java"); 192 if (!file.exists()) { 193 file.createNewFile(); 194 } 195 CLDRConverter.info("Generating file " + file); 196 197 try (PrintWriter out = new PrintWriter(file, "us-ascii")) { 198 out.println(CopyrightHeaders.getOpenJDKCopyright()); 199 200 out.println("package sun.util.cldr;\n\n" 201 + "import java.util.ListResourceBundle;\n"); 202 out.printf("public class %s extends ListResourceBundle {\n", METAINFO_CLASS); 203 out.println(" @Override\n" + 204 " protected final Object[][] getContents() {\n" + 205 " final Object[][] data = new Object[][] {"); 206 for (String key : metaInfo.keySet()) { 207 out.printf(" { \"%s\",\n", key); 208 out.printf(" \"%s\" },\n", toLocaleList(metaInfo.get(key))); 209 } 210 out.println(" };\n return data;\n }\n}"); 211 } 212 } 213 214 private static String toLocaleList(SortedSet<String> set) { 215 StringBuilder sb = new StringBuilder(set.size() * 6); 216 for (String id : set) { 217 if (!"root".equals(id)) { 218 if (sb.length() > 0) { 219 sb.append(' '); 220 } 221 sb.append(id); 222 } 223 } 224 return sb.toString(); 225 } 226 }