Refactor make-keyboard-text

Change-Id: Ifaf955ae896a18e5cbc9c1af5a1b7e15942eb886
This commit is contained in:
Tadashi G. Takaoka 2014-04-08 16:13:40 +09:00
parent 113523d22d
commit 465a2ac534
4 changed files with 79 additions and 75 deletions

View file

@ -16,6 +16,7 @@
package com.android.inputmethod.keyboard.tools; package com.android.inputmethod.keyboard.tools;
import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -58,7 +59,7 @@ public final class JarUtils {
public boolean accept(String dirName, String name); public boolean accept(String dirName, String name);
} }
public static ArrayList<String> getNameListing(final JarFile jar, final JarFilter filter) { public static ArrayList<String> getEntryNameListing(final JarFile jar, final JarFilter filter) {
final ArrayList<String> result = new ArrayList<String>(); final ArrayList<String> result = new ArrayList<String>();
final Enumeration<JarEntry> entries = jar.entries(); final Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
@ -74,12 +75,42 @@ public final class JarUtils {
return result; return result;
} }
public static ArrayList<String> getNameListing(final JarFile jar, final String filterName) { public static ArrayList<String> getEntryNameListing(final JarFile jar,
return getNameListing(jar, new JarFilter() { final String filterName) {
return getEntryNameListing(jar, new JarFilter() {
@Override @Override
public boolean accept(final String dirName, final String name) { public boolean accept(final String dirName, final String name) {
return name.equals(filterName); return name.equals(filterName);
} }
}); });
} }
// The language is taken from string resource jar entry name (values-<language>/)
// or {@link LocaleUtils#DEFAULT_LANGUAGE_NAME} for the default string resource
// directory (values/).
public static String getLanguageFromEntryName(final String jarEntryName) {
final String dirName = jarEntryName.substring(0, jarEntryName.lastIndexOf('/'));
final int pos = dirName.lastIndexOf('/');
final String parentName = (pos >= 0) ? dirName.substring(pos + 1) : dirName;
final int languagePos = parentName.indexOf('-');
if (languagePos < 0) {
// Default resource name.
return LocaleUtils.DEFAULT_LANGUAGE_NAME;
}
final String language = parentName.substring(languagePos + 1);
final int countryPos = language.indexOf("-r");
if (countryPos < 0) {
return language;
}
return language.replace("-r", "_");
}
public static void close(final Closeable stream) {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
}
}
} }

View file

@ -26,6 +26,10 @@ import java.util.Locale;
* for the make-keyboard-text tool. * for the make-keyboard-text tool.
*/ */
public final class LocaleUtils { public final class LocaleUtils {
public static final String DEFAULT_LANGUAGE_NAME = "DEFAULT";
public static final String NO_LANGUAGE_CODE = "zz";
public static final String NO_LANGUAGE_DISPLAY_NAME = "Alphabet";
private LocaleUtils() { private LocaleUtils() {
// Intentional empty constructor for utility class. // Intentional empty constructor for utility class.
} }
@ -58,4 +62,12 @@ public final class LocaleUtils {
return retval; return retval;
} }
} }
public static String getLanguageDisplayName(final String language) {
if (language.equals(NO_LANGUAGE_CODE)) {
return NO_LANGUAGE_DISPLAY_NAME;
}
final Locale locale = constructLocaleFromString(language);
return locale.getDisplayName(Locale.ENGLISH);
}
} }

View file

