blob: e49bbf4eb81db4495b07e6b92757630dc3cdc4d2 [file] [log] [blame]
/*
* Copyright 2008 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.i18n.rebind;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.i18n.client.impl.LocaleInfoImpl;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import org.apache.tapestry.util.text.LocalizedProperties;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
/**
* Generator used to generate an implementation of the LocaleInfoImpl class,
* which is used by the LocaleInfo class.
*/
public class LocaleInfoGenerator extends Generator {
/**
* Properties file containing machine-generated locale display names, in
* their native locales (if possible).
*/
private static final String GENERATED_LOCALE_NATIVE_DISPLAY_NAMES =
"com/google/gwt/i18n/client/impl/cldr/LocaleNativeDisplayNames-generated.properties";
/**
* Properties file containing hand-made corrections to the machine-generated
* locale display names above.
*/
private static final String MANUAL_LOCALE_NATIVE_DISPLAY_NAMES =
"com/google/gwt/i18n/client/impl/cldr/LocaleNativeDisplayNames-manual.properties";
/**
* Properties file containing hand-made overrides of locale display names,
* in their native locales (if possible).
*/
private static final String OVERRIDE_LOCALE_NATIVE_DISPLAY_NAMES =
"com/google/gwt/i18n/client/impl/cldr/LocaleNativeDisplayNames-override.properties";
/**
* The token representing the locale property controlling Localization.
*/
private static final String PROP_LOCALE = "locale";
/**
* Generate an implementation for the given type.
*
* @param logger error logger
* @param context generator context
* @param typeName target type name
* @return generated class name
* @throws UnableToCompleteException
*/
@Override
public final String generate(TreeLogger logger, GeneratorContext context,
String typeName) throws UnableToCompleteException {
TypeOracle typeOracle = context.getTypeOracle();
// Get the current locale and interface type.
PropertyOracle propertyOracle = context.getPropertyOracle();
String locale = null;
String[] localeValues = null;
try {
locale = propertyOracle.getPropertyValue(logger, PROP_LOCALE);
localeValues = propertyOracle.getPropertyValueSet(logger, PROP_LOCALE);
} catch (BadPropertyValueException e) {
logger.log(TreeLogger.TRACE, "LocaleInfo used without I18N module, using defaults", e);
return LocaleInfoImpl.class.getName();
}
JClassType targetClass;
try {
targetClass = typeOracle.getType(typeName);
} catch (NotFoundException e) {
logger.log(TreeLogger.ERROR, "No such type", e);
throw new UnableToCompleteException();
}
assert (LocaleInfoImpl.class.getName().equals(targetClass.getQualifiedSourceName()));
String packageName = targetClass.getPackage().getName();
String className = targetClass.getName().replace('.', '_') + "_";
if (!locale.equals("default")) {
className += locale;
}
String qualName = packageName + "." + className;
PrintWriter pw = context.tryCreate(logger, packageName, className);
if (pw != null) {
ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
packageName, className);
factory.setSuperclass(targetClass.getQualifiedSourceName());
factory.addImport("com.google.gwt.core.client.JavaScriptObject");
SourceWriter writer = factory.createSourceWriter(context, pw);
writer.println("private JavaScriptObject nativeDisplayNames;");
writer.println();
writer.println("public String[] getAvailableLocaleNames() {");
writer.println(" return new String[] {");
for (String propval : localeValues) {
writer.println(" \"" + propval.replaceAll("\"", "\\\"") + "\",");
}
writer.println(" };");
writer.println("}");
writer.println();
writer.println("public String getLocaleName() {");
writer.println(" return \"" + locale + "\";");
writer.println("}");
writer.println();
writer.println("public native String getLocaleNativeDisplayName(String localeName) /*-{");
writer.println(" this.@" + qualName + "::ensureNativeDisplayNames()();");
writer.println(" return this.@" + qualName + "::nativeDisplayNames[localeName];");
writer.println("}-*/;");
writer.println();
writer.println("private native void ensureNativeDisplayNames() /*-{");
writer.println(" if (this.@" + qualName + "::nativeDisplayNames != null) {");
writer.println(" return;");
writer.println(" }");
writer.println(" this.@" + qualName + "::nativeDisplayNames = {");
LocalizedProperties displayNames = new LocalizedProperties();
LocalizedProperties displayNamesManual = new LocalizedProperties();
LocalizedProperties displayNamesOverride = new LocalizedProperties();
ClassLoader classLoader = getClass().getClassLoader();
try {
InputStream str = classLoader.getResourceAsStream(GENERATED_LOCALE_NATIVE_DISPLAY_NAMES);
if (str != null) {
displayNames.load(str, "UTF-8");
}
str = classLoader.getResourceAsStream(MANUAL_LOCALE_NATIVE_DISPLAY_NAMES);
if (str != null) {
displayNamesManual.load(str, "UTF-8");
}
str = classLoader.getResourceAsStream(OVERRIDE_LOCALE_NATIVE_DISPLAY_NAMES);
if (str != null) {
displayNamesOverride.load(str, "UTF-8");
}
} catch (UnsupportedEncodingException e) {
// UTF-8 should always be defined
logger.log(TreeLogger.ERROR, "UTF-8 encoding is not defined", e);
throw new UnableToCompleteException();
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Exception reading locale display names", e);
throw new UnableToCompleteException();
}
boolean needComma = false;
for (String propval : localeValues) {
String displayName = displayNamesOverride.getProperty(propval);
if (displayName == null) {
displayName = displayNamesManual.getProperty(propval);
}
if (displayName == null) {
displayName = displayNames.getProperty(propval);
}
if (displayName != null && displayName.length() != 0) {
propval.replace("\"", "\\\"");
displayName.replace("\"", "\\\"");
if (needComma) {
writer.println(",");
}
writer.print(" \"" + propval + "\": \"" + displayName + "\"");
needComma = true;
}
}
if (needComma) {
writer.println();
}
writer.println(" };");
writer.println("}-*/;");
writer.commit(logger);
}
return packageName + "." + className;
}
}