/**
  * Writes a loadNamesMapJava method for the current locale, based on its the supplied names map
  * and its superclass (if any).
  *
  * <p>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<String, CurrencyInfo> 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<String, String> loadNamesMapJava() {");
         writer.indent();
         writer.println("HashMap<String, String> 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).
  *
  * <p>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<String, CurrencyInfo> 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("}-*/;");
   }
 }
 /**
  * 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<String, CurrencyInfo> 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;
 }