| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.tools.cldr; |
| |
| import com.google.gwt.codegen.server.AbortablePrintWriter; |
| import com.google.gwt.codegen.server.JavaSourceWriterBuilder; |
| import com.google.gwt.codegen.server.LoggingCodeGenContext; |
| import com.google.gwt.i18n.shared.GwtLocale; |
| |
| import org.unicode.cldr.util.CLDRFile; |
| |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Base class for CLDR processors that generate GWT i18n resources. |
| */ |
| public abstract class Processor { |
| |
| /** |
| * A CodeGenContext implementation that logs to j.u.logging and creates |
| * output files using {@link Processor#createOutputFile(String, String)}. |
| */ |
| protected class ProcessorCodeGenContext extends LoggingCodeGenContext { |
| @Override |
| public JavaSourceWriterBuilder addClass(String superPkg, String pkgName, String className) { |
| String pkgPath = superPkg == null ? pkgName : superPkg + '/' + pkgName; |
| if (pkgPath.length() > 0) { |
| pkgPath = pkgPath.replace('.', '/') + '/'; |
| } |
| String classPath = className.replace('.', '_'); |
| String fileName = pkgPath + classPath + ".java"; |
| try { |
| PrintWriter pw = createOutputFile("", fileName); |
| AbortablePrintWriter apw = new AbortablePrintWriter(pw); |
| printHeader(apw); |
| return new JavaSourceWriterBuilder(apw, pkgName, className); |
| } catch (FileNotFoundException e) { |
| error("Unable to create " + fileName, e); |
| return null; |
| } catch (IOException e) { |
| error("Unable to create " + fileName, e); |
| return null; |
| } |
| } |
| } |
| |
| protected static final String I18N_PACKAGE_PATH = "user/src/com/google/gwt/i18n/"; |
| |
| protected static <T> String join(String joiner, Iterable<T> objects) { |
| StringBuilder buf = new StringBuilder(); |
| for (Object obj : objects) { |
| if (buf.length() > 0) { |
| buf.append(joiner); |
| } |
| buf.append(obj.toString()); |
| } |
| return buf.toString(); |
| } |
| |
| protected static String localeSuffix(GwtLocale locale) { |
| return (locale.isDefault() ? "" : "_") + locale.getAsString(); |
| } |
| |
| /** |
| * @param value |
| * @return value with all quotes escaped |
| */ |
| protected static String quote(String value) { |
| return value.replace("\"", "\\\""); |
| } |
| |
| protected final InputFactory cldrFactory; |
| |
| protected final LocaleData localeData; |
| |
| protected final File outputDir; |
| |
| private boolean useOverride; |
| |
| /** |
| * Initialize the shared portion of a Processor. |
| * |
| * @param outputDir output directory for created files |
| * @param cldrFactory CLDR factory used to create new CLDRFile instances |
| * @param localeData LocaleData instance to collect data from CLDR files |
| */ |
| protected Processor(File outputDir, InputFactory cldrFactory, LocaleData localeData) { |
| this.outputDir = outputDir; |
| this.cldrFactory = cldrFactory; |
| this.localeData = localeData; |
| useOverride = true; |
| } |
| |
| /** |
| * Execute this processor. |
| * |
| * It will call loadData, cleanupData, writeOutputFiles, and then reset on its |
| * localeData instance. |
| * |
| * @throws IOException |
| */ |
| public final void run() throws IOException { |
| try { |
| loadData(); |
| cleanupData(); |
| writeOutputFiles(); |
| } finally { |
| localeData.reset(); |
| } |
| } |
| |
| /** |
| * Override hook for subclasses to implement any cleanup needed, such as |
| * removing values which duplicate those from ancestors. |
| */ |
| protected void cleanupData() { |
| // do nothing by default |
| } |
| |
| protected PrintWriter createOutputFile(String suffix) throws IOException, FileNotFoundException { |
| return createOutputFile(I18N_PACKAGE_PATH, suffix); |
| } |
| |
| protected PrintWriter createOutputFile(String prefix, String suffix) throws IOException, |
| FileNotFoundException { |
| PrintWriter pw; |
| File f = new File(outputDir, prefix + suffix); |
| File parent = f.getParentFile(); |
| if (parent != null) { |
| parent.mkdirs(); |
| } |
| f.createNewFile(); |
| pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), |
| "UTF-8")), false); |
| return pw; |
| } |
| |
| protected void generateIntMethod(PrintWriter pw, String category, GwtLocale locale, String key, |
| String method) { |
| String value = localeData.getEntry(category, locale, key); |
| if (value != null) { |
| pw.println(); |
| if (useOverride) { |
| pw.println(" @Override"); |
| } |
| pw.println(" public int " + method + "() {"); |
| pw.println(" return " + value + ";"); |
| pw.println(" }"); |
| } |
| } |
| |
| protected void generateStringMethod(PrintWriter pw, String category, GwtLocale locale, |
| String key, String method) { |
| String value = localeData.getEntry(category, locale, key); |
| generateStringValue(pw, method, value); |
| } |
| |
| protected void generateStringValue(PrintWriter pw, String method, String value) { |
| if (value != null) { |
| pw.println(); |
| if (useOverride) { |
| pw.println(" @Override"); |
| } |
| pw.println(" public String " + method + "() {"); |
| pw.println(" return \"" + quote(value) + "\";"); |
| pw.println(" }"); |
| } |
| } |
| |
| /** |
| * @return true if generated methods should use @Override. |
| */ |
| protected boolean getOverrides() { |
| return useOverride; |
| } |
| |
| /** |
| * Load data needed by this processor. |
| * |
| * @throws IOException |
| */ |
| protected abstract void loadData() throws IOException; |
| |
| protected void printHeader(PrintWriter pw) { |
| printJavaHeader(pw); |
| } |
| |
| protected void printJavaHeader(PrintWriter pw) { |
| int year = 2012; |
| pw.println("/*"); |
| pw.println(" * Copyright " + year + " Google Inc."); |
| pw.println(" * "); |
| pw.println(" * Licensed under the Apache License, Version 2.0 (the " |
| + "\"License\"); you may not"); |
| pw.println(" * use this file except in compliance with the License. You " |
| + "may obtain a copy of"); |
| pw.println(" * the License at"); |
| pw.println(" * "); |
| pw.println(" * http://www.apache.org/licenses/LICENSE-2.0"); |
| pw.println(" * "); |
| pw.println(" * Unless required by applicable law or agreed to in writing, " + "software"); |
| pw.println(" * distributed under the License is distributed on an \"AS " |
| + "IS\" BASIS, WITHOUT"); |
| pw.println(" * WARRANTIES OR CONDITIONS OF ANY KIND, either express or " + "implied. See the"); |
| pw.println(" * License for the specific language governing permissions and " |
| + "limitations under"); |
| pw.println(" * the License."); |
| pw.println(" */"); |
| } |
| |
| protected void printPropertiesHeader(PrintWriter pw) { |
| int year = 2012; |
| pw.println("# Copyright " + year + " Google Inc."); |
| pw.println("# "); |
| pw.println("# Licensed under the Apache License, Version 2.0 (the " |
| + "\"License\"); you may not"); |
| pw.println("# use this file except in compliance with the License. You " |
| + "may obtain a copy of"); |
| pw.println("# the License at"); |
| pw.println("# "); |
| pw.println("# http://www.apache.org/licenses/LICENSE-2.0"); |
| pw.println("# "); |
| pw.println("# Unless required by applicable law or agreed to in writing, " + "software"); |
| pw.println("# distributed under the License is distributed on an \"AS " |
| + "IS\" BASIS, WITHOUT"); |
| pw.println("# WARRANTIES OR CONDITIONS OF ANY KIND, either express or " + "implied. See the"); |
| pw.println("# License for the specific language governing permissions and " |
| + "limitations under"); |
| pw.println("# the License."); |
| } |
| |
| protected void printVersion(PrintWriter pw, GwtLocale locale, String prefix) { |
| pw.println(prefix + "DO NOT EDIT - GENERATED FROM CLDR DATA"); |
| } |
| |
| /** |
| * Writes a file containing CLDR version information. |
| * @param path the filename, relative to {@link #I18N_PACKAGE_PATH}. |
| */ |
| protected void writeVersionFile(String path, Set<GwtLocale> locales) throws IOException { |
| Map<String, GwtLocale> byName = new HashMap<String, GwtLocale>(); |
| for (GwtLocale locale : locales) { |
| String name = locale.getAsString(); |
| if (byName.containsKey(name)) { |
| throw new RuntimeException("more than one locale with name: " + name); |
| } |
| byName.put(name, locale); |
| } |
| |
| List<String> names = new ArrayList<String>(byName.keySet()); |
| Collections.sort(names); |
| |
| PrintWriter out = createOutputFile(path); |
| out.println("cldrVersion=" + CLDRFile.GEN_VERSION); |
| out.println(); |
| for (String name : names) { |
| Map<String, String> props = localeData.getEntries("version", byName.get(name)); |
| List<String> keys = new ArrayList<String>(props.keySet()); |
| Collections.sort(keys); |
| for (String key : keys) { |
| if (key.equals("date") || key.equals("type")) { |
| // The date comes from Subversion and depends on the local machine's timezone. |
| // Skip it to make the build deterministic. |
| |
| // There is more than one "type" field and it's not obviously useful. |
| continue; |
| } |
| String value = props.get(key); |
| if (!name.isEmpty()) { |
| key = name + "." + key; |
| } |
| out.println(key + "=" + value); |
| } |
| } |
| out.close(); |
| } |
| |
| /** |
| * Set whether method definitions should use @Override. |
| * |
| * @param useOverride |
| */ |
| protected void setOverrides(boolean useOverride) { |
| this.useOverride = useOverride; |
| } |
| |
| /** |
| * Write output files produced by this processor. |
| * |
| * @throws IOException |
| */ |
| protected abstract void writeOutputFiles() throws IOException; |
| } |