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