12be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka/* 22be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * Copyright (C) 2012 The Android Open Source Project 32be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * 42be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 52be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * you may not use this file except in compliance with the License. 62be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * You may obtain a copy of the License at 72be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * 82be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 92be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * 102be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 112be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 122be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * See the License for the specific language governing permissions and 142be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka * limitations under the License. 152be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka */ 162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 17ca6acfdd6b3400ad6e29d45c29b0ec40ea92a968Tadashi G. Takaokapackage com.android.inputmethod.keyboard.tools; 182be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 192be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.Closeable; 202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.File; 212be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.IOException; 222be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.InputStream; 232be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.InputStreamReader; 242be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.LineNumberReader; 252be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.PrintStream; 262be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.ArrayList; 272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.Collections; 282be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.HashMap; 292be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.Locale; 302be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.jar.JarFile; 312be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 322be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokapublic class MoreKeysResources { 336bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private static final String TEXT_RESOURCE_NAME = "donottranslate-more-keys.xml"; 342be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 356bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private static final String JAVA_TEMPLATE = "KeyboardTextsSet.tmpl"; 362be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static final String MARK_NAMES = "@NAMES@"; 376bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private static final String MARK_DEFAULT_TEXTS = "@DEFAULT_TEXTS@"; 386bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private static final String MARK_TEXTS = "@TEXTS@"; 396bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private static final String MARK_LANGUAGES_AND_TEXTS = "@LANGUAGES_AND_TEXTS@"; 402be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static final String DEFAUT_LANGUAGE_NAME = "DEFAULT"; 412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static final String ARRAY_NAME_FOR_LANGUAGE = "LANGUAGE_%s"; 422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static final String EMPTY_STRING_VAR = "EMPTY"; 432be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 442be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static final String NO_LANGUAGE_CODE = "zz"; 45c5beb522ed954d372a4a1e3f38db7b56d37eb820Jean Chalard private static final String NO_LANGUAGE_DISPLAY_NAME = "Alphabet"; 462be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 472be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private final JarFile mJar; 482be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka // Language to string resources map. 492be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private final HashMap<String, StringResourceMap> mResourcesMap = 502be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka new HashMap<String, StringResourceMap>(); 512be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka // Name to id map. 522be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private final HashMap<String, Integer> mNameToIdMap = new HashMap<String,Integer>(); 532be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 542be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public MoreKeysResources(final JarFile jar) { 552be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka mJar = jar; 566bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka final ArrayList<String> resources = JarUtils.getNameListing(jar, TEXT_RESOURCE_NAME); 572be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final String name : resources) { 582be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String dirName = name.substring(0, name.lastIndexOf('/')); 592be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final int pos = dirName.lastIndexOf('/'); 602be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String parentName = (pos >= 0) ? dirName.substring(pos + 1) : dirName; 612be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String language = getLanguageFromResDir(parentName); 622be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final InputStream stream = JarUtils.openResource(name); 632be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka try { 642be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka mResourcesMap.put(language, new StringResourceMap(stream)); 652be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } finally { 662be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka close(stream); 672be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 682be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 692be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 702be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 712be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String getLanguageFromResDir(final String dirName) { 722be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final int languagePos = dirName.indexOf('-'); 732be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (languagePos < 0) { 742be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka // Default resource. 752be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return DEFAUT_LANGUAGE_NAME; 762be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 772be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String language = dirName.substring(languagePos + 1); 782be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final int countryPos = language.indexOf("-r"); 792be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (countryPos < 0) { 802be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return language; 812be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 822be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return language.replace("-r", "_"); 832be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 842be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 852be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public void writeToJava(final String outDir) { 862be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final ArrayList<String> list = JarUtils.getNameListing(mJar, JAVA_TEMPLATE); 872be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (list.isEmpty()) 882be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException("Can't find java template " + JAVA_TEMPLATE); 892be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (list.size() > 1) 902be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException("Found multiple java template " + JAVA_TEMPLATE); 912be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String template = list.get(0); 922be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String javaPackage = template.substring(0, template.lastIndexOf('/')); 932be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka PrintStream ps = null; 942be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka LineNumberReader lnr = null; 952be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka try { 962be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (outDir == null) { 972be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka ps = System.out; 982be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 992be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final File outPackage = new File(outDir, javaPackage); 1002be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final File outputFile = new File(outPackage, 1012be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka JAVA_TEMPLATE.replace(".tmpl", ".java")); 1022be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka outPackage.mkdirs(); 1039c9802e6473e5e2e2b792d5f14502139feb49637Tadashi G. Takaoka ps = new PrintStream(outputFile, "UTF-8"); 1042be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1052be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka lnr = new LineNumberReader(new InputStreamReader(JarUtils.openResource(template))); 1062be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka inflateTemplate(lnr, ps); 1072be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } catch (IOException e) { 1082be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException(e); 1092be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } finally { 1102be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka close(lnr); 1112be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka close(ps); 1122be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1132be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1142be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1152be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private void inflateTemplate(final LineNumberReader in, final PrintStream out) 1162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throws IOException { 1172be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka String line; 1182be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka while ((line = in.readLine()) != null) { 1192be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (line.contains(MARK_NAMES)) { 1202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka dumpNames(out); 1216bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka } else if (line.contains(MARK_DEFAULT_TEXTS)) { 1226bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka dumpDefaultTexts(out); 1236bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka } else if (line.contains(MARK_TEXTS)) { 1246bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka dumpTexts(out); 1256bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka } else if (line.contains(MARK_LANGUAGES_AND_TEXTS)) { 1262be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka dumpLanguageMap(out); 1272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 1282be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.println(line); 1292be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1302be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1312be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1322be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1332be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private void dumpNames(final PrintStream out) { 1342be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringResourceMap defaultResMap = mResourcesMap.get(DEFAUT_LANGUAGE_NAME); 1352be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka int id = 0; 1362be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final StringResource res : defaultResMap.getResources()) { 1372be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.format(" /* %2d */ \"%s\",\n", id, res.mName); 1382be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka mNameToIdMap.put(res.mName, id); 1392be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka id++; 1402be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1436bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private void dumpDefaultTexts(final PrintStream out) { 1442be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringResourceMap defaultResMap = mResourcesMap.get(DEFAUT_LANGUAGE_NAME); 1456bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka dumpTextsInternal(out, defaultResMap, defaultResMap); 1462be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1472be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1486bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private void dumpTexts(final PrintStream out) { 1492be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringResourceMap defaultResMap = mResourcesMap.get(DEFAUT_LANGUAGE_NAME); 1502be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final ArrayList<String> allLanguages = new ArrayList<String>(); 1512be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka allLanguages.addAll(mResourcesMap.keySet()); 1522be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka Collections.sort(allLanguages); 1532be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final String language : allLanguages) { 1542be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (language.equals(DEFAUT_LANGUAGE_NAME)) { 1552be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka continue; 1562be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1572be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.format(" /* Language %s: %s */\n", language, getLanguageDisplayName(language)); 1582be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.format(" private static final String[] " + ARRAY_NAME_FOR_LANGUAGE + " = {\n", 1592be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka language); 1602be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringResourceMap resMap = mResourcesMap.get(language); 161c27e899dbe3915d12da48feb49f6796da151cec2Tadashi G. Takaoka for (final StringResource res : resMap.getResources()) { 162c27e899dbe3915d12da48feb49f6796da151cec2Tadashi G. Takaoka if (!defaultResMap.contains(res.mName)) { 163c27e899dbe3915d12da48feb49f6796da151cec2Tadashi G. Takaoka throw new RuntimeException(res.mName + " in " + language 164c27e899dbe3915d12da48feb49f6796da151cec2Tadashi G. Takaoka + " doesn't have default resource"); 165c27e899dbe3915d12da48feb49f6796da151cec2Tadashi G. Takaoka } 166c27e899dbe3915d12da48feb49f6796da151cec2Tadashi G. Takaoka } 1676bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka dumpTextsInternal(out, resMap, defaultResMap); 1682be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.format(" };\n\n"); 1692be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1702be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1712be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1722be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private void dumpLanguageMap(final PrintStream out) { 1732be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final ArrayList<String> allLanguages = new ArrayList<String>(); 1742be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka allLanguages.addAll(mResourcesMap.keySet()); 1752be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka Collections.sort(allLanguages); 1762be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final String language : allLanguages) { 1772be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.format(" \"%s\", " + ARRAY_NAME_FOR_LANGUAGE + ", /* %s */\n", 1782be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka language, language, getLanguageDisplayName(language)); 1792be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1802be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1812be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1822be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String getLanguageDisplayName(final String language) { 1832be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (language.equals(NO_LANGUAGE_CODE)) { 1842be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return NO_LANGUAGE_DISPLAY_NAME; 1852be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 1862be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return new Locale(language).getDisplayLanguage(); 1872be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1882be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1892be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1906bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private static void dumpTextsInternal(final PrintStream out, final StringResourceMap resMap, 1912be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringResourceMap defaultResMap) { 1922be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final ArrayInitializerFormatter formatter = 1932be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka new ArrayInitializerFormatter(out, 100, " "); 1942be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka boolean successiveNull = false; 1952be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final StringResource defaultRes : defaultResMap.getResources()) { 1962be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (resMap.contains(defaultRes.mName)) { 1972be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringResource res = resMap.get(defaultRes.mName); 1982be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (res.mComment != null) { 1992be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outCommentLines(addPrefix(" // ", res. mComment)); 2002be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2012be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String escaped = escapeNonAscii(res.mValue); 2022be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (escaped.length() == 0) { 2032be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outElement(EMPTY_STRING_VAR + ","); 2042be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 2052be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outElement(String.format("\"%s\",", escaped)); 2062be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2072be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka successiveNull = false; 2082be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 2092be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outElement("null,"); 2102be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka successiveNull = true; 2112be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2122be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2132be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (!successiveNull) { 2142be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.flush(); 2152be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2172be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2182be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String addPrefix(final String prefix, final String lines) { 2192be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringBuilder sb = new StringBuilder(); 2202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final String line : lines.split("\n")) { 2212be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka sb.append(prefix + line.trim() + "\n"); 2222be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2232be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return sb.toString(); 2242be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2252be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2262be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String escapeNonAscii(final String text) { 2272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringBuilder sb = new StringBuilder(); 2282be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final int length = text.length(); 2292be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (int i = 0; i < length; i++) { 2302be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final char c = text.charAt(i); 2312be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (c >= ' ' && c < 0x7f) { 2322be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka sb.append(c); 2332be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 2342be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka sb.append(String.format("\\u%04X", (int)c)); 2352be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2362be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2372be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return replaceIncompatibleEscape(sb.toString()); 2382be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2392be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2402be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String replaceIncompatibleEscape(final String text) { 2412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka String t = text; 2422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka t = replaceAll(t, "\\?", "?"); 2432be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka t = replaceAll(t, "\\@", "@"); 2446bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka t = replaceAll(t, "@string/", "!text/"); 2452be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return t; 2462be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2472be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2482be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String replaceAll(final String text, final String target, final String replace) { 2492be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka String t = text; 2502be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka while (t.indexOf(target) >= 0) { 2512be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka t = t.replace(target, replace); 2522be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2532be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return t; 2542be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2552be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2562be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static void close(Closeable stream) { 2572be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka try { 2582be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (stream != null) { 2592be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka stream.close(); 2602be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2612be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } catch (IOException e) { 2622be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2632be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2642be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka} 265