@ -16,10 +16,8 @@
package com.android.inputmethod.keyboard.tools; package com.android.inputmethod.keyboard.tools;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.io.PrintStream; import java.io.PrintStream;
@ -28,6 +26,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.TreeMap;
import java.util.jar.JarFile; import java.util.jar.JarFile;
public class MoreKeysResources { public class MoreKeysResources {
@ -38,20 +37,13 @@ public class MoreKeysResources {
private static final String MARK_DEFAULT_TEXTS = "@DEFAULT_TEXTS@"; private static final String MARK_DEFAULT_TEXTS = "@DEFAULT_TEXTS@";
private static final String MARK_TEXTS = "@TEXTS@"; private static final String MARK_TEXTS = "@TEXTS@";
private static final String MARK_LANGUAGES_AND_TEXTS = "@LANGUAGES_AND_TEXTS@"; private static final String MARK_LANGUAGES_AND_TEXTS = "@LANGUAGES_AND_TEXTS@";
private static final String DEFAULT_LANGUAGE_NAME = "DEFAULT";
private static final String EMPTY_STRING_VAR = "EMPTY"; private static final String EMPTY_STRING_VAR = "EMPTY";
private static final String NO_LANGUAGE_CODE = "zz";
private static final String NO_LANGUAGE_DISPLAY_NAME = "Alphabet";
private final JarFile mJar; private final JarFile mJar;
// Language to string resources map. // String resources maps sorted by its language. The language is determined from the jar entry
private final HashMap<String, StringResourceMap> mResourcesMap = // name by calling {@link JarUtils#getLanguegFromEntryName(String)}.
new HashMap<String, StringResourceMap>(); private final TreeMap<String, StringResourceMap> mResourcesMap =
// Sorted languages list. The language is taken from string resource directories new TreeMap<String, StringResourceMap>();
// (values-<language>/) or {@link #DEFAULT_LANGUAGE_NAME} for the default string resource
// directory (values/).
private final ArrayList<String> mSortedLanguagesList = new ArrayList<String>();
// Default string resources map. // Default string resources map.
private final StringResourceMap mDefaultResourceMap; private final StringResourceMap mDefaultResourceMap;
// Histogram of string resource names. This is used to sort {@link #mSortedResourceNames}. // Histogram of string resource names. This is used to sort {@link #mSortedResourceNames}.
@ -64,22 +56,13 @@ public class MoreKeysResources {
public MoreKeysResources(final JarFile jar) { public MoreKeysResources(final JarFile jar) {
mJar = jar; mJar = jar;
final ArrayList<String> resources = JarUtils.getNameListing(jar, TEXT_RESOURCE_NAME); final ArrayList<String> resourceEntryNames = JarUtils.getEntryNameListing(
for (final String name : resources) { jar, TEXT_RESOURCE_NAME);
final String dirName = name.substring(0, name.lastIndexOf('/')); for (final String entryName : resourceEntryNames) {
final int pos = dirName.lastIndexOf('/'); final StringResourceMap resMap = new StringResourceMap(entryName);
final String parentName = (pos >= 0) ? dirName.substring(pos + 1) : dirName; mResourcesMap.put(resMap.mLanguage, resMap);
final String language = getLanguageFromResDir(parentName);
final InputStream stream = JarUtils.openResource(name);
try {
mResourcesMap.put(language, new StringResourceMap(stream));
} finally {
close(stream);
}
} }
mDefaultResourceMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME); mDefaultResourceMap = mResourcesMap.get(LocaleUtils.DEFAULT_LANGUAGE_NAME);
mSortedLanguagesList.addAll(mResourcesMap.keySet());
Collections.sort(mSortedLanguagesList);
// Initialize name histogram and names list. // Initialize name histogram and names list.
final HashMap<String, Integer> nameHistogram = mNameHistogram; final HashMap<String, Integer> nameHistogram = mNameHistogram;
@ -118,22 +101,8 @@ public class MoreKeysResources {
mSortedResourceNames = resourceNamesList.toArray(new String[resourceNamesList.size()]); mSortedResourceNames = resourceNamesList.toArray(new String[resourceNamesList.size()]);
} }
private static String getLanguageFromResDir(final String dirName) {
final int languagePos = dirName.indexOf('-');
if (languagePos < 0) {
// Default resource.
return DEFAULT_LANGUAGE_NAME;
}
final String language = dirName.substring(languagePos + 1);
final int countryPos = language.indexOf("-r");
if (countryPos < 0) {
return language;
}
return language.replace("-r", "_");
}
public void writeToJava(final String outDir) { public void writeToJava(final String outDir) {
final ArrayList<String> list = JarUtils.getNameListing(mJar, JAVA_TEMPLATE); final ArrayList<String> list = JarUtils.getEntryNameListing(mJar, JAVA_TEMPLATE);
if (list.isEmpty()) { if (list.isEmpty()) {
throw new RuntimeException("Can't find java template " + JAVA_TEMPLATE); throw new RuntimeException("Can't find java template " + JAVA_TEMPLATE);
} }
@ -159,8 +128,8 @@ public class MoreKeysResources {
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} finally { } finally {
close(lnr); JarUtils.close(lnr);
close(ps); JarUtils.close(ps);
} }
} }
@ -201,10 +170,11 @@ public class MoreKeysResources {
} }
private void dumpTexts(final PrintStream out) { private void dumpTexts(final PrintStream out) {
for (final String language : mSortedLanguagesList) { for (final StringResourceMap resMap : mResourcesMap.values()) {
final StringResourceMap resMap = mResourcesMap.get(language); final String language = resMap.mLanguage;
if (resMap == mDefaultResourceMap) continue; if (resMap == mDefaultResourceMap) continue;
out.format(" /* Language %s: %s */\n", language, getLanguageDisplayName(language)); out.format(" /* Language %s: %s */\n",
language, LocaleUtils.getLanguageDisplayName(language));
out.format(" private static final String[] " + getArrayNameForLanguage(language) out.format(" private static final String[] " + getArrayNameForLanguage(language)
+ " = {\n"); + " = {\n");
final int outputArraySize = dumpTextsInternal(out, resMap); final int outputArraySize = dumpTextsInternal(out, resMap);
@ -214,8 +184,8 @@ public class MoreKeysResources {
} }
private void dumpLanguageMap(final PrintStream out) { private void dumpLanguageMap(final PrintStream out) {
for (final String language : mSortedLanguagesList) { for (final StringResourceMap resMap : mResourcesMap.values()) {
final StringResourceMap resMap = mResourcesMap.get(language); final String language = resMap.mLanguage;
final Locale locale = LocaleUtils.constructLocaleFromString(language); final Locale locale = LocaleUtils.constructLocaleFromString(language);
final String languageKeyToDump = locale.getCountry().isEmpty() final String languageKeyToDump = locale.getCountry().isEmpty()
? String.format("\"%s\"", language) ? String.format("\"%s\"", language)
@ -223,18 +193,10 @@ public class MoreKeysResources {
out.format(" %s, %-15s /* %3d/%3d %s */\n", out.format(" %s, %-15s /* %3d/%3d %s */\n",
languageKeyToDump, getArrayNameForLanguage(language) + ",", languageKeyToDump, getArrayNameForLanguage(language) + ",",
resMap.getResources().size(), resMap.getOutputArraySize(), resMap.getResources().size(), resMap.getOutputArraySize(),
getLanguageDisplayName(language)); LocaleUtils.getLanguageDisplayName(language));
} }
} }
private static String getLanguageDisplayName(final String language) {
final Locale locale = LocaleUtils.constructLocaleFromString(language);
if (locale.getLanguage().equals(NO_LANGUAGE_CODE)) {
return NO_LANGUAGE_DISPLAY_NAME;
}
return locale.getDisplayName(Locale.ENGLISH);
}
private int dumpTextsInternal(final PrintStream out, final StringResourceMap resMap) { private int dumpTextsInternal(final PrintStream out, final StringResourceMap resMap) {
final ArrayInitializerFormatter formatter = final ArrayInitializerFormatter formatter =
new ArrayInitializerFormatter(out, 100, " ", mSortedResourceNames); new ArrayInitializerFormatter(out, 100, " ", mSortedResourceNames);
@ -289,13 +251,4 @@ public class MoreKeysResources {
} }
return sb.toString(); return sb.toString();
} }
private static void close(final Closeable stream) {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
}
}
} }

View file

@ -34,6 +34,8 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParserFactory;
public class StringResourceMap { public class StringResourceMap {
// Lanugage name.
public final String mLanguage;
// String resource list. // String resource list.
private final List<StringResource> mResources; private final List<StringResource> mResources;
// Name to string resource map. // Name to string resource map.
@ -45,22 +47,28 @@ public class StringResourceMap {
// {@link MoreKeysResources#dumpLanguageMap(OutputStream)} via {@link #getOutputArraySize()}. // {@link MoreKeysResources#dumpLanguageMap(OutputStream)} via {@link #getOutputArraySize()}.
private int mOutputArraySize; private int mOutputArraySize;
public StringResourceMap(final InputStream is) { public StringResourceMap(final String jarEntryName) {
mLanguage = JarUtils.getLanguageFromEntryName(jarEntryName);
final StringResourceHandler handler = new StringResourceHandler(); final StringResourceHandler handler = new StringResourceHandler();
final SAXParserFactory factory = SAXParserFactory.newInstance(); final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true); factory.setNamespaceAware(true);
final InputStream stream = JarUtils.openResource(jarEntryName);
try { try {
final SAXParser parser = factory.newSAXParser(); final SAXParser parser = factory.newSAXParser();
// In order to get comment tag. // In order to get comment tag.
parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
parser.parse(is, handler); parser.parse(stream, handler);
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (SAXParseException e) { } catch (SAXParseException e) {
throw new RuntimeException(e.getMessage() + " at line " + e.getLineNumber() throw new RuntimeException(e.getMessage() + " at line " + e.getLineNumber()
+ ", column " + e.getColumnNumber()); + ", column " + e.getColumnNumber(), e);
} catch (SAXException e) { } catch (SAXException e) {
throw new RuntimeException(e.getMessage()); throw new RuntimeException(e.getMessage(), e);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
JarUtils.close(stream);
} }
mResources = Collections.unmodifiableList(handler.mResources); mResources = Collections.unmodifiableList(handler.mResources);