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.File; 202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.IOException; 212be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.InputStreamReader; 222be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.LineNumberReader; 232be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.io.PrintStream; 242be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.ArrayList; 252be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.Collections; 260fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaokaimport java.util.Comparator; 272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaokaimport java.util.HashMap; 28d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaokaimport java.util.Locale; 29465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaokaimport java.util.TreeMap; 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 35e5320c1d1fb31c570841f656941758e5f064b896Tadashi G. Takaoka private static final String JAVA_TEMPLATE = "KeyboardTextsTable.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@"; 396bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka private static final String TEXTS_ARRAY_NAME_PREFIX = "TEXTS_"; 406bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka private static final String MARK_LOCALES_AND_TEXTS = "@LOCALES_AND_TEXTS@"; 412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static final String EMPTY_STRING_VAR = "EMPTY"; 422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 432be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private final JarFile mJar; 44465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka // String resources maps sorted by its language. The language is determined from the jar entry 456bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka // name by calling {@link JarUtils#getLocaleFromEntryName(String)}. 46a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka private final TreeMap<String, StringResourceMap> mResourcesMap = new TreeMap<>(); 470fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Default string resources map. 480fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka private final StringResourceMap mDefaultResourceMap; 490fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Histogram of string resource names. This is used to sort {@link #mSortedResourceNames}. 50a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka private final HashMap<String, Integer> mNameHistogram = new HashMap<>(); 510fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Sorted string resource names array; Descending order of histogram count. 520fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // The string resource name is specified as an attribute "name" in string resource files. 530fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // The string resource can be accessed by specifying name "!text/<name>" 540fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // via {@link KeyboardTextsSet#getText(String)}. 550fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka private final String[] mSortedResourceNames; 562be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 572be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public MoreKeysResources(final JarFile jar) { 582be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka mJar = jar; 59465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final ArrayList<String> resourceEntryNames = JarUtils.getEntryNameListing( 60465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka jar, TEXT_RESOURCE_NAME); 61465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka for (final String entryName : resourceEntryNames) { 62465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final StringResourceMap resMap = new StringResourceMap(entryName); 63d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka mResourcesMap.put(LocaleUtils.getLocaleCode(resMap.mLocale), resMap); 642be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 65d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka mDefaultResourceMap = mResourcesMap.get( 66d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka LocaleUtils.getLocaleCode(LocaleUtils.DEFAULT_LOCALE)); 670fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka 680fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Initialize name histogram and names list. 690fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final HashMap<String, Integer> nameHistogram = mNameHistogram; 70a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka final ArrayList<String> resourceNamesList = new ArrayList<>(); 710fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka for (final StringResource res : mDefaultResourceMap.getResources()) { 720fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka nameHistogram.put(res.mName, 0); // Initialize histogram value. 730fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka resourceNamesList.add(res.mName); 740fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka } 750fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Make name histogram. 766bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka for (final String locale : mResourcesMap.keySet()) { 776bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka final StringResourceMap resMap = mResourcesMap.get(locale); 780fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka if (resMap == mDefaultResourceMap) continue; 790fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka for (final StringResource res : resMap.getResources()) { 800fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka if (!mDefaultResourceMap.contains(res.mName)) { 816bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka throw new RuntimeException(res.mName + " in " + locale 820fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka + " doesn't have default resource"); 830fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka } 840fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int histogramValue = nameHistogram.get(res.mName); 850fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka nameHistogram.put(res.mName, histogramValue + 1); 860fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka } 870fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka } 880fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Sort names list. 890fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka Collections.sort(resourceNamesList, new Comparator<String>() { 900fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka @Override 910fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka public int compare(final String leftName, final String rightName) { 920fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int leftCount = nameHistogram.get(leftName); 930fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int rightCount = nameHistogram.get(rightName); 940fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // Descending order of histogram count. 950fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka if (leftCount > rightCount) return -1; 960fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka if (leftCount < rightCount) return 1; 970fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // TODO: Add further criteria to order the same histogram value names to be able to 980fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // minimize footprints of string resources arrays. 990fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka return 0; 1000fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka } 1010fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka }); 1020fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka mSortedResourceNames = resourceNamesList.toArray(new String[resourceNamesList.size()]); 1032be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1042be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1052be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka public void writeToJava(final String outDir) { 106465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka final ArrayList<String> list = JarUtils.getEntryNameListing(mJar, JAVA_TEMPLATE); 1072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (list.isEmpty()) { 1082be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException("Can't find java template " + JAVA_TEMPLATE); 1092fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 1102fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (list.size() > 1) { 1112be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException("Found multiple java template " + JAVA_TEMPLATE); 1122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 1132be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String template = list.get(0); 1142be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String javaPackage = template.substring(0, template.lastIndexOf('/')); 1152be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka PrintStream ps = null; 1162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka LineNumberReader lnr = null; 1172be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka try { 1182be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (outDir == null) { 1192be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka ps = System.out; 1202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 1212be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final File outPackage = new File(outDir, javaPackage); 1222be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final File outputFile = new File(outPackage, 1232be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka JAVA_TEMPLATE.replace(".tmpl", ".java")); 1242be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka outPackage.mkdirs(); 1259c9802e6473e5e2e2b792d5f14502139feb49637Tadashi G. Takaoka ps = new PrintStream(outputFile, "UTF-8"); 1262be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka lnr = new LineNumberReader(new InputStreamReader(JarUtils.openResource(template))); 1282be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka inflateTemplate(lnr, ps); 1292be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } catch (IOException e) { 1302be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throw new RuntimeException(e); 1312be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } finally { 132465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka JarUtils.close(lnr); 133465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka JarUtils.close(ps); 1342be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1352be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1362be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1372be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private void inflateTemplate(final LineNumberReader in, final PrintStream out) 1382be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka throws IOException { 1392be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka String line; 1402be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka while ((line = in.readLine()) != null) { 1412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (line.contains(MARK_NAMES)) { 1422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka dumpNames(out); 1436bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka } else if (line.contains(MARK_DEFAULT_TEXTS)) { 1446bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka dumpDefaultTexts(out); 1456bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka } else if (line.contains(MARK_TEXTS)) { 1466bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka dumpTexts(out); 1476bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka } else if (line.contains(MARK_LOCALES_AND_TEXTS)) { 1486bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka dumpLocalesMap(out); 1492be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 1502be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.println(line); 1512be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1522be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1532be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1542be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1552be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private void dumpNames(final PrintStream out) { 1560fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int namesCount = mSortedResourceNames.length; 1570fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka for (int index = 0; index < namesCount; index++) { 1580fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final String name = mSortedResourceNames[index]; 1590fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int histogramValue = mNameHistogram.get(name); 1600fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka out.format(" /* %3d:%2d */ \"%s\",\n", index, histogramValue, name); 1612be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1622be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1632be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1646bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private void dumpDefaultTexts(final PrintStream out) { 1650fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int outputArraySize = dumpTextsInternal(out, mDefaultResourceMap); 1660fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka mDefaultResourceMap.setOutputArraySize(outputArraySize); 167ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka } 168ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka 169d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka private static String getArrayNameForLocale(final Locale locale) { 170d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka return TEXTS_ARRAY_NAME_PREFIX + LocaleUtils.getLocaleCode(locale); 1712be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1722be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1736bfd5f631908c4afd893c9b25b353e5e16c5fc0cTadashi G. Takaoka private void dumpTexts(final PrintStream out) { 174465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka for (final StringResourceMap resMap : mResourcesMap.values()) { 175d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka final Locale locale = resMap.mLocale; 1760fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka if (resMap == mDefaultResourceMap) continue; 1776bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka out.format(" /* Locale %s: %s */\n", 1786bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka locale, LocaleUtils.getLocaleDisplayName(locale)); 1796bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka out.format(" private static final String[] " + getArrayNameForLocale(locale) 180ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka + " = {\n"); 1810fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int outputArraySize = dumpTextsInternal(out, resMap); 182ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka resMap.setOutputArraySize(outputArraySize); 1832be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka out.format(" };\n\n"); 1842be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1852be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1862be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 1876bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka private void dumpLocalesMap(final PrintStream out) { 188465a2ac534bf5c0dea38608dbe713ed3a9dc84ebTadashi G. Takaoka for (final StringResourceMap resMap : mResourcesMap.values()) { 189d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka final Locale locale = resMap.mLocale; 190d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka final String localeStr = LocaleUtils.getLocaleCode(locale); 191d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka final String localeToDump = (locale == LocaleUtils.DEFAULT_LOCALE) 192d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka ? String.format("\"%s\"", localeStr) 193d317796207d9c9443669ff94aac63c4193ec0e6fTadashi G. Takaoka : String.format("\"%s\"%s", localeStr, " ".substring(localeStr.length())); 1946bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka out.format(" %s, %-12s /* %3d/%3d %s */\n", 1956bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka localeToDump, getArrayNameForLocale(locale) + ",", 196ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka resMap.getResources().size(), resMap.getOutputArraySize(), 1976bb3556ff7b24a5a38d7cc4276017bda3a9a4bbaTadashi G. Takaoka LocaleUtils.getLocaleDisplayName(locale)); 1982be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 1992be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2002be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2010fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka private int dumpTextsInternal(final PrintStream out, final StringResourceMap resMap) { 2022be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final ArrayInitializerFormatter formatter = 2030fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka new ArrayInitializerFormatter(out, 100, " ", mSortedResourceNames); 204ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka int outputArraySize = 0; 2052be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka boolean successiveNull = false; 2060fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final int namesCount = mSortedResourceNames.length; 2070fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka for (int index = 0; index < namesCount; index++) { 2080fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final String name = mSortedResourceNames[index]; 2090fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka final StringResource res = resMap.get(name); 2100fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka if (res != null) { 2110fe4d00068fb9ea85bfab083aa595082dd24e59cTadashi G. Takaoka // TODO: Check whether the resource value is equal to the default. 2122be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (res.mComment != null) { 2132be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outCommentLines(addPrefix(" // ", res. mComment)); 2142be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2152be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final String escaped = escapeNonAscii(res.mValue); 2162be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (escaped.length() == 0) { 2172be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outElement(EMPTY_STRING_VAR + ","); 2182be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 2192be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outElement(String.format("\"%s\",", escaped)); 2202be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2212be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka successiveNull = false; 222ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka outputArraySize = formatter.getCurrentIndex(); 2232be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 2242be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.outElement("null,"); 2252be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka successiveNull = true; 2262be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2272be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2282be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (!successiveNull) { 2292be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka formatter.flush(); 2302be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 231ed509695a42455874aa9c047ed4343f636ef527bTadashi G. Takaoka return outputArraySize; 2322be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2332be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2342be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String addPrefix(final String prefix, final String lines) { 2352be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringBuilder sb = new StringBuilder(); 2362be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (final String line : lines.split("\n")) { 2372be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka sb.append(prefix + line.trim() + "\n"); 2382be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2392be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka return sb.toString(); 2402be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2412be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka 2422be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka private static String escapeNonAscii(final String text) { 2432be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final StringBuilder sb = new StringBuilder(); 2442be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final int length = text.length(); 2452be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka for (int i = 0; i < length; i++) { 2462be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka final char c = text.charAt(i); 2472be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka if (c >= ' ' && c < 0x7f) { 2482be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka sb.append(c); 2492be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } else { 2502be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka sb.append(String.format("\\u%04X", (int)c)); 2512be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2522be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 253e422c94634da4d0e61a9106addebf06cbcf70c2eTadashi G. Takaoka return sb.toString(); 2542be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka } 2552be51f4fd0c5cd70c7a2757558ffe45e703700cfTadashi G. Takaoka} 256