All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.i18n.rebind.CurrencyListGenerator Maven / Gradle / Ivy

There is a newer version: 2.7.0.vaadin7
Show newest version
/*
 * 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.client.JavaScriptObject;
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.CurrencyList;
import com.google.gwt.i18n.client.impl.CurrencyDataImpl;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
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;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Pattern;

/**
 * Generator used to generate a localized version of CurrencyList, which
 * contains the list of currencies (with names, symbols, and other information)
 * localized to the current locale.
 */
public class CurrencyListGenerator extends Generator {

  /**
   * Immutable collection of data about a currency in a locale, built from the
   * CurrencyData and CurrencyExtra properties files.
   */
  private static class CurrencyInfo {

    private static final Pattern SPLIT_VERTICALBAR = Pattern.compile("\\|");

    private final String code;

    private final String displayName;

    private final int flags;

    private final boolean obsolete;

    private final String portableSymbol;

    private String simpleSymbol;

    private final String symbol;

    /**
     * Create an instance.
     * 
     * currencyData format:
     * 
     * 
     *       display name|symbol|decimal digits|not-used-flag
     * 
* *
    *
  • If a symbol is not supplied, the currency code will be used *
  • If # of decimal digits is omitted, 2 is used *
  • If a currency is not generally used, not-used-flag=1 *
  • Trailing empty fields can be omitted *
  • If null, use currencyCode as the display name *
* * extraData format: * *
     *       portable symbol|flags|currency symbol override
     *     flags are space separated list of:
     *       At most one of the following:
     *         SymPrefix     The currency symbol goes before the number,
     *                       regardless of the normal position for this locale.
     *         SymSuffix     The currency symbol goes after the number,
     *                       regardless of the normal position for this locale.
     *
     *       At most one of the following:
     *         ForceSpace    Always add a space between the currency symbol
     *                       and the number.
     *         ForceNoSpace  Never add a space between the currency symbol
     *                       and the number.
     * 
* * @param currencyCode ISO4217 currency code * @param currencyData entry from a CurrencyData properties file * @param extraData entry from a CurrencyExtra properties file * @throws NumberFormatException */ public CurrencyInfo(String currencyCode, String currencyData, String extraData) throws NumberFormatException { code = currencyCode; if (currencyData == null) { currencyData = currencyCode; } String[] currencySplit = SPLIT_VERTICALBAR.split(currencyData); String currencyDisplay = currencySplit[0]; String currencySymbol = null; String simpleCurrencySymbol = null; if (currencySplit.length > 1 && currencySplit[1].length() > 0) { currencySymbol = currencySplit[1]; } int currencyFractionDigits = 2; if (currencySplit.length > 2 && currencySplit[2].length() > 0) { currencyFractionDigits = Integer.valueOf(currencySplit[2]); } boolean currencyObsolete = false; if (currencySplit.length > 3 && currencySplit[3].length() > 0) { currencyObsolete = Integer.valueOf(currencySplit[3]) != 0; } int currencyFlags = currencyFractionDigits; if (currencyObsolete) { currencyFlags |= CurrencyDataImpl.DEPRECATED_FLAG; } String currencyPortableSymbol = ""; if (extraData != null) { // CurrencyExtra contains up to 3 fields separated by | // 0 - portable currency symbol // 1 - space-separated flags regarding currency symbol // positioning/spacing // 2 - override of CLDR-derived currency symbol // 3 - simple currency symbol String[] extraSplit = SPLIT_VERTICALBAR.split(extraData); currencyPortableSymbol = extraSplit[0]; if (extraSplit.length > 1) { if (extraSplit[1].contains("SymPrefix")) { currencyFlags |= CurrencyDataImpl.POS_FIXED_FLAG; } else if (extraSplit[1].contains("SymSuffix")) { currencyFlags |= CurrencyDataImpl.POS_FIXED_FLAG | CurrencyDataImpl.POS_SUFFIX_FLAG; } if (extraSplit[1].contains("ForceSpace")) { currencyFlags |= CurrencyDataImpl.SPACING_FIXED_FLAG | CurrencyDataImpl.SPACE_FORCED_FLAG; } else if (extraSplit[1].contains("ForceNoSpace")) { currencyFlags |= CurrencyDataImpl.SPACING_FIXED_FLAG; } } // If a non-empty override is supplied, use it for the currency // symbol. if (extraSplit.length > 2 && extraSplit[2].length() > 0) { currencySymbol = extraSplit[2]; } // If a non-empty simple symbol is supplied, use it for the currency // symbol. if (extraSplit.length > 3 && extraSplit[3].length() > 0) { simpleCurrencySymbol = extraSplit[3]; } // If we don't have a currency symbol yet, use the portable symbol if // supplied. if (currencySymbol == null && currencyPortableSymbol.length() > 0) { currencySymbol = currencyPortableSymbol; } } // If all else fails, use the currency code as the symbol. if (currencySymbol == null) { currencySymbol = currencyCode; } if (currencyPortableSymbol.length() == 0) { currencyPortableSymbol = currencySymbol; } if (simpleCurrencySymbol == null) { simpleCurrencySymbol = currencySymbol; } displayName = currencyDisplay; symbol = currencySymbol; flags = currencyFlags; portableSymbol = currencyPortableSymbol; simpleSymbol = simpleCurrencySymbol; obsolete = currencyObsolete; } public String getDisplayName() { return displayName; } public String getJava() { StringBuilder buf = new StringBuilder(); buf.append("new CurrencyDataImpl(\"").append(quote(code)).append("\", \""); buf.append(quote(symbol)).append("\", ").append(flags); buf.append(", \"").append(quote(portableSymbol)).append('\"'); buf.append(", \"").append(quote(simpleSymbol)).append('\"'); return buf.append(')').toString(); } public String getJson() { StringBuilder buf = new StringBuilder(); buf.append("[ \"").append(quote(code)).append("\", \""); buf.append(quote(symbol)).append("\", ").append(flags); buf.append(", \"").append(quote(portableSymbol)).append('\"'); buf.append(", \"").append(quote(simpleSymbol)).append('\"'); return buf.append(']').toString(); } } private static final String CURRENCY_DATA = CurrencyDataImpl.class.getCanonicalName(); /** * Prefix for properties files containing CLDR-derived currency data for each * locale. */ private static final String CURRENCY_DATA_PREFIX = "com/google/gwt/i18n/client/impl/cldr/CurrencyData"; /** * Prefix for properties files containing additional flags about currencies * each locale, which are not present in CLDR. */ private static final String CURRENCY_EXTRA_PREFIX = "com/google/gwt/i18n/client/constants/CurrencyExtra"; private static final String CURRENCY_LIST = CurrencyList.class.getCanonicalName(); private static final String HASHMAP = HashMap.class.getCanonicalName(); private static final String JAVASCRIPTOBJECT = JavaScriptObject.class.getCanonicalName(); /** * Prefix for properties files containing number formatting constants for each * locale. We use this only to get the default currency for our current * locale. */ private static final String NUMBER_CONSTANTS_PREFIX = "com/google/gwt/i18n/client/constants/NumberConstantsImpl"; /** * Backslash-escape any double quotes in the supplied string. * * @param str string to quote * @return string with double quotes backslash-escaped. */ private static String quote(String str) { return str.replace("\"", "\\\""); } private static ImmutableSet relevantPropertyNames = ImmutableSet.of("locale.queryparam", "locale", "runtime.locales", "locale.cookie"); /** * 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 { assert CURRENCY_LIST.equals(typeName); TypeOracle typeOracle = context.getTypeOracle(); PropertyOracle propertyOracle = context.getPropertyOracle(); LocaleUtils localeUtils = LocaleUtils.getInstance(logger, propertyOracle, context); GwtLocale locale = localeUtils.getCompileLocale(); Set runtimeLocales = localeUtils.getRuntimeLocales(); JClassType targetClass; try { targetClass = typeOracle.getType(typeName); } catch (NotFoundException e) { logger.log(TreeLogger.ERROR, "No such type", e); throw new UnableToCompleteException(); } if (runtimeLocales.isEmpty()) { return generateLocaleTree(logger, context, targetClass, locale); } CachedGeneratorContext cachedContext = new CachedGeneratorContext(context); return generateRuntimeSelection(logger, cachedContext, targetClass, locale, runtimeLocales); } @Override public Set getAccessedPropertyNames() { return relevantPropertyNames; } @Override public boolean contentDependsOnTypes() { return false; } /** * Generate an implementation class for the requested locale, including all * parent classes along the inheritance chain. The data will be kept at the * location in the inheritance chain where it was defined in properties files. * * @param logger * @param context * @param targetClass * @param locale * @return generated class name for the requested locale */ private String generateLocaleTree(TreeLogger logger, GeneratorContext context, JClassType targetClass, GwtLocale locale) { String superClassName = CURRENCY_LIST; List searchList = locale.getCompleteSearchList(); /** * Map of currency code -> CurrencyInfo for that code. */ Map allCurrencyData = new HashMap(); LocalizedProperties currencyExtra = null; /* * The searchList is guaranteed to be ordered such that subclasses always * precede superclasses. Therefore, we iterate backwards to ensure that * superclasses are always generated first. */ String lastDefaultCurrencyCode = null; for (int i = searchList.size(); i-- > 0;) { GwtLocale search = searchList.get(i); LocalizedProperties newExtra = getProperties(CURRENCY_EXTRA_PREFIX, search); if (newExtra != null) { currencyExtra = newExtra; } Map currencyData = getCurrencyData(search); Set keySet = currencyData.keySet(); String[] currencies = new String[keySet.size()]; keySet.toArray(currencies); Arrays.sort(currencies); // Go ahead and populate the data map. for (String currencyCode : currencies) { String extraData = currencyExtra == null ? null : currencyExtra.getProperty(currencyCode); allCurrencyData.put(currencyCode, new CurrencyInfo(currencyCode, currencyData.get(currencyCode), extraData)); } String defCurrencyCode = getDefaultCurrency(search); // If this locale specifies a particular locale, or the one that is // inherited has been changed in this locale, re-specify the default // currency so the method will be generated. if (defCurrencyCode == null && keySet.contains(lastDefaultCurrencyCode)) { defCurrencyCode = lastDefaultCurrencyCode; } if (!currencyData.isEmpty() || defCurrencyCode != null) { String newClass = generateOneLocale(logger, context, targetClass, search, superClassName, currencies, allCurrencyData, defCurrencyCode); superClassName = newClass; lastDefaultCurrencyCode = defCurrencyCode; } } return superClassName; } /** * Generate the implementation for a single locale, overriding from its parent * only data that has changed in this locale. * * @param logger * @param context * @param targetClass * @param locale * @param superClassName * @param currencies the set of currencies defined in this locale * @param allCurrencyData map of currency code -> unparsed CurrencyInfo for * that code * @param defCurrencyCode default currency code for this locale * @return fully-qualified class name generated */ private String generateOneLocale(TreeLogger logger, GeneratorContext context, JClassType targetClass, GwtLocale locale, String superClassName, String[] currencies, Map allCurrencyData, String defCurrencyCode) { String packageName = targetClass.getPackage().getName(); String className = targetClass.getName().replace('.', '_') + "_" + locale.getAsString(); PrintWriter pw = context.tryCreate(logger, packageName, className); if (pw != null) { ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, className); factory.setSuperclass(superClassName); factory.addImport(CURRENCY_DATA); factory.addImport(JAVASCRIPTOBJECT); factory.addImport(HASHMAP); SourceWriter writer = factory.createSourceWriter(context, pw); if (defCurrencyCode != null) { CurrencyInfo currencyInfo = allCurrencyData.get(defCurrencyCode); if (currencyInfo == null) { // Synthesize a null info if the specified default wasn't found. currencyInfo = new CurrencyInfo(defCurrencyCode, null, null); allCurrencyData.put(defCurrencyCode, currencyInfo); } writer.println(); writer.println("@Override"); writer.println("protected CurrencyData getDefaultJava() {"); writer.println(" return " + currencyInfo.getJava() + ";"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected native CurrencyData getDefaultNative() /*-{"); writer.println(" return " + currencyInfo.getJson() + ";"); writer.println("}-*/;"); } if (currencies.length > 0) { writeCurrencyMethodJava(writer, currencies, allCurrencyData); writeCurrencyMethodNative(writer, currencies, allCurrencyData); writeNamesMethodJava(writer, currencies, allCurrencyData); writeNamesMethodNative(writer, currencies, allCurrencyData); } writer.commit(logger); } return packageName + "." + className; } /** * Generate a class which can select between alternate implementations at * runtime based on the runtime locale. * * @param logger TreeLogger instance for log messages * @param context GeneratorContext for generating source files * @param targetClass class to generate * @param compileLocale the compile-time locale we are generating for * @param locales set of all locales to generate * @return fully-qualified class name that was generated */ private String generateRuntimeSelection(TreeLogger logger, GeneratorContext context, JClassType targetClass, GwtLocale compileLocale, Set locales) { String packageName = targetClass.getPackage().getName(); String className = targetClass.getName().replace('.', '_') + "_" + compileLocale.getAsString() + "_runtimeSelection"; PrintWriter pw = context.tryCreate(logger, packageName, className); if (pw != null) { ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, className); factory.setSuperclass(targetClass.getQualifiedSourceName()); factory.addImport(CURRENCY_DATA); factory.addImport(JAVASCRIPTOBJECT); factory.addImport(HASHMAP); factory.addImport("com.google.gwt.i18n.client.LocaleInfo"); SourceWriter writer = factory.createSourceWriter(context, pw); writer.println("private CurrencyList instance;"); writer.println(); writer.println("@Override"); writer.println("protected CurrencyData getDefaultJava() {"); writer.println(" ensureInstance();"); writer.println(" return instance.getDefaultJava();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected CurrencyData getDefaultNative() {"); writer.println(" ensureInstance();"); writer.println(" return instance.getDefaultNative();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected HashMap loadCurrencyMapJava() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadCurrencyMapJava();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected JavaScriptObject loadCurrencyMapNative() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadCurrencyMapNative();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected HashMap loadNamesMapJava() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadNamesMapJava();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected JavaScriptObject loadNamesMapNative() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadNamesMapNative();"); writer.println("}"); writer.println(); writer.println("private void ensureInstance() {"); writer.indent(); writer.println("if (instance != null) {"); writer.println(" return;"); writer.println("}"); boolean fetchedLocale = false; Map> localeMap = new TreeMap>(); String compileLocaleClass = processChildLocale(logger, context, targetClass, localeMap, compileLocale); if (compileLocaleClass == null) { // already gave warning, just use default implementation return null; } for (GwtLocale runtimeLocale : locales) { processChildLocale(logger, context, targetClass, localeMap, runtimeLocale); } for (Entry> entry : localeMap.entrySet()) { if (!fetchedLocale) { writer.println("String runtimeLocale = LocaleInfo.getCurrentLocale().getLocaleName();"); fetchedLocale = true; } boolean firstLocale = true; String generatedClass = entry.getKey(); if (compileLocaleClass.equals(generatedClass)) { // The catch-all will handle this continue; } writer.print("if ("); for (GwtLocale locale : entry.getValue()) { if (firstLocale) { firstLocale = false; } else { writer.println(); writer.print(" || "); } writer.print("\"" + locale.toString() + "\".equals(runtimeLocale)"); } writer.println(") {"); writer.println(" instance = new " + generatedClass + "();"); writer.println(" return;"); writer.println("}"); } writer.println("instance = new " + compileLocaleClass + "();"); writer.outdent(); writer.println("}"); writer.commit(logger); } return packageName + "." + className; } /** * Return a map of currency data for the requested locale, or null if there is * not one (not that inheritance is not handled here). *

* The keys are ISO4217 currency codes. The format of the map values is: * *

   * display name|symbol|decimal digits|not-used-flag
   * 
* * If a symbol is not supplied, the currency code will be used If # of decimal * digits is omitted, 2 is used If a currency is not generally used, * not-used-flag=1 Trailing empty fields can be omitted * * @param locale * @return currency data map */ @SuppressWarnings("unchecked") private Map getCurrencyData(GwtLocale locale) { LocalizedProperties currencyData = getProperties(CURRENCY_DATA_PREFIX, locale); if (currencyData == null) { return Collections.emptyMap(); } return currencyData.getPropertyMap(); } /** * Returns the default currency code for the requested locale. * * @param locale * @return ISO4217 currency code */ private String getDefaultCurrency(GwtLocale locale) { String defCurrencyCode = null; LocalizedProperties numberConstants = getProperties(NUMBER_CONSTANTS_PREFIX, locale); if (numberConstants != null) { defCurrencyCode = numberConstants.getProperty("defCurrencyCode"); } if (defCurrencyCode == null && locale.isDefault()) { defCurrencyCode = "USD"; } return defCurrencyCode; } /** * Load a properties file for a given locale. Note that locale inheritance is * the responsibility of the caller. * * @param prefix classpath prefix of properties file * @param locale locale to load * @return LocalizedProperties instance containing properties file or null if * not found. */ private LocalizedProperties getProperties(String prefix, GwtLocale locale) { String propFile = prefix; if (!locale.isDefault()) { propFile += "_" + locale.getAsString(); } propFile += ".properties"; InputStream str = null; ClassLoader classLoader = getClass().getClassLoader(); LocalizedProperties props = new LocalizedProperties(); try { str = classLoader.getResourceAsStream(propFile); if (str != null) { props.load(str, "UTF-8"); return props; } } catch (UnsupportedEncodingException e) { // UTF-8 should always be defined return null; } catch (IOException e) { return null; } finally { if (str != null) { try { str.close(); } catch (IOException e) { } } } return null; } /** * Generate an implementation for a runtime locale, to be referenced from the * generated runtime selection code. * * @param logger * @param context * @param targetClass * @param localeMap * @param locale * @return class name of the generated class, or null if failed */ private String processChildLocale(TreeLogger logger, GeneratorContext context, JClassType targetClass, Map> localeMap, GwtLocale locale) { String generatedClass = generateLocaleTree(logger, context, targetClass, locale); if (generatedClass == null) { logger.log(TreeLogger.ERROR, "Failed to generate " + targetClass.getQualifiedSourceName() + " in locale " + locale.toString()); // skip failed locale return null; } Set locales = localeMap.get(generatedClass); if (locales == null) { locales = new HashSet(); localeMap.put(generatedClass, locales); } locales.add(locale); return generatedClass; } /** * Writes a loadCurrencyMapJava method for the current locale, based on its * currency data and its superclass (if any). As currencies are included in * this method, their names are added to {@code nameMap} for later use. * * If no new currency data is added for this locale over its superclass, the * method is omitted entirely. * * @param writer SourceWriter instance to use for writing the class * @param currencies array of valid currency names in the order they should be * listed * @param allCurrencyData map of currency codes to currency data for the * current locale, including all inherited currencies data */ private void writeCurrencyMethodJava(SourceWriter writer, String[] currencies, Map allCurrencyData) { boolean needHeader = true; for (String currencyCode : currencies) { // TODO(jat): only emit new data where it differs from superclass! CurrencyInfo currencyInfo = allCurrencyData.get(currencyCode); if (needHeader) { needHeader = false; writer.println(); writer.println("@Override"); writer.println("protected HashMap loadCurrencyMapJava() {"); writer.indent(); writer.println("HashMap result = super.loadCurrencyMapJava();"); } writer.println("// " + currencyInfo.getDisplayName()); writer.println("result.put(\"" + quote(currencyCode) + "\", " + currencyInfo.getJava() + ");"); } if (!needHeader) { writer.println("return result;"); writer.outdent(); writer.println("}"); } } /** * Writes a loadCurrencyMapNative method for the current locale, based on its * currency data and its superclass (if any). As currencies are included in * this method, their names are added to {@code nameMap} for later use. * * If no new currency data is added for this locale over its superclass, the * method is omitted entirely. * * @param writer SourceWriter instance to use for writing the class * @param currencies array of valid currency names in the order they should be * listed * @param allCurrencyData map of currency codes to currency data for the * current locale, including all inherited currencies data */ private void writeCurrencyMethodNative(SourceWriter writer, String[] currencies, Map allCurrencyData) { boolean needHeader = true; for (String currencyCode : currencies) { // TODO(jat): only emit new data where it differs from superclass! CurrencyInfo currencyInfo = allCurrencyData.get(currencyCode); if (needHeader) { needHeader = false; writer.println(); writer.println("@Override"); writer.println("protected JavaScriptObject loadCurrencyMapNative() {"); writer.indent(); writer.println("return overrideMap(super.loadCurrencyMapNative(), loadMyCurrencyMapOverridesNative());"); writer.outdent(); writer.println("}"); writer.println(); writer.println("private native JavaScriptObject loadMyCurrencyMapOverridesNative() /*-{"); writer.indent(); writer.println("return {"); writer.indent(); } writer.println("// " + currencyInfo.getDisplayName()); writer.println("\"" + quote(currencyCode) + "\": " + currencyInfo.getJson() + ","); } if (!needHeader) { writer.outdent(); writer.println("};"); writer.outdent(); writer.println("}-*/;"); } } /** * Writes a loadNamesMapJava method for the current locale, based on its the * supplied names map and its superclass (if any). * * If no new names are added for this locale over its superclass, the method * is omitted entirely. * * @param writer SourceWriter instance to use for writing the class * @param currencies array of valid currency names in the order they should be * listed * @param allCurrencyData map of currency codes to currency data for the * current locale, including all inherited currencies data */ private void writeNamesMethodJava(SourceWriter writer, String[] currencies, Map allCurrencyData) { boolean needHeader = true; for (String currencyCode : currencies) { // TODO(jat): only emit new data where it differs from superclass! CurrencyInfo currencyInfo = allCurrencyData.get(currencyCode); String displayName = currencyInfo.getDisplayName(); if (displayName != null && !currencyCode.equals(displayName)) { if (needHeader) { needHeader = false; writer.println(); writer.println("@Override"); writer.println("protected HashMap loadNamesMapJava() {"); writer.indent(); writer.println("HashMap result = super.loadNamesMapJava();"); } writer.println("result.put(\"" + quote(currencyCode) + "\", \"" + quote(displayName) + "\");"); } } if (!needHeader) { writer.println("return result;"); writer.outdent(); writer.println("}"); } } /** * Writes a loadNamesMapNative method for the current locale, based on its the * supplied names map and its superclass (if any). * * If no new names are added for this locale over its superclass, the method * is omitted entirely. * * @param writer SourceWriter instance to use for writing the class * @param currencies array of valid currency names in the order they should be * listed * @param allCurrencyData map of currency codes to currency data for the * current locale, including all inherited currencies data */ private void writeNamesMethodNative(SourceWriter writer, String[] currencies, Map allCurrencyData) { boolean needHeader = true; for (String currencyCode : currencies) { // TODO(jat): only emit new data where it differs from superclass! CurrencyInfo currencyInfo = allCurrencyData.get(currencyCode); String displayName = currencyInfo.getDisplayName(); if (displayName != null && !currencyCode.equals(displayName)) { if (needHeader) { needHeader = false; writer.println(); writer.println("@Override"); writer.println("protected JavaScriptObject loadNamesMapNative() {"); writer.indent(); writer.println("return overrideMap(super.loadNamesMapNative(), loadMyNamesMapOverridesNative());"); writer.outdent(); writer.println("}"); writer.println(); writer.println("private native JavaScriptObject loadMyNamesMapOverridesNative() /*-{"); writer.indent(); writer.println("return {"); writer.indent(); } writer.println("\"" + quote(currencyCode) + "\": \"" + quote(displayName) + "\","); } } if (!needHeader) { writer.outdent(); writer.println("};"); writer.outdent(); writer.println("}-*/;"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